in reply to using while, first line was skipped

Why did you use
$#data ++

The normal way to add a new member to an array is to use push:

#!/usr/bin/perl use warnings; use strict; my @data; while (my $line = <>) { if ($line =~ /^(.*) (\d+)$/) { push @data, $1; } } for my $d (@data) { print "$d\n"; }

Update: When @data is empty, $#data ++ returns -1, but for some reason, and creates one empty element in the array (same as $#data = 0), so Perl doesn't die with

Modification of non-creatable array value attempted, subscript -1

as it does for

my @data; $data[-1] = 2;

In the next iteration of the loop, $#data is 0 (and so is $#data ++), so the assignment overwrites the first assigned value.

لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Replies are listed 'Best First'.
Re^2: using while, first line was skipped
by rendus (Initiate) on Jul 27, 2015 at 15:23 UTC
    Hi choroba, Thank you for helping out and for your explanation. I use $#data ++ because I just followed some example I found. Is this how I supposed to write again?
    #! /usr/bin/perl my $file = 'input'; open my $fh, '<', $file or die "cant open : $!"; @data=<$fh>; while (my $line = <>) { if ($line =~ /^(.*) (\d+)$/) { push @data, $1; } } for my $d (@data) { print "$d\n"; } close $fh;
    It doesn't work though. Do you mind show me a detailed code that I could possibly implement? Thank you!
      I use $#data ++ because I just followed some example I found.

      Dangerous approach. You might get bitten if you use code you don't understand. And this example particularly is very obscure - please avoid that source of examples.

      Let's take a close look at this piece of code:

      $data[ $#data ++ ] = $1;

      What happens here, and why does it work, but not as expected?

      Consider:

      • An empty array has no elements.
      • The index -1 references the last element of an array.
      • $#data is the index of the last element of @data.
        • If @data has 1 element, it is 0.
        • If @data has no elements, it is -1.
      • Assigning to the last element of an empty array (which doesn't exist) gives a runtime error:
        Modification of non-creatable array value attempted, subscript -1 at ...
      • Array elements can be pre-allocated assigning to $#data.
      • $#data ++ is a post-increment.

      Putting the above pieces together, the following happens the first time through the loop:
      The last element of the empty array @data is requested by evaluating $#data, which yields -1. Finishing the evaluation of the term inside brackets [ $#data ++ ], the value of $#data is incremented after establishing the index requested, which leads to the creation of the first array element which index 0, so accessing the last element (index -1) is valid, and $1 is assigned to the first slot (which happens to be the last) at index 0.

      The next time through the loop, $#data yields 0, after that it is incremented, creating a slot at index 1. The assignment is also to the element at index 0, which means its contents from the previous assignment is overwritten.

      After the loop, @data has a dangling empty array element, and the first value is gone. Had you used warnings, you would have seen that:

      use warnings; my @data; for( 1..3 ) { $data[ $#data ++ ] = $_; } for (@data) { print $_,"\n"; } __END__ 2 3 Use of uninitialized value $_ in print at - line 7.

      Perl tries hard to do what you mean... if you know what you mean.

      Changing the post-increment to a pre-increment yields the desired effect:

      use warnings; my @data; for( 1..3 ) { $data[ ++ $#data ] = $_; } for (@data) { print $_,"\n"; } __END__ 1 2 3

      - but it is unwieldy, and as choroba above says, better use push which is the preferred idiom.

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      No. Just use the file handle instead of the default one:
      while (my $line = <$fh>) {
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        Thank you so much! It works perfect now. :) Greatly appreciate your kind help and explanation.