http://www.perlmonks.org?node_id=206130

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

Hello,

I have a screen and I want to prompt the users for 1 of 3 choices.
Let's say I have a screen that says:

Choose 1 of the 3 options: 1=Turkey 2=Steak 3=Apple Choose one:
What would be a good method to code this?

Is there a perl CASE statement or am I doing a bunch of if-then statemetents?
i.e. $choice=<STDIN>; if ($choice="1") { $choice="Turkey"; } else choice="2"...etx

Ultimately I am going to have many choices (10-20).
Any suggestions on how to tackle this efficiently?

Thanks,
He who laughs last, doesn't get the joke.

Replies are listed 'Best First'.
Re: STDIN method?
by insensate (Hermit) on Oct 17, 2002 at 20:40 UTC
    I always like using a hash:
    use strict; my %hash=(1=>"Turkey",2=>"Goat",3=>"Fish"); print "choose 1:\n"; for(sort keys %hash){ print "$_=$hash{$_}\n"; } print "Choice: "; my $ans=<STDIN>; chomp $ans; print "Invalid Answer!" unless exists $hash{$ans}; print "You chose $hash{$ans}\n";
    This way you only have to change the hash as your selection alternatives change.
    -Jason
      That makes the most sense to me too. Plus if you need to scale up your switch statement, it's easy with a hash!
      $hash{1} = sub {print "You chose turkey";}; $hash{2} = sub {print "You chose Goat;"; print "..ew";}; for (keys %hash) { &{$hash{$_}}; }
      ..Obviously for just picking what to print, you're making work for yourself, but if you need to accomplish more than that (which is usually the case), it can save time (without a million elsifs cluttering your code).
Re: STDIN method?
by jkahn (Friar) on Oct 17, 2002 at 20:34 UTC
Re: STDIN method?
by janx (Monk) on Oct 17, 2002 at 20:42 UTC
    No, sorry. There is no built-in case/switch statement (yet - in Perl 6 there will be, it's called given).
    If you don't mind source filters though, there is the excellent module Switch.pm by Damian Conway.

    Otherwise you will have to use if/elsif statements.

    Be aware:

    > $choice=<STDIN>; > if ($choice="1") { > $choice="Turkey"; > } > else choice="2"...etx
    = assigns, it does not compare!
    Use eq for string comparison (or == for a numeric one).

    janx

Re: STDIN method?
by jjdraco (Scribe) on Oct 17, 2002 at 20:35 UTC
    there is a perl switch module you can get.
    besides that I think you have to if..elsif..else it

    jjdraco
    learning Perl one statement at a time.
Re: STDIN method?
by Mr. Muskrat (Canon) on Oct 17, 2002 at 21:38 UTC

    In the spirit of TMTOWTDI:

    #!/bin/perl use strict; use warnings; my $choice = 0; my @choices = (undef, "Turkey", "Steak", "Chicken", "Ground Beef", "Ma +shed Potatoes", "Apple Turnover", "Cherry Pie", "Giblet Stuffing", "G +oat Liver", "Goat Cheese", "Head Cheese", "Cheeseburger"); my $num = scalar @choices - 1; print "Choices is $num\n"; while ($choice < 1 or $choice > $num) { print "\nChoose 1 of the $num options:\n"; foreach (1 .. $num) { print "$_ $choices[$_]\n"; } print "\nChoice: "; $choice = <STDIN>; $choice += 0; } print "\nYou choose $choices[$choice].\n";

    Updated: Added more options to better match what vivekvp is going to do with it.
    Also, this is probably not the best way to do it. It was fun to write though. :)

Re: STDIN method?
by Enlil (Parson) on Oct 17, 2002 at 20:40 UTC
    The method I would use:

    Is take just print the menu (using print or printf). And then look have a variable waiting for <STDIN>. After chomping this variable, I would use a lot of if/elsif statements (quick and dirty), or possibly a hash of references to subs to do what I need to be done when a choice has been made. Perl has no CASE or SWITCH statements, but that should not stop you from

    -Enlil

Re: STDIN method?
by tadman (Prior) on Oct 18, 2002 at 07:20 UTC
    Something so simple can't help but be golfed:
    sub f { my$x;my%x=map{++$x,$_}@_;print"Choose 1 of the $x options:\n",(map{"$_ +=$x{$_}\n"}1..@_),"\nChoose one:\n";chomp($_=<>);$x{$_} } print "Response=".p(qw[ Turkey Steak Apple ]),$/;
    You might have to use <STDIN> instead of <> if you have something in @ARGV.