PDA

View Full Version : Easy beginners Perl question


eristic
01-22-2007, 01:51 AM
I'm trying to learn perl on my own, and am stuck when trying to write a program that has a set of names in an array, and when you enter different numbers, it will list the corresponding names. I got that to work, but then tried to have it check to ensure that the numbers the user entered were in the range, and now it doesn't work and I cannot figure it out. Any/all help is very much appreciated for this beginner :thumbsup:

#!/usr/bin/perl
use warnings;
use strict;
my @names = qw<alpha beta charlie delta>;
print
"Enter a number from 1 - 4, one per line, then " .
"press ctrl+z\n";
chomp (my @numbers = <STDIN>);
if ($numbers [ $_ - 1 ] >=4) {
print "You typed a number that is not in the range of 1 - 4";
} else {
foreach (@number) {
print "$names[ $_ - 1 ]\n";
}
}

eristic
01-22-2007, 03:10 PM
So I looked at the code again (had to take a break, was getting frustrated) and I think I see what may have been causing some problems. I can't run test it right now (@ work) but if someone could run it and let me know that would be awesome :D


#!/usr/bin/perl
use warnings;
use strict;
my @names = qw<alpha beta charlie delta>;
print
"Enter a number from 1 - 4, one per line, then " .
"press ctrl+z\n";
chomp (my @numbers = <STDIN>);
if ($numbers - 1 >=4) {
print "You typed a number that is not in the range of 1 - 4";
} else {
foreach $names (@names) {
print "$names\n";
}
}

david_kw
01-22-2007, 08:33 PM
I'm afraid it didn't work. There are a couple issues.

The main one is @numbers is an array. So writing

