Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

**HomeWork** Printing the found input from an array

by trenchwar (Beadle)
on Apr 02, 2008 at 03:12 UTC ( [id://677874]=perlquestion: print w/replies, xml ) Need Help??

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

Yet again I am slightly lost,
It runs perfectly, however the array that prints at the bottom of the script that calls $city clearly has no value for $city.
As always thank everyone who takes the time to help and explain what I am missing!.
#!/usr/bin/perl print "Excuse Generator\n\n\n"; my @myCities = ('Baltimore','Chicago','Los Angeles','New York','San Di +ego'); my $found=0; print "Please pick one of the following cities by entering any portion + of the beginning of the city name:(@myCities)\n"; chomp(my $input_city = <STDIN> ); if ( $input_city =~ m/^l/i ) { print "We no longer tour the city of Angels, please try again\ +n"; exit; } foreach my $city ( @myCities ) { if ($city =~ /^$input_city/i ) { print "Found $city\n"; $found = 1; next; } } if ($found == 0) { print "No City found!\n"; } my %num2mon = ( "1" => "January", "2" => "February", "3" => "March", "4" => "April", "5" => "May", "6" => "June", "7" => "July", "8" => "August", "9" => "September", "10" => "October", "11" => "November", "12" => "December" ); print "Enter the month as an integer i.e. (1=January, 2=Febuary, etc.) +\n"; chomp($month = <STDIN> ); if (exists $num2mon{$month}) { #exists; } else { print "Invalid Month $month specified\n"; } print "How many days [1-31]?\n"; chomp(my $num_days = <STDIN> ); my $days = join( ", ", 1 .. $num_days ),; @myArray = ( "\nHi Steve, \n\n", "I'm looking forward to the Perl class. \n", "I just want to let you know that I won't be in class on the f +ollowing days:\n\n", "\ $num2mon{$month} $days\n\n", "I'm touring $city with my dance band, Liquid Blue!\n\n", "Thanks,\n", "Scott Stephens\n\n" ); print @myArray;

Replies are listed 'Best First'.
Re: **HomeWork** Printing the found input from an array
by ww (Archbishop) on Apr 02, 2008 at 03:29 UTC
    You seem to harbor a misconception about strict and warnings:
    And I know I have to turn warnings on, I just wanted to figure out how to get it working first.

    Nope! That's backward. Strict and warnings help you get it working by telling you what's wrong with your code.

    Granted, the output may be hard to follow at first; may point you to the wrong line in some cases (if blocks); may demand other techniques (such as inserting print statements); but strict and warnings are NOT something to "turn on" when you think you have working code; they exist to help you get there.

      ww, perfect explanation, thank you... I appreciate your tact!

        The diagnostics pragma is useful because is explains what the various warnings and errors mean in more detail.

        It is also a good pragma to turn on while you are learning.


        TGI says moo

Re: **HomeWork** Printing the found input from an array
by chromatic (Archbishop) on Apr 02, 2008 at 03:28 UTC

    If you used strict, you'd see why. The scoping of $city is such that it's not available when you declare your array. Somehow you need to keep the appropriate city value after you've found a match. (What if you assigned it to $found, and then checked if $found is empty instead of if it's zero?)

Re: **HomeWork** Printing the found input from an array
by Anonymous Monk on Apr 02, 2008 at 03:26 UTC
    And I know I have to turn warnings on, I just wanted to figure out how to get it working first.
    Thats what warnings are for, turn them on.
      Name "main::city" used only once: possible typo...line 61.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: **HomeWork** Printing the found input from an array
by radiantmatrix (Parson) on Apr 02, 2008 at 14:43 UTC

    Your issue is scoping.

    foreach my $city ( @myCities ) { # $city is local to this loop only! } print "$city"; #there's no $city in scope!

    You've declared $city within the scope of the foreach loop. Once you leave that loop, $city goes out of scope. If you'd used strict and warnings you would have gotten a warning on that print "main::city used only once", which would have been a good clue that you might have scope issues.

    Simple fix? Move $city into a wider scope:

    my $city; # now is scoped to the whole package! foreach $city ( @myCities ) { # do your stuff } print "$city"; # works as expected!

    Make sense?

    <radiant.matrix>
    Ramblings and references
    The Code that can be seen is not the true Code
    I haven't found a problem yet that can't be solved by a well-placed trebuchet
      # works as expected!

      Which depends on you expectations:

      my @myCities = (1 .. 2); my $city = "before"; # now is scoped to the whole package! foreach $city ( @myCities ) { # do your stuff $city = "after"; } print "$city"; # works as expected! # ... unless you expected it to print "after" # ... actually it prints "before"

      This is a Perl peculiarity I was once also bitten by.

      Actually Perl will localize the $city for the scope of the for-loop. See perldoc perlsyn.

      Make sense?

      Not really. There are now two variables named city (one localized to the loop and a new one in the outer scope), and one of them is always undef.

      The purpose of the loop is to validate $inner_city, so why is $city being printed? Fix:

      foreach my $city ( @myCities ) { # $city is local to this loop only! } print "$inner_city";
      Makes perfect since... I was isolating $city inside the loop which is why it had no value, correct?
        which is why it had no value
        But it did have a value! But only within the loop and once you left the loop the variable got out scope and did not exist anymore.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: **HomeWork** Printing the found input from an array
by Anonymous Monk on Apr 02, 2008 at 03:39 UTC
Re: **HomeWork** Printing the found input from an array
by merlyn (Sage) on Apr 02, 2008 at 21:15 UTC
    my %num2mon = ( "1" => "January", "2" => "February", "3" => "March", "4" => "April", "5" => "May", "6" => "June", "7" => "July", "8" => "August", "9" => "September", "10" => "October", "11" => "November", "12" => "December" );
    This is so scarily similar to last week's winner.

    Are these guys both in the same class?

Re: **HomeWork** Printing the found input from an array
by wrinkles (Pilgrim) on Apr 02, 2008 at 09:20 UTC
    I made a few changes, including substituting "unless" a couple of times, and changing the month hash to a list.
    #!/usr/bin/perl #update: some problems with the month array in my code belo w (I was t +hinking the index starts at 1 not 0, newbie mistake. See discussion. use strict; use warnings; print "Excuse Generator\n\n\n"; my @myCities = ('Baltimore','Chicago','Los Angeles','New York','San Di +ego'); my $found=0; print "Please pick one of the following cities by entering any portion + of the beginning of the city name:(@myCities)\n"; chomp(my $input_city = <STDIN> ); if ( $input_city =~ m/^l/i ) { print "We no longer tour the city of Angels, please try again\ +n"; exit; } foreach my $city ( @myCities ) { if ($city =~ /^$input_city/i ) { $found = $city; print "Found $found\n"; next; } } unless ($found) { print "No City found!\n"; exit; } my @months = qw(January February March April May June July August Sept +ember October November December); print "Enter the month as an integer i.e. (1=January, 2=Febuary, etc.) +\n"; chomp(my $month = <STDIN> ); print "Invalid Month $month specified\n" unless (exists $months[$month +]); print "How many days [1-31]?\n"; chomp(my $num_days = <STDIN> ); #problems here, see discussion my $days = join( ", ", 1 .. $num_days ),; my @myArray = ( "\nHi Steve, \n\n", "I'm looking forward to the Perl class. \n", "I just want to let you know that I won't be in class on the f +ollowing days:\n\n", "\ $months[$month] $days\n\n", "I'm touring $found with my dance band, Liquid Blue!\n\n", "Thanks,\n", "Scott Stephens\n\n" ); print @myArray;
      toolic's point is well taken, but that "fix" is only partial. If, at runtime, one enters 0 for the month number, we see this:
      Enter the month as an integer i.e. (1=January, 2=Febuary, etc.) 0 How many days [1-31]? 31 Hi Steve, I'm looking forward to the Perl class. I just want to let you know that I won't be in class on the following +days: December 1, 2, 3, 4, 5, 6, 7, ....
      So one still needs to test another element of validity in the input:
      chomp(my $month = <STDIN> ); $month--; print "Invalid Month $month specified\n" unless (exists $months[$month +]); unless (exists $months[$month] && ( $month >=0 && $month <= 11 ) ){ print" Quitting. Insufficient user IQ or typing skills\n"; exit; }

      And, similarly with the day_of_month entry.

      Further, looking back to OP's test for cities, telling the user that only a restricted list is acceptable is fine, but if the user ignores that, and enters, say, ( Livonia || Las Vegas || Los Gatos ),that user still gets an answer (clear enough here, but perhaps not in a more complicated scenario) which refers only to Los Angeles, and thus may fail to help the (inattentive) luser understand what's wrong.

      Undoubtedly outside the scope of this particular bit of homework, but worth thinking about: Checking for invalid input and providing feedback are highly desireable and designing checks with broad coverage may require a lot of thought about how the user could "screw things up."

      changing the month hash to a list
      This prints the incorrect month name because an array index starts at 0, not 1. This will fix it:
      chomp(my $month = <STDIN> ); $month--;
Re: **HomeWork** Printing the found input from an array
by Anonymous Monk on Apr 04, 2008 at 19:37 UTC
    Your variable $city is lexically scoped to the foreach loop and therefore it is visible only there. Define it before the loop to access it from outside the loop.
    ... my $city; foreach $city ( @myCities ) { ...
Re: **HomeWork** Printing the found input from an array
by Anonymous Monk on Apr 04, 2008 at 19:57 UTC
    Hi trenchwar,
    Your variable $city is lexically scoped and therefore visible only within the foreach loop.
    If you need it outside the loop, define it in front of it.
    ... my $city; foreach $city ( @myCities ) { ...
    regards rollo

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://677874]
Approved by ww
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (8)
As of 2025-03-26 14:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When you first encountered Perl, which feature amazed you the most?










    Results (68 votes). Check out past polls.

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.