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

I have this peace of code:
while ($i > 0 and $i <= $average) { print qq~<img src="http://www.ffinfo.com/images/misc/starfull. +gif" width="15" height="15" alt="Full Star" style="vertical-align: bo +ttom" /> ~; $i++ }
and it is not printing the HTML code even though $average is set to 3. I have gone though my O'riles book and been spending the better part of an hour on the web and can not find why this would not work. Every while loop example I see only uses one test but never says if that is the most you can use. Can I use 2 tests or am I limited to just 1 test? (If I remove one of the tests the code works fine)

Replies are listed 'Best First'.
Re: while loops with two tests not working.
by GrandFather (Saint) on Jul 20, 2007 at 00:02 UTC

    You haven't given us enough code to see where your problem is, but I'd suggest that you use strictures (use strict; use warnings;) and use a Perl for loop rather than the while loop:

    use strict; use warnings; my $average = 3; for my $i (1 .. $average) { print qq~dibbly\n~; }

    Prints:

    dibbly dibbly dibbly

    DWIM is Perl's answer to Gödel
      Not sure how much code you need but here is the hole scripts. From the testing I have done I know the problem is in the while loop.
      #!/user/perl/ use CGI q~:standard~; use CGI::Carp qw(fatalsToBrowser); use strict; use DBI; print "Content-type: text/html\n\n"; my ($dbh, $sth, $filename, @votes, $average, $i); $filename = $ENV{'QUERY_STRING'}; $dbh = DBI -> connect ('dbi:ODBC:', '', '') or die $DBI::errstr; $sth = $dbh -> prepare (qq~select One, Two, Three, Four, Five, TotalVo +tes from FanRatings where Title = ?~) or die $DBI::errstr; $sth -> execute ($filename) or die $DBI::errstr; @votes = $sth -> fetchrow_array; if (defined $votes[0]) { #$average = (($votes[0] + $votes[1] + $votes[2] + $votes[3] + $vot +es[4]) / $votes[5]); $average = 3; $i = 0; while ($i > 0 and $i <= $average) { print qq~<img src="http://www.ffinfo.com/images/misc/starfull. +gif" width="15" height="15" alt="Full Star" style="vertical-align: bo +ttom" /> ~; $i++ } if ($average =~ /\d\.\d/) { print qq~<img src="http://www.ffinfo.com/images/misc/starhalf. +gif" width="15" height="15" alt="Half Full Star" style="vertical-alig +n: bottom" />~; $i = $i + 0.5 } while ($i <= 4) { print qq~<img src="http://www.ffinfo.com/images/misc/starempty +.gif" width="15" height"15" alt="Empty Star" style="vertical-align: b +ottom" /> ~; $i++ } } else { $i = 0; while ($i <= 4) { print qq~<img src="http://www.ffinfo.com/images/misc/starempty +.gif" width="15" height"15" alt="Empty Star" style="vertical-align: b +ottom" /> ~; $i++ } print qq~<br />Be the first to rate this Fan Creation.~; } $dbh -> disconnect();
      I will look into switching to a for loop but for my feature info can a while loop handle two tests?
        I believe it is a logic error.

        The code in the while block does not execute because the while condition is false.

        $average = 3; $i = 0; while ($i > 0 and $i <= $average)
        In order for the while condition to be true, $i must be either 1, 2 or 3. But $i starts at 0.

        Do you really want this?

        while ($i >= 0 and $i <= $average)
        Get into the habit of using strict.
        If $i=0, you will never enter the loop which requires $i > 0
        Change to $i >= 0
        my $average = 3; my $i = 0; while ($i >= 0 and $i <= $average) { print qq~<img src=".... /> ~; $i++ }

        Why do you test $i > 0 - it will always fail on the first iteration and you never get another. More likely the logic of what you want is:

        use strict; use warnings; for my $avg (0, 1.3, 1.5, 1.6, 3, 5) { my $average = $avg; my $stars = 0; print "$average: "; while ($stars < int ($average)) { print "*"; ++$stars; } if ($stars <= $average - 0.5) { print "+"; ++$stars; } while ($stars < 5) { print "."; $stars++; } } continue { print "\n"; }

        DWIM is Perl's answer to Gödel
Re: while loops with two tests not working.
by Cody Pendant (Prior) on Jul 20, 2007 at 03:55 UTC
    Just for the fun of it (and a gentle push towards "use a templating system"), I came up with this:
    use strict; use warnings; use HTML::Template; my $t = HTML::Template->new( filehandle => \*DATA, die_on_bad_params => 0 ); my ( $average, @fullstars, @emptystars ); $average = 3.7; # hard-coded for testing for ( 1 .. 5 ) { if ( $_ <= $average ) { push( @fullstars, 1 ); } else { push( @emptystars, 1 ) } } if ( int($average) != $average ) { $t->param( halfstar => 1 ); shift(@emptystars); } $t->param( fullstars => \@fullstars, emptystars => \@emptystars ); print $t->output(); __DATA__ <tmpl_loop name="fullstars"> <img src="fullstar"> </tmpl_loop> <tmpl_if name="halfstar"> <img src="halfstar"> </tmpl_if> <tmpl_loop name="emptystars"> <img src="emptystar"> </tmpl_loop>


    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...