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

I just started to write my own code and I have a problem that I cannot get around. I've made an array list with some scores. I want to be able to type in a name and get that persons score. If the name doesn't exist then return an error message.

The problem I have is on the last print line. It only prints the name and not the score (ie "Noel has a").

Thanks in advanced for the help

#!/usr/bin/perl @grades = qw(Noel 25 Ben 76 Clementine 49 Norm 66 Chris 92 Doug 42 Carol 25 Ben 12 Clementine 0 Norm 66); ###Create my list %grades = @grades; ### turn the list into a hash print "Whose Grade do you want\n"; ### ask for the name $_ = <STDIN>; print "$_\n"; ### this is for diagnostics chomp $_; $student = $grades{$_}; ### find the grade print "$student\n"; ### this is for diagnostics if ($student = "") {print "Cannot find that student, try again\n";} else {print "$_ has a" . $student . "\n";}; ###All I see for the output is + up to the a and not $student####

Replies are listed 'Best First'.
Re: Printing two variables in the same line
by Fletch (Bishop) on Oct 07, 2004 at 19:59 UTC

    First, use strict; and use warnings.

    Next, there's no need to use @grades to initialize %grades. Just my %grades = qw( ... ) will work fine.

    As for why it's not printing you've committed the classic mistake of using the assignment operator when you meant to test for equality. perldoc perlop and look for eq.

    Update: And you also don't need to explicitly use the concatenation operator. Just "$_ has a $student\n".

    Update: And really you don't need $student at all. Just exists $grades{ $_ } and print "$_ has a $grades{ $_ }\n" without it.

      Let me elaborate:
      if ($student = "") {print "Cannot find that student, try again\n";}
      Says, essentially, if the result of assigning the value "" to $student is true....

      The problem with that? $student = "" both returns a false value AND makes $student contain an empty string!

      The comparison operators are == for binary values (numbers, mostly) and eq for strings. What you really want is:

      if ($student eq "") {print "Cannot find that student, try again\n";} ## OR, Better unless ($student) {print "Cannot find that student, try again\n";}
      That way, $student will still hold the value you expect when you reach your print statement. If you use the latter version, it will also function properly if $student is undefined for some reason ("" and undefined are slightly different, but both false).

      It's a very common mistake, and hard to catch. The above advice to use strict; and use warnings; is sound. Also, learning to use the perl debugger might have helped you here.

      radiantmatrix
      require General::Disclaimer;
        Thank you for taking the time to elaborate and the examples you gave. It was a great help!!!
      Thanks for the help. I'll learn more about the debugger soon.
Re: Printing two variables in the same line
by Anonymous Monk on Oct 07, 2004 at 22:45 UTC
    Something you should note with your hash:

    Your @grades array has students with multiple grades. When you convert @grades to %grades, you are losing the first entry.

    The following script

    use Data::Dumper; @grades = qw(Noel 25 Ben 76 Clementine 49 Norm 66 Chris 92 Doug 42 Carol 25 Ben 12 Clementine 0 Norm 66); %grades = @grades; print Dumper \@grades; print Dumper \%grades;
    will output
    $VAR1 = [ 'Noel', '25', 'Ben', '76', 'Clementine', '49', 'Norm', '66', 'Chris', '92', 'Doug', '42', 'Carol', '25', 'Ben', '12', 'Clementine', '0', 'Norm', '66' ]; $VAR1 = { 'Chris' => '92', 'Carol' => '25', 'Doug' => '42', 'Norm' => '66', 'Clementine' => '0', 'Ben' => '12', 'Noel' => '25' };
    and you'll see that only the last entry for each student is stored in your hash (which is fine if that is what you want to do, but I thought I would point that out just in case you didn't realize that was happening).
Re: Printing two variables in the same line
by The_Rabbit (Acolyte) on Oct 07, 2004 at 20:25 UTC
    Formatting your code will make it a lot easier to read. E.g. :
    if ($student = "") { print "Cannot find that student, try again\n"; } else { print "$_ has a" . $student . "\n"; }
    Also, you do not need to put a trailing semicolon at the end of your else block. All this does is create an empty statement that does nothing.

      I have been advised by some people I trust, and have a huge ammount of respect for, To always put a semi-colon on the end of every statement, even those at the end of a block. While using a semi-colon on the last statement of a block is not necissary, it can help maintainablity. I can think of a hundered situations where I have gone back and added code into an existing block, and if the semi-colon is not there, when I'm adding to it later, I am likely to forget (until I try to run the code and it doesn't compile).

      May the Force be with you

        Hmm, I don't think I was being clear enough. The author had:

        if { } else { };

        I'm not talking about having a semi-colon at the end of the last statment in a block. I'm talking about having a semi-colon AFTER the closing curly brace at the end of the block.