For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > February 2006 > Error in the "if" block









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Error in the "if" block
Ron Smith

2006-02-19, 6:57 pm

Hi all,

This page accepts a series of numbers, separated by spaces, and gives the values listed bellow.

I'm getting the following error, but don't see why. Can anyone spot my error?

Please, enter numbers separated by spaces only!: Bad file descriptor at E:/www/cgi-bin/pg93ex3.11SeriesOfNumbers.pl line 14.

I've narrowed the problem down to the "if" block (the regex), I'd like to accept numbers and spaces only. Here's the code:

#!E:/www/perl/bin/perl.exe

use strict;
use warnings;
use CGI qw( :standard );
use CGI::Carp qw( fatalsToBrowser );
print header();

my $userIn = param( "textfield" );

if ( $userIn =~ /^(\d+|\s*)$/ ) {
$userIn = $1;
} else {
die "Please, enter numbers separated by spaces only!: $!";
}

my @numbers = split( / /, $userIn );
my $total = scalar( @numbers );
my @sorted = sort( @numbers );
my $smallestNum = @sorted[0];
my $largestNum = @sorted[-1];

my $sum = 0;
foreach ( @numbers ) {
$sum += $_;
}

my $average = ( $sum / $total );

print<<HTML;
<html>
<head>
<title>Series of Numbers</title>
<style type="text/css">
<!--
..style1 {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
}
body,td,th {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
}
-->
</style>
</head>
This page accepts a series of numbers, separated by spaces, and gives the values listed bellow.
<form action="" method="post" name="form1" class="style1" id="form1">
<table width="448" border="0">
<tr>
<td width="270"><div align="right">Enter your numbers here: </div></td>
<td width="165"><input type="text" name="textfield" /></td>
</tr>
<tr>
<td colspan="2">
<div align="center">
<a href="http://mail.yahoo.com/config/login?/pg93ex3.11SeriesOfNumbers.html"> Click here to go back! </a>
</div></td>
</tr>
<tr>
<td><div align="right">The total number of numbers entered is: </div></td>
<td> $total </td>
</tr>
<tr>
<td><div align="right">The smallest number is: </div></td>
<td> @sorted[0] </td>
</tr>
<tr>
<td><div align="right">The largest number is: </div></td>
<td> @sorted[-1] </td>
</tr>
<tr>
<td><div align="right">The sum of all the numbers is: </div></td>
<td> $sum </td>
</tr>
<tr>
<td><div align="right">The average of all the numbers is:</div></td>
<td> $average </td>
</tr>
</table>
</form>
</html>
HTML


Ron Smith
gsatlarge@yahoo.com
Ron Smith

2006-02-20, 6:56 pm

--- "John W. Krahn" <krahnj@telus.net> wrote:

> Your problem is that you are using the $! variable:
>
> But you are using it for a pattern match failure
> which is neither a system nor
> a library call.
>
>
> I would write that as:
>
> my @numbers = $userIn =~ /\d+/g;
> @numbers or die "Please, enter numbers separated by
> spaces only!";
>

Yep. Actually, I had already followed your suggestion,
with the addition of "\n". But, it was to get rid of
the fact that "$!" was spitting out the file name.
Thanks, for an explaination behind the *real* reason I
should make the change.
>
>
> "my $total =" forces scalar context so using the
> scalar() function is redundant.


Thanks, I shortened this up too; scalar function gone.
[pg. 73 "Camel Book]
>
>
> But since you are sorting numbers, you probably want
> to do a numeric sort to
> get the correct numbers:
>
> my ( $smallestNum, $largestNum ) = sort { $a <=> $b
> } @numbers;
>

I'm using: my @sorted = sort { $a <=> $b } @numbers;
Thanks, again. [pg. 790 "Camel Book"] This was
overlooked in my haste.
>
>
> You could just use the array there as a mathematical
> expression forces scalar
> context:
>
> my $average = ( $sum / @numbers );
>

This is bookmarked for future reference. Thanks, a lot
John. :-)


Ron Smith
gsatlarge@yahoo.com
Ron Smith

2006-02-20, 6:56 pm



--- "John W. Krahn" <krahnj@telus.net> wrote:

> Ron Smith wrote:
> Hans Meier (John Doe) wrote:
>
> Context. Without the parentheses you have scalar
> context but with the
> parentheses you have list context. In scalar
> context the match operator
> returns 'true' or 'false' but in list context it
> returns the contents of all
> capturing parentheses in the pattern.


Thanks.
>
>
> John
> --
> use Perl;
> program
> fulfillment
>
> --
> To unsubscribe, e-mail:
> beginners-unsubscribe@perl.org
> For additional commands, e-mail:
> beginners-help@perl.org
> <http://learn.perl.org/>
> <http://learn.perl.org/first-response>
>
>
>



Ron Smith
gsatlarge@yahoo.com
John W. Krahn

2006-02-20, 6:56 pm

Ron Smith wrote:
> --- "John W. Krahn" <krahnj@telus.net> wrote:
> I'm using: my @sorted = sort { $a <=> $b } @numbers;


Sorry, my mistake, that should really be:

my ( $smallestNum, $largestNum ) = ( sort { $a <=> $b } @numbers )[ 0, -1 ];

Although as I said, the for loop is more efficient.



John
--
use Perl;
program
fulfillment
Ron Smith

2006-02-20, 9:55 pm

>
> Sorry, my mistake, that should really be:
>
> my ( $smallestNum, $largestNum ) = ( sort { $a <=>
> $b } @numbers )[ 0, -1 ];
>
> Although as I said, the for loop is more efficient.
>


I just amazes me as to how *flexable* Perl is.


Ron Smith
gsatlarge@yahoo.com
Ron Smith

2006-02-20, 9:55 pm

>
> Sorry, my mistake, that should really be:
>
> my ( $smallestNum, $largestNum ) = ( sort { $a <=>
> $b } @numbers )[ 0, -1 ];
>
> Although as I said, the for loop is more efficient.
>


It just amazes me as to how *flexable* Perl is.


Ron Smith
gsatlarge@yahoo.com
DJ Stunks

2006-02-20, 9:55 pm

John W. Krahn wrote:
> Sorry, my mistake, that should really be:
>
> my ( $smallestNum, $largestNum ) = ( sort { $a <=> $b } @numbers )[ 0, -1 ];
>
> Although as I said, the for loop is more efficient.
>


So I thought I'd take a crack at my first benchmark, and I thought I'd
use it to compare the two methods discussed to a compiled C module:
List::Util.

Let me know what you all think (including you, grandmasters).

It would appear C beats the socks off the other two approaches (and
that sort beats for), but I don't know if the test is valid...

-jp

C:\tmp>cat tmp.pl
#!/usr/bin/perl

use strict;
use warnings;

use List::Util qw{ min max };

our @data = map { int(rand 10) } (1..10);

sub min_max_via_sort {
my ($smallestNum,$largestNum) = (sort { $a <=> $b } @_)[0,-1];
return ($smallestNum,$largestNum);
}

sub min_max_via_for {
my ($smallestNum,$largestNum) = @_[0,0];
for ( @_ ) {
$smallestNum = $_ if $smallestNum > $_;
$largestNum = $_ if $largestNum < $_;
}
return ($smallestNum,$largestNum);
}

sub min_max_via_ListUtil {
my $smallestNum = min @_;
my $largestNum = max @_;
return ($smallestNum,$largestNum);
}

sub compare {
my ($title) = @_;

print "\n[$title]\n";

use Benchmark qw{ cmpthese };
cmpthese -25, {
sort => 'my ($small,$large) = min_max_via_sort(@data)',
for => 'my ($small,$large) = min_max_via_for(@data)',
listutil => 'my ($small,$large) = min_max_via_ListUtil(@data)',
};

return;
}

compare('10 items, 25x');

C:\tmp>tmp.pl

[10 items, 25x]
Rate for sort listutil
for 123088/s -- -24% -56%
sort 162497/s 32% -- -41%
listutil 277427/s 125% 71% --

Chas Owens

2006-02-21, 3:55 am

On 2/20/06, John W. Krahn <krahnj@telus.net> wrote:
snip
> my ( $smallestNum, $largestNum ) =3D ( sort { $a <=3D> $b } @numbers )[ 0=

, -1 ];
>
> Although as I said, the for loop is more efficient.

snip

Ah this old chestnut. Depending on the size of the array sort is
faster (after 200 or so items for starts to be better). See the
benchmark program at the end of the post for how these numbers were
generated.

Results for list of 10 items
Rate for sort
for 146391/s -- -57%
sort 338736/s 131% --

Results for list of 20 items
Rate for sort
for 101629/s -- -51%
sort 205937/s 103% --

Results for list of 40 items
Rate for sort
for 57833/s -- -39%
sort 95050/s 64% --

Results for list of 80 items
Rate for sort
for 32950/s -- -22%
sort 42259/s 28% --

Results for list of 160 items
Rate for sort
for 17379/s -- -7%
sort 18656/s 7% --

Results for list of 320 items
Rate sort for
sort 8281/s -- -7%
for 8905/s 8% --

#!/usr/bin/perl

use strict;
use Benchmark qw(cmpthese);

sub min_for {
=09my $min =3D shift;
=09for (@_) {
=09=09$min =3D $_ if $_ < $min;
=09}
=09return $min;
}

sub min_sort { (sort { $a <=3D> $b } @_)[0] }

for my $size (10, 20, 40, 80, 160, 320) {
=09my @rand;
=09push @rand, rand(1000) for 1 .. $size;
=09print "Results for list of $size items\n";
=09cmpthese(
=09=09-3,
=09=09{
=09=09'for' =3D> sub { min_for(@rand) },
=09=09'sort' =3D> sub { min_sort(@rand) }
=09=09},
=09);
=09print "\n";
}
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com