Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

I don't understand why I'm getting an unitialized value warning

by little_mistress (Monk)
on Apr 12, 2000 at 23:19 UTC ( #7416=perlquestion: print w/replies, xml ) Need Help??

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

here is a small and simple script, and yet its doing something that i dont understand On line ten, its giving a "Use of uninitialized value at test.pl line 10." warning. It seems like all the values are indeed initialized. What am I missing?
#!C:\Perl\bin\perl.exe -w $file = 'foo.txt'; open(SESAME, $file); @lines = <SESAME>; close(SESAME); $total = @lines; for ($i=0; $i <= $total; $i++) { if ($lines[$i] eq "\n") # This is line the line { pop @lines; $i = $i -1; $total = @lines; } } print "There are $total records in $file\n";
Use of uninitialized value at test.pl line 10.

Replies are listed 'Best First'.
Re: I don't understand why I'm getting an unitialized value warning
by btrott (Parson) on Apr 12, 2000 at 23:28 UTC
    $total is the number of elements in @lines, not the last array index. You're looping until $i <= $total, so the last element that you're trying to access is beyond the bounds of the array. So it's undefined.

    Say that your array has 5 elements:

    my @lines = qw/a b c d e/; my $total = @lines;
    $total is now 5, but the last array index is 4, because the indices start at 0. In your for loop, $i goes from 0 to 5, and when $i is 5, you're trying to access
    $lines[5]
    which doesn't exist.

    The solution, of course, is to change your for loop:

    for my $i (0..$total-1) { ...
    Of course, if this is all you're doing, you may as well just use grep:
    my $total = grep $_ ne "\n", @lines;
      god im such a duhhhh ....
      ok ok thanks
      This was sent to me by a coworker so i dont know if it's real code
      or just and example to show me whats going on. But, no i didn't write it
      and i don't know what its for or if its anything more than an example.
Re: I don't understand why I'm getting an unitialized value warning
by chromatic (Archbishop) on Apr 12, 2000 at 23:48 UTC
    I'm a little confused as to the purpose of this snippet. Are records in your file separated by an extra newline? I ask because it *appears* that your code tests each line in @lines to see if it only contains "\n". If so, it pops the last line off of the array (probably not what you want), decreases the number of lines expected (probably what you want) and decrements the loop index (which will cause the loop to hit the newline again, and keep popping off good lines from your array, probably the source of your error message).

    If you want to get rid of blank lines more easily, one idea is:

    #!C:\Perl\bin\perl.exe -w use strict; # I'm a masochist my $file = shift || 'foo.txt'; # why not my @lines; open(SESAME, $file) || die "Cannot open $file: $!"; # save debuggin +g time while (<SESAME>) { chomp; next unless $_; push @lines, $_; } close(SESAME) || die "Cannot close $file: $!"; my $total = @lines; print "There are $total records in $file\n";
    Not too bad. I can make it shorter, though:
    { local *SESAME; # localizing a filehandle saves debugging ti +me too open (SESAME, $file) || die "Foo: $!"; local $/ = "\n\n"; # "line" delimiter is now two newlines @lines = <SESAME>; close (SESAME) || die "Bar: $!"; }
    Bingo! One record per line in the array. You could also throw a split in there on newlines if you wanted records stored in the array one line at a time.
Re: I don't understand why I'm getting an unitialized value warning
by plaid (Chaplain) on Apr 13, 2000 at 01:21 UTC
    Here I'm assuming chromatic's assessment of the code is correct (that \n\n is the record delimiter). This isn't particularly useful, but I like ugly one-liners:)
    perl -an0777 -F"\n\n" -e 'END { print "There are ", scalar @F, " recor +ds in $ARGV\n" }' foo.txt
Re: I don't understand why I'm getting an unitialized value warning
by Doc Technical (Initiate) on Apr 13, 2000 at 10:36 UTC
    Here's how I'd make sure there are no blank records in the file,
    to get an accurate count of the records that have data in them:
    (I've been doing a lot with regular expressions and file parsing lately)

    local $/;             # Perl's record separator - default is \n unless...
    $/ = undef;           # ... we make it undefined!
    open(SESAME,$file);   # open the file
    $f = (<SESAME>);      # the entire file, including all \n chars, is now sitting in a single scalar!
    close(SESAME);
    $f = s/\n+/\n/gs;     # regular expression replaces contiguous strings of \n chars with single \n chars.
    $f = s/^\n//s;        # regex removes \n at the start of the string, if there is one.
    $f = s/\n$//s;        # regex removes \n at the end of the string, if there is one.
    @x = split(/\n/,$f);  # split string on the \n char, store split values in array @x
    $x = @x;              # the number of elements in @x
    print "There are $x records in file $file\n";
    exit(0);
      Sorry about the repetition. new here and getting the hang of the way response submissions must be formatted. The last one is correct. BTW, it would sure be nice if the folks who run this put up a "your response has been submitted" screen when a submission is made, instead of re-displaying the submission request page again.
Re: I don't understand why I'm getting an unitialized value warning
by Doc Technical (Initiate) on Apr 13, 2000 at 10:20 UTC
    Here's how I'd make sure there are no blank records in the file, to get an accurate count of the records that have data in them: (I've been doing a lot with regular expressions and file parsing lately) local $/; # Perl's record separator - default is \n unless... $/ = undef; # ... we make it undefined! open(SESAME,$file) # open the file $f = (<SESAME>); # the entire file, including all \n chars, is now sitting in a single scalar! close(SESAME); $f = s/\n+/\n/gs; # regular expression replaces contiguous strings of \n chars with single \n chars. $f = s/^\n//s; # removes \n at the start of the string, if there is one. $f = s/\n$//s; # removes \n at the end of the string, if there is one. @x = split(/\n/, $f); # split string on the \n char, store split values in array @x $x = @x; # the number of elements in @x print "There are $x records in file $file\n"; exit(0);

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://7416]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2022-07-04 23:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?