alisea
alisea

Reputation: 362

Unintended endless While loop - why?

I have an array of numeric values that's sorted. I also have a minimum and maximum value and want to remove any values from the array that are smaller than the minimum or bigger than the maximum value. I am getting an endless loop when my minimum value is smaller than the value of the first array element. Here's a minimal example of the code in question:

#!/usr/bin/perl

use strict;
use warnings;

my @array = ( 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 );
my $min_wert = 1;
my $max_wert = 13;

while ( $array[0] < $min_wert ) {
    shift @array;
}
while ( $array[-1] > $max_wert ) {
    pop @array;
}

print join( ' ', @array );
print "\n";

The problem is, this version works flawlessly, outputting

5 6 7 8 9 10 11 12 13

The first while is not entered in this case.

Dropping the same test case into my production code, I'm getting the following error message on the line with the shift-statement:

Use of uninitialized value in numeric lt (<) at line 1130.

I then introduced a counter to try to figure out why the while-loop is even entered, and that completely removes the problem instead of giving me the opportunity for further diagnostics.

    @werte_liste = sort {$a <=> $b} @werte_liste; 
    print join( ' ', @werte_liste );
    print "\n";
    print "Start: $start_index - Stop: $stop_index\n"

    while ( $werte_liste[0] < $start_index ) {
        print "In while-loop- why?\n";
        shift @werte_liste;
    }
    while ( $werte_liste[-1] > $stop_index ) {
        pop @werte_liste;
    }

why do I enter that first while loop in this case? And second, is there a better solution to my specific problem (I'm not talking lots of values here, so readability of code is more important than efficiency).

Upvotes: 0

Views: 71

Answers (2)

oals
oals

Reputation: 210

I don't know why it works with your testcase but doesn't in your production code, but here's my guess:

Your array becomes empty. $array[0] < $min_wert is true if $array[0] is undef (which happens if the array is empty), and $min_wert > 0.

undef is basically treated as a 0 in numerical comparisons (it emits a warning).

You can check that the array still has elements with this:

while ( @array and $array[0] < $min_wert ) {

The other while loop probably has the same problem.

Upvotes: 3

mob
mob

Reputation: 118605

What happens when @werte_liste is empty?

For one, $werte_liste[0] will be undefined, and the expression $werte_liste[0] < $start_index will generate the Use of uninitialized value in numerlic lt ... warnings.

For another, $werte_liste[0] will evaluate to 0 for the < comparison. If $start_index is positive, then $werte_liste[0] < $start_index is true.

Finally, shift @werte_liste will have no effect on @werte_liste, @werte_liste will remain empty, and your while ... expression will repeat indefinitely.

Upvotes: 1

Related Questions