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

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

Hi, I am learning perl and hit a snag! I was hoping someone could help me with this really simple question. I am trying to make a program that takes in a list of numbers as input, and each number represents the corresponding name in my @name array. So if I put in 2 3 4, i should get betty barney dino as my output. But right now I only get fred as my output. It does not run through the entire list! Why is that? Did I code something wrong? Thanks
@names = qw/ fred betty barney dino wilma peblles bamm-bamm /; chomp(@list = <STDIN>); foreach (@list) { print "$names[ $_ - 1 ]\n"; }

Replies are listed 'Best First'.
Re: A simple foreach question
by davido (Cardinal) on Mar 06, 2005 at 06:44 UTC

    It could be how you're entering the numbers. As a simple example of this, try the following:

    chomp( @list = <STDIN> ); print "Item: ", ++$count, ", Value: $_\n" foreach @list;

    If you are hitting 'enter' after each number, your output will look (for example) like this:

    Item: 1, Value: 2 Item: 2, Value: 3 Item: 3, Value: 4

    But if you're just entering each number one after the next, separated by whitespace, and hitting enter at the very end, your output will look like:

    Item: 1, Value: 2 3 4

    Hopefully that illustrates what is going on here. The quick fix is to alter the script to look like this:

    chomp( @input = <STDIN> ); push( @list, split( /\s+/, $_ ) ) foreach @input; foreach ( @list ) { print "$names[$_-1]\n"; }

    Dave

Re: A simple foreach question
by rlb3 (Deacon) on Mar 06, 2005 at 06:43 UTC

    Hello,

    I think your problem is that <STDIN> is not returning an list. It's putting all the values in to $list[0]. I made two changes to your code and it seams to work.

    #!/usr/bin/perl @names = qw/ fred betty barney dino wilma peblles bamm-bamm /; chomp($list = <STDIN>); @list = split /\s+/,$list; foreach (@list) { print "$names[ $_ - 1 ]\n"; }

    Hope this helps.

      I think your problem is that <STDIN> is not returning an list.
      This is not exactly true. <STDIN> does return a list because it is called in list context. The list are the lines of input. For further details, see the other comments.
Re: A simple foreach question
by chas (Priest) on Mar 06, 2005 at 06:43 UTC
    If I run your script and enter 2, 3, and 4 each followed by a return, and then an end of file (e.g.cntrl Z in DOS), I get betty barney and dino. Same result if I put the numbers in a file on distinct lines. However, if you put the list of numbers all on one line they all get read by the diamond operator as a line, and it looks like that string gets interpreted as just a 2 inside the brackets, (I get betty in that case, not fred.)
    chas
Re: A simple foreach question
by runrig (Abbot) on Mar 06, 2005 at 06:49 UTC
    use warnings; would have told you what the problem was. use strict; also for good measure.
Re: A simple foreach question
by calin (Deacon) on Mar 06, 2005 at 11:23 UTC

    Your program works, but with the following restrictions:

    • You have to enter a single number on each input line.
    • Your program first reads ("slurps") the whole input stream, before going on to processing. Press Ctrl-D on an empty line when you're done with input (on Windoze, you may have to type an additional Enter IIRC).

    Keep in mind that the elements of @list in your progam are lines, not necessarily numbers. Here's another approach that is more flexible with input format. You can separate numbers with commas, spaces etc. Also, input is processed ASAP (after each line, buffering permitting) :

    my @names = qw/ fred betty barney dino wilma peblles bamm-bamm /; while(<STDIN>) { print $names[$_ - 1], "\n" for grep {$_ <= @names} m/\d+/g; }
Re: A simple foreach question
by davidj (Priest) on Mar 06, 2005 at 06:53 UTC
    I believe the reason is this: You are receiving the input in list context. Therefore when you enter '2 3 4' it is being recieved as a string and the array has only one element. Now, when you iterate through your 1 element array, you are trying to use it as a number, but since the one element '2 3 4' is a string, only the 2 is being used. It would be better to do something like this:

    #!/usr/bin/perl use strict; my @names = qw/ fred betty barney dino wilma peblles bamm-bamm /; chomp( my $list = <STDIN>); my @list = split(" ", $list); foreach (@list) { print " $names[ $_ - 1]\n"; } exit;
    davidj
Re: A simple foreach question
by gopalr (Priest) on Mar 06, 2005 at 06:53 UTC
    @list = split (' ', $ARGV[0]); ## It should be in Command line argume +nt

    or

    @list = (split (' ', <STDIN>)));