if ($numbers - 1 >= 4) {

doesn't do what you want it to. You need to loop through each of the numbers in the array and do the check like.

foreach my $n (@numbers) {
if ($numbers[$n] - 1 >= 4) {

Also I'm assuming the last part of your code is supposed to loop through the different numbers that have been entered? Right now it will list all the names once and ignore any input.

To do this part you can use the same loop that is above and

print $names[$n - 1] . "\n";

I don't know if you want a working example or not so I didn't post one.

Good luck.

david_kw

FishMonger
01-22-2007, 09:02 PM
The main one [issue] is @numbers is an array.No, the first main issue is that the script won't compile due to using vars that were not declared with my.

if ($numbers[$n] - 1 >= 4) {Why would you do that messy thing?

do this:if ($n > $#numbers) {# this checks if $n is greater than the last index number, 3 in this case

or:if ($n > @numbers) {# this checks if $n is greater than the number of array elements, 4 in this case

Personally, I'd change the input range to 0-3 instead of 1-4

eristic
01-22-2007, 09:09 PM
Basically, I want it to do 2 things. If the user types " 1 3 4 2 " the program will return "alpha charlie delta beta." If the user enters anything greater than 1-4, I want it to tell the user that he/she has picked a number beyond the scope. I am a little confused about your $n variable.



foreach my $n (@numbers) {

if ($numbers[$n] - 1 >= 4) {


What is the $n (@numbers) ? I can see that it somehow related to the index of the scalar value of $numbers (from the array) but I am confused as to how and why you put it there. I am working on the code now, so I appreciate the hints, but I am hopeful I can figure this out.

KevinADC
01-22-2007, 09:14 PM
The code is not checking the range correctly either. Numbers less than 1 (one) can be entered. You're thinking is good but the code is just not correct. Here is a sample progam that does the same thing but is still begginer type code.

#!/usr/bin/perl
my @names = qw<alpha beta charlie delta>;
print qq~Enter 4 numbers, ranging from 1 - 4.\nFirst number: ~;
while (1) {
chomp(my $n = <STDIN>);
if ($n < 1 || $n > 4) {
print "Number out of range!\nEnter a number from 1 - 4: ";
redo; # starts loop over
}
push @numbers, $n;
last if @numbers > 3;# breaks out of "while" loop
print "Next number: ";
}
for (@numbers) {
print "$names[$_-1]\n";;
}

of course this program nevers ends if a person never enters 4 valid numbers. So some type of alarm would probably be prudent but since this is learning excersize it's not really important.

david_kw
01-22-2007, 09:22 PM
No, the first main issue is that the script won't compile due to using vars that were not declared with my.

I disagree. From his point of view I think all his variables were initialized with my.

He initialized @names and @numbers both. He is using $numbers and $names too but I know when I was learning it wasn't obvious that was a unique identifier to @numbers and @names.



if ($numbers[$n] - 1 >= 4) {

Why would you do that messy thing?

Because I made a mistake and was thinking of a for loop instead of a foreach loop. Still I believe using his initial code and working from there is a better way to learn.

So it should have been

if ($n - 1 >= 4) {

do this:if ($n > $#numbers) {# this checks if $n is greater than the last index number, 3 in this case

or:if ($n > @numbers) {# this checks if $n is greater than the number of array elements, 4 in this case


I don't claim to be an expert perl programmer by any means but shouldn't that be

if ($n > @names) {

? What good would it do to check to see if each number was bigger than the number of numbers in the array? You could be doing something advanced I don't understand or I know that sometimes mistakes happen.

Again, for me, learning optimizations and better ways of doing things is great, but secondary to learning the language in the first place.

david_kw

eristic
01-22-2007, 09:24 PM
Ahh so many commands I have yet to learn :eek: Intimidating but I'm going to study it. I redid the thing from scratch (w/o) the check and am trying to see how I can implement a check using what I have learned so far (as the online guide says I should be able to do).

Here is my code w/o the check:

#!/usr/bin/perl
use warnings;
use strict;

my @names = qw<alpha bravo charlie delta>;
print
"Enter a number from 1 - 4, one per line, then " .
"press ctrl+z\n";
chomp (my @numbers = <STDIN>);
foreach (@numbers) {
print "$names[ $_ - 1 ]\n";
}


The commands I have yet to learn in yours Kevin are : while, last, redo. Basically all I have access to is push/pop, shift/unshift, foreach,if/then.

david_kw
01-22-2007, 09:27 PM
Basically, I want it to do 2 things. If the user types " 1 3 4 2 " the program will return "alpha charlie delta beta." If the user enters anything greater than 1-4, I want it to tell the user that he/she has picked a number beyond the scope. I am a little confused about your $n variable.



foreach my $n (@numbers) {

if ($numbers[$n] - 1 >= 4) {


What is the $n (@numbers) ? I can see that it somehow related to the index of the scalar value of $numbers (from the array) but I am confused as to how and why you put it there. I am working on the code now, so I appreciate the hints, but I am hopeful I can figure this out.

My mistake, it should have been


for my $n (@numbers) { # each time through the loop $n gets the next value in the array
if ($n - 1 >= 4) { # check that value to see if it is in your range


But while we are throwing out code to solve the problem here's mine.


#!/usr/bin/perl
use warnings;
use strict;
my @names = qw<alpha beta charlie delta>;
print "Enter a number from 1 - 4, one per line, then " .
"press ctrl+z\n";
chomp (my @numbers = <STDIN>);

foreach my $n (@numbers) { # each time through the loop $n gets the next value in the array
if ($n < 1 or $n > 4) { # see if that number is in your range
print "You typed a number that is not in the range of 1 - 4\n";
} else {
print "$names[$n - 1]\n";
}
}


david_kw

eristic
01-22-2007, 09:34 PM
Wow! I get it. Your comment David regarding the foreach my $n (@numbers) now makes sense to me. The book did an example with that, but did not explain the function of the $n. I see now. I was definitely over thinking it. Thank you to everyone that posted!!! Reading the different comments and seeing the different ways to do it really help me. Hopefully you guys don't mind me asking questions every so often. I see most people on this forum supersede me by far, so I hope I can learn from you guys. :)

FishMonger
01-22-2007, 09:56 PM
You still have a problem with invaild user input. What do you think will happen if the user does the unexpected, such as a typo like entering an 'e' instead of a 3 or 4?

Here's a better approach that could also be improved.
#!/usr/bin/perl

use warnings;
use strict;

my @names = qw<alpha beta charlie delta>;
my $number;

do {
print "Enter a number from 1 - 4 or Q to quit:";
chomp ($number = <STDIN>);
if ($number =~ /^\d$/ && $number =~ /[0-3]/) {
print "$names[$number]\n\n";
} elsif ($number !~ /q/i) {
print "Invalid Entry\n\n";
}
} until $number =~ /q/i;

david_kw
01-22-2007, 10:13 PM
Actually I think entering 'e' would work correctly, although it would also generate a warning which I agree isn't what you want.

Regular expressions are a good way to scare someone starting out. :)

david_kw

FishMonger
01-22-2007, 11:10 PM
Actually I think entering 'e' would work correctly, although it would also generate a warning which I agree isn't what you want.That was the exact point that I was making.

Regular expressions are a good way to scare someone starting out. :)Yes, they can be intimidating at first, but the earlier they are learned, the better Perl programmer you become and the simple ones that I used are easy to explain and understand. However, I should have dropped that first one since it's unneeded if the anchors are put in the second regex.