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;
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. | [reply] |
|
ww, perfect explanation, thank you... I appreciate your tact!
| [reply] |
|
| [reply] |
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?)
| [reply] [d/l] [select] |
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. | [reply] |
|
Name "main::city" used only once: possible typo...line 61.
| [reply] |
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
|
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
| [reply] [d/l] [select] |
|
# 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. | [reply] [d/l] [select] |
|
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";
| [reply] [d/l] [select] |
|
Makes perfect since... I was isolating $city inside the loop which is why it had no value, correct?
| [reply] |
|
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
| [reply] |
Re: **HomeWork** Printing the found input from an array
by Anonymous Monk on Apr 02, 2008 at 03:39 UTC
|
| [reply] |
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?
| [reply] [d/l] |
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;
| [reply] [d/l] |
|
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." | [reply] [d/l] [select] |
|
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--;
| [reply] [d/l] |
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 ) {
...
| [reply] [d/l] |
|
| [reply] |
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 | [reply] [d/l] |
|
|