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". |