in reply to catching incorrect input type

A general command line loop can be done like this:
The while() condition issues the prompt and gets what the user says. Then we proceed with more detailed analysis.
- General rules for command input: spaces - leading - trailing don't matter - blank lines don't matter.
- Use a regex to see if all the stuff is there- here if $minute is not defined, that means the regex didn't match - just say: bad format and prompt with the formatting hint - the user will stare at it and figure it out.
-Then start checking each individual thing for a range of "correctness" as far as you can do for one field at a time. Issue error on the first error seen and re-prompt.

Checking user input can get pretty "wordy" - this is one area where the Perl code won't be much shorter than the C code. Don't worry about that. Be logical and straight-forward. Remember that you are parsing something that a person is typing - super efficiency is not required - logical thinking and clarity of the error messages is!

If this winds up being a page of code - don't worry about it - again you are running maybe 10 if statements - speed is not an issue here - clarity is an issue.

#!/usr/bin/perl -w use strict; my $prompt = "Enter the start date (mm/dd/yyyy hh:mm): "; my $line; while ( (print "$prompt"), $line =<STDIN>) { next if $line =~ /^\s*$/; #simple reprompt on blank line my ($month, $day, $year, $hour, $minute) = $line =~ m|^\s*(\d+)/(\d+)/(\d+)\s+(\d+):(\d+)\s*$|; if (!defined $minute) #regex failed initial "laugh test" { print "illegal format!\n"; next; } if ($month <1 or $month>12) { print "got month of $month - must be 1-12\n"; next; } if ($day <1 or $day>31) { print "got day of $day - must be 1-31\n"; next; } # more conditions here #finally try to convert the date to an epoch and see #if that works, eg 2/31/2012 should fail... #all tests pass, you have a "good date time" } __END__ C:\TEMP>commandloop5.pl Enter the start date (mm/dd/yyyy hh:mm): fjfjf 97609876 afadfa illegal format! Enter the start date (mm/dd/yyyy hh:mm): 0/0/2012 99:00 got month of 0 - must be 1-12 Enter the start date (mm/dd/yyyy hh:mm): 1/0/2012 99:00 got day of 0 - must be 1-31 Enter the start date (mm/dd/yyyy hh:mm): I stopped program
I would drop these words like "Please" in the prompt - get to the point - don't be overly polite.
You can use elsif clauses but don't overly worry about efficiency - the whole loop will run much, much faster than the user can even type one character - literally the "enter" key is still moving upwards even after the whole user input has already been validated.

Update: Note that the initial regex is fairly loose:
digit(s)/digit(s)/digit(s)        digit(s):digit(s)
is "close enough" - get the basic syntax in the first regex
apr/2/2012 00:02 is not "close enough".
Once the basic syntax requirements are met, then get into the details of what these various fields mean and what the valid values are for them. I am assuming that you want to be "reasonably" user friendly - and not just "screw you - this isn't exactly what I asked for".

Replies are listed 'Best First'.
Re^2: catching incorrect input type
by zwon (Abbot) on Apr 03, 2012 at 14:27 UTC

    Not really the way to check a date, it's already a lot of code and still far from being correct. Use appropriate module:

    use 5.010; use strict; use warnings; use DateTime::Format::Strptime; my $strp = DateTime::Format::Strptime->new( pattern => '%m/%d/%Y %H:%M +', ); while (<DATA>) { chomp; my $dt = $strp->parse_datetime($_); if ($dt) { say "Parsed: $dt"; } else { say "Invalid date: $_"; } } __DATA__ 2/21/2012 fjfjf 97609876 afadfa 0/0/2012 99:00 1/0/2012 99:00 02/31/2012 01:55 02/21/2012 01:55