BioGeek has asked for the wisdom of the Perl Monks concerning the following question:

Hey Monks, I wrote a program that asks the user to input a number between 1 and 10. If the user does so, the program will execute and give the results. However, if the user inputs something else, I would like to have my initial question reprinted and the program started again. What's the easiest way to implement this?

Replies are listed 'Best First'.
Re: restart program on wrong user input.
by Aristotle (Chancellor) on Aug 01, 2004 at 19:59 UTC
    You want a postcondition loop.
    my $input; do { print "Please enter a number in the range 1 .. 10: "; chomp( $input = <STDIN> ); } until ( $input !~ /\D/ ) and ( $input >= 1 ) and ( $input <= 10 );
    Perl treats the do {} while $cond construct specially — all other loops in Perl are precondition loops, that is, they check their condition before the body is executed. A do {} while $cond checks its condition after the body is executed. Hence the terms pre- and postcondition.

    Makeshifts last the longest.

Re: restart program on wrong user input.
by b4e (Sexton) on Aug 01, 2004 at 19:48 UTC
    i would go for the while loop :
    $input_var = 0 ; # to get the loop executed at least once while( ($input_var < 1) && ($input_var > 10) ) { print "please input the number ... : "; $input_var = <STDIN>; } # do your stuff with $input_var # output result
Re: restart program on wrong user input.
by ccn (Vicar) on Aug 01, 2004 at 20:01 UTC

    { print "Give me a number:"; $num = <STDIN>; if ($num < 1 or $num > 10) { print "try again\n"; redo; } } print "OK\n";
Re: restart program on wrong user input.
by DigitalKitty (Parson) on Aug 01, 2004 at 23:36 UTC
    Hi BioGeek.

    In the spirit of diversity, I'd like to offer this contribution:
    #!/usr/bin/perl -w use strict; my $num; while() { print 'Enter a number between 1 and 10 (inclusive): '; chomp( $num = <STDIN> ); if( $num gt "9" ) { print "Numbers only. That was a string!\n"; next; } if( $num < 1 || $num > 10 ) { print "Please enter a value greater than one or less than 10\n"; next; } print "Thank you. You entered $num\n"; last; }

    Hope this helps,
      $num gt "9"

      That made me blink for a second before I realized what was going on. Then I noticed you're missing the other half of the condition ($num lt "0").

      You'd do better to check whether non-digits match in $num:

      $num =~ /\D/

      This is self-documenting and complete.

      Makeshifts last the longest.

        Well, now I see why the credo of perl is TIMTOWTDI!

        Thaks to everyone who provided input to this simple newbie question.
Re: restart program on wrong user input.
by graff (Chancellor) on Aug 01, 2004 at 22:17 UTC
    The easiest way to handle getting an input value from the user is to use @ARGV:
    #!/usr/bin/perl use strict; my $Usage = "Usage: $0 N\n where N is a number between 1 and 10\n"; die $Usage unless ( @ARGV == 1 and $ARGV[0] =~ /^\d{1,2}$/ and $ARGV[0] > 0 and $ARGV[0] <= 10 ); # now do whatever you need to do with $ARGV[0]...
    If you're already doing stuff with command-line args that are providing other information for the script, you might consider using Getopt::Std or Getopt::Long.

    Letting the user put the information on the command line is generally easier for both the script writer (less code to write) and the user (better line editing facilities provided by the shell than by the perl script reading from STDIN, plus the ability of running your script non-interactively (e.g. from a cron job or another script). If you want to write more code to provide a better keyboard input facility for the user, you could use ReadLine. Nothing wrong at all with that -- it's excellent when you really need it, e.g. for carrying on indefinite dialogs with users, like the CPAN shell does. But if you're just dealing with something simple that can be fed in from the command line, using @ARGV is much simpler, and simpler is better.

Re: restart program on wrong user input.
by BUU (Prior) on Aug 01, 2004 at 19:38 UTC
    The easiest is probably a goto:
    TOP: my $num = <STDIN>; if( $num != 10 and $num != 0 ) #ok, a horrible condition { goto TOP; } #rest of code
    Other ways would involve possibly a subroutine or hacking about with a while loop:
    my $input; while( $input != "good" ) { print "Please enter number:\n"; $input = <STDIN>; } #rest of code