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

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

Hi, i am writing a script that sort elements of an array into certain criteria, and then asks the user what catergory they want to see. I have given a snippet of code here, my problem is that i want to print out every value of a certain criteria when the user asks to see it, however my print statement only prints a single value. Am i not passing the whole array into the scalar variable?? is it because it isn't nested in the loop correctly?? - if i put the whole thing into the loop i end up asking the same question over and over to the user. what am i doing wrong??
#! /usr/local/bin/perl -w use strict; my $num_of_params; $num_of_params = @ARGV; if ($num_of_params < 2) { die ("\n You haven't entered enough parameters !!\n\n"); } open (INFILE, $ARGV[0]) or die "unable to open file"; open (OUTFILE, ">$ARGV[1]"); my $line; my @array; my $self=0; my $choice; while (<INFILE>) { $line = $_; chomp ($line); @array = (); @array = split (/\s+/, $line); if (($array[1] =~ /^Happy/) && ($array[2] <30)) { ; $self = "$array[1]\t$array[2]\n"; # if i print $self here it prints out all of the results from that cat +ergory } print STDOUT "Please select the catergory of results that you wish t +o see;\n\n\t 1. Hello\n\t2.Happy \n\t3. unhappy \n\t4.grumpy \n\n"; $choice = <STDIN>; # remove the newline character from the chosen option. chomp $choice; if ($choice eq 1) { # if i print $self here it only prints one result, not the entire list print "$self\n"; } close OUTFILE;

Replies are listed 'Best First'.
Re: why won't is print every value???
by vladb (Vicar) on Jun 05, 2002 at 15:25 UTC
    Well, you seem to be storing only one line in your array. Every loop, you actually clear your array and set it to the values of a new line like so:
    while (<INFILE>) { { . . . @array = (); @array = split (/\s+/, $line); . . . }
    I guess you might look at changing this into this:
    my @array; while (<INFILE>) { { . . . push @array, split(/\s+/, $line); . . . }
    However, I guess you'll also have to alter the following if (...) {} block as so:
    if ($line =~ /^Happy\s+30/) { print $line . "\n"; }
    If I understand your code right ;-).

    note: I didn't have a chance to actually test the code ;/. Pardon me if it breaks anywhere ;)

    _____________________
    $"=q;grep;;$,=q"grep";for(`find . -name ".saves*~"`){s;$/;;;/(.*-(\d+) +-.*)$/; $_=["ps -e -o pid | "," $2 | "," -v "," "];`@$_`?{print"+ $1"}:{print" +- $1"}&&`rm $1`; print$\;}
Re: why won't is print every value???
by erasei (Pilgrim) on Jun 05, 2002 at 18:37 UTC
    This is my first reply, so if something isn't formatted just right, I will apologize in advance. But maybe the meaning will show through in any event :)

    I am by no means a monk, but being a full time Perl programmer, I know a lot of shortcuts. (Correct short cuts, that is, not hacks.) So, I kinda ramble over most of the code, I don't mean to step on toes or say the way you have it isn't right.. it's just a shorter way of doing the same thing. Like your argument code:

    my $num_of_params; $num_of_params = @ARGV; if ($num_of_params < 2) { die ("\n You haven't entered enough parameters !!\n\n"); }
    I would write it like this:
    die "\nYou haven't entered enough parameters !!\n\n" unless $ARGV[1];
    Does the same thing, just easier to type. Next, you have:
    open (INFILE, $ARGV[0]) or die "unable to open file"; open (OUTFILE, ">$ARGV[1]");
    If this is for end-users, you are right in not being very descriptive with your error messages. However, especially during debugging, I would be a lot more loud and graphic with your errors, something like:
    open (INFILE, $ARGV[0]) or die "unable to open file $ARGV[0]: $!\n"; open (OUTFILE, ">$ARGV[1]") or warn "unable to open file $ARGV[1]: $!\ +n";
    should work fine. Again, if it's for end-user use, turn off the errors once it's working if you need to. Next you have:
    -snip- @array = (); @array = split (/\s+/, $line); -snip- # if i print $self here it prints out all of the results from that cat +ergory
    I think the post above me covered this, and probably already answered your main question. The reason that $self is is valid here is because the array is still valid. Each time you run the loop you are clearing the array, thus the one entry that you are displaying is probably the last entry in the file you read in, because the array isn't cleared at the end. Next you have:
    $choice = <STDIN>; # remove the newline character from the chosen option. chomp $choice; if ($choice eq 1)
    Again, what you have works just fine, but since you are only reading in one character, why not just use 'getc'? Something like this:
    if (getc(STDIN) eq "1")
    Since getc only gets one character, no need for a chomp, and you save yourself a variable use. So, I hope that I got across the help I wanted to give without seeming to pick nits. Your code worked just fine (excepting the reason for the post of course), it's just that personally, I am always looking for a better way to do things, and in this case, I saw a few that I thought I would share.
      This is a tangent, but you should be careful with code like:
      die "\nYou haven't entered enough parameters !!\n\n" unless $ARGV[1];
      because if the second argument passed to the script evaluates to false (0,undef,''), the script will die even if you didn't wish it to do so. a way to prevent this:
      die "\nYou haven't entered enough parameters !!\n\n" unless defined $A +RGV[1];
        Aah, very true, but in this case, he wants to have +some+ input. An 'undef' or an empty string should be dropped because it isn't a valid option. But you are right in the grand scheme of things.
Re: why won't is print every value???
by Util (Priest) on Jun 06, 2002 at 00:03 UTC

    Util meditates on:
    "If I put the whole thing into the loop i end up asking the same question over and over to the user."


    Yes. This will anger your users.

    Where should Anonymous Monk request the user's input? Before, during, or after the while(<INFILE>){} loop?
    For clarity below, I will set aside strict, /pattern/oi, chomp, and similar elements of our craft.

    During:
    while (<INFILE>) { $word = <STDIN>; print if /$word/; } # Officiate is asked for input on every line of the file. # Officiate throttles monk; blacking out, you meditate on your error.