Why does this not print the filenames ?

Discussion in 'Perl Misc' started by elhombre, Mar 13, 2009.

  1. elhombre

    elhombre Guest

    I'm sure this is a typical newbie error but I cannot see why this prints

    FILE wordcount is 17 when it should print c:\original.txt word count is 17.

    If I try

    print $_ . " word count is " . $wordCount . "\n";

    it complains that $_ is unitialised and I cannot see why.

    Any ideas ?


    foreach (@ARGV) {
    open(FILE, $_) or die "File $_ does not exist";
    while (<FILE>) {
    my @words = split;
    foreach my $word (@words) {
    $wordCount++;
    }
    }
    print FILE . " word count is " . $wordCount . "\n";
    close FILE;
    $wordCount = 0;
    }
     
    elhombre, Mar 13, 2009
    #1
    1. Advertising

  2. "elhombre" <> wrote:
    >I'm sure this is a typical newbie error but I cannot see why this prints
    >
    >FILE wordcount is 17 when it should print c:\original.txt word count is 17.
    >
    >If I try
    >
    >print $_ . " word count is " . $wordCount . "\n";
    >
    >it complains that $_ is unitialised and I cannot see why.
    >
    >Any ideas ?
    >
    >
    >foreach (@ARGV) {
    > open(FILE, $_) or die "File $_ does not exist";
    > while (<FILE>) {
    > my @words = split;
    > foreach my $word (@words) {
    > $wordCount++;


    The whole while() loop can better be written as
    $wordcount = @words;
    because an array used in scalar context returns the number of its
    elements.No need to manually count them.

    And that will also solve the warning message, because you are using $_
    for two conflicting purposes: to iterate over @ARGV and to iterate over
    @words.

    > }
    > }
    > print FILE . " word count is " . $wordCount . "\n";


    You aren't printing $_, you are printing FILE.

    > close FILE;
    > $wordCount = 0;
    >}


    jue
     
    Jürgen Exner, Mar 13, 2009
    #2
    1. Advertising

  3. Jürgen Exner <> wrote:
    >"elhombre" <> wrote:


    >>foreach (@ARGV) {
    >> open(FILE, $_) or die "File $_ does not exist";
    >> while (<FILE>) {
    >> my @words = split;
    >> foreach my $word (@words) {
    >> $wordCount++;

    >
    >The whole while() loop can better be written as


    Daaah!
    Note to self: Before posting turn on brain.

    Make that the whole foreach() loop could be written as
    $wordCount += @words;

    >because an array used in scalar context returns the number of its
    >elements.No need to manually count them.


    jue
     
    Jürgen Exner, Mar 13, 2009
    #3
  4. elhombre wrote:
    > I'm sure this is a typical newbie error but I cannot see why this prints
    >
    > FILE wordcount is 17 when it should print c:\original.txt word count is
    > 17.


    Well, I don't understand how you got that far with the code below. When
    I tried it, Perl complained with the error message "Modification of a
    read-only value attempted".

    Only after having changed

    > while (<FILE>) {
    > my @words = split;


    to

    while ( my $line = <FILE> ) {
    my @words = split ' ', $line;

    the script produces the output you say.

    > If I try
    >
    > print $_ . " word count is " . $wordCount . "\n";
    >
    > it complains that $_ is unitialised and I cannot see why.


    With the above change, it does not complain.

    > Any ideas ?


    You are trying to alias $_ to both a file name and a line. In cases when
    you have an outer and an inner loop, you need to be specific in at least
    one of them.

    > foreach (@ARGV) {
    > open(FILE, $_) or die "File $_ does not exist";
    > while (<FILE>) {
    > my @words = split;
    > foreach my $word (@words) {
    > $wordCount++;
    > }
    > }
    > print FILE . " word count is " . $wordCount . "\n";
    > close FILE;
    > $wordCount = 0;
    > }


    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Mar 13, 2009
    #4
  5. elhombre

    elhombre Guest

    "Jürgen Exner" <> wrote in message
    news:...
    > "elhombre" <> wrote:
    > The whole while() loop can better be written as
    > $wordcount = @words;
    > because an array used in scalar context returns the number of its
    > elements.No need to manually count them.
    >
    > And that will also solve the warning message, because you are using $_
    > for two conflicting purposes: to iterate over @ARGV and to iterate over
    > @words.
    >
    >> }
    >> }
    >> print FILE . " word count is " . $wordCount . "\n";

    >
    > You aren't printing $_, you are printing FILE.
    >
    >> close FILE;
    >> $wordCount = 0;
    >>}

    >
    > jue


    Thanks Jue ! So simplifying gives me (I am going to rename FILE to FH so as
    to hopefully avoid confusion

    foreach (@ARGV) {
    open(FH, $_) or die "File $_ does not exist";
    while (<FH>) {
    @words = split;
    $wordCount = @words;
    }
    print FH . " word count is " . $wordCount . "\n";
    close FH;
    }

    Which gives the output

    FH word count is 18

    when what I am trying to get is

    c:\original.txt word count is 18.

    Which indicates of course that the filehandle FH is not the actual name of
    the file being opened ? How do I get it to print "c:\original.txt" ?

    Thanks again.
     
    elhombre, Mar 13, 2009
    #5
  6. Jürgen Exner wrote:
    > "elhombre" <> wrote:
    >>
    >> foreach (@ARGV) {
    >> open(FILE, $_) or die "File $_ does not exist";
    >> while (<FILE>) {
    >> my @words = split;
    >> foreach my $word (@words) {
    >> $wordCount++;


    <corrected> (in accordance with your next message)
    > The whole foreach() loop could be written as
    > $wordCount += @words;

    </corrected>

    > because an array used in scalar context returns the number of its
    > elements.No need to manually count them.
    >
    > And that will also solve the warning message, because you are using $_
    > for two conflicting purposes: to iterate over @ARGV and to iterate over
    > @words.


    No, he is using $_ to iterate over @ARGV and to iterate over <FILE>, so
    that conflict still remains. (See my post.)

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Mar 13, 2009
    #6
  7. elhombre wrote:
    > I'm sure this is a typical newbie error but I cannot see why this prints
    >
    > FILE wordcount is 17 when it should print c:\original.txt word count is
    > 17.
    >
    > If I try
    >
    > print $_ . " word count is " . $wordCount . "\n";
    >
    > it complains that $_ is unitialised and I cannot see why.
    >
    > Any ideas ?
    >
    >
    > foreach (@ARGV) {
    > open(FILE, $_) or die "File $_ does not exist";
    > while (<FILE>) {
    > my @words = split;
    > foreach my $word (@words) {
    > $wordCount++;
    > }
    > }
    > print FILE . " word count is " . $wordCount . "\n";
    > close FILE;
    > $wordCount = 0;
    > }



    made a few mods - this works better (see comments below... :)

    use strict;

    foreach (@ARGV) {
    my $file = $_;
    my ($wordCount,$word);

    open(FILE, $file) or die "File $file does not exist";
    while (<FILE>) {
    my @words = split;
    foreach my $word (@words) {
    $wordCount++;
    }
    }
    print $file . " word count is " . $wordCount . "\n";
    close FILE;
    }


    Try uncommenting the $file def and replace $_ with $file and see if you
    get any different results.

    perl g.pl login.com login.com y.com version.com
    word count is 370
    word count is 370
    word count is 14
    word count is 63

    VS.

    perl g.pl login.com login.com y.com version.com
    login.com word count is 370
    login.com word count is 370
    y.com word count is 14
    version.com word count is 63
     
    Michael Austin, Mar 13, 2009
    #7
  8. elhombre

    elhombre Guest

    "Michael Austin" <> wrote in message
    news:k8jul.18590$...

    > made a few mods - this works better (see comments below... :)
    >
    > use strict;
    >
    > foreach (@ARGV) {
    > my $file = $_;
    > my ($wordCount,$word);
    >
    > open(FILE, $file) or die "File $file does not exist";
    > while (<FILE>) {
    > my @words = split;
    > foreach my $word (@words) {
    > $wordCount++;
    > }
    > }
    > print $file . " word count is " . $wordCount . "\n";
    > close FILE;
    > }
    >
    >

    Thank you Michael ! I've spent 3 hours at this and it was something so
    simple. Thanks as well to Jue and Gunter, your help is greatly appreciated
    and very valuable.
     
    elhombre, Mar 13, 2009
    #8
  9. elhombre <> wrote:

    > I'm sure this is a typical newbie error but I cannot see why this prints
    >
    > FILE wordcount is 17 when it should print c:\original.txt word count is 17.


    > open(FILE, $_) or die "File $_ does not exist";


    > print FILE . " word count is " . $wordCount . "\n";



    There is no way to get a filename from a filehandle.

    There may, in fact, be no filename associated with a filehandle:

    open FILE, 'date|' or die "problem running date program $!";

    What "filename" should FILE have now?


    If you want to use the filename later, save it into a variable.


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
     
    Tad J McClellan, Mar 13, 2009
    #9
  10. Gunnar Hjalmarsson wrote:
    > elhombre wrote:
    >> I'm sure this is a typical newbie error but I cannot see why this prints
    >>
    >> FILE wordcount is 17 when it should print c:\original.txt word count
    >> is 17.

    >
    > Well, I don't understand how you got that far with the code below. When
    > I tried it, Perl complained with the error message "Modification of a
    > read-only value attempted".
    >
    > Only after having changed
    >
    >> while (<FILE>) {
    >> my @words = split;

    >
    > to
    >
    > while ( my $line = <FILE> ) {
    > my @words = split ' ', $line;
    >
    > the script produces the output you say.


    After having corrected Jürgen, I have to correct myself as well. The
    above change is advisable; not for the reason I mentioned above, but to
    prevent the warning message when $_ is printed after the while loop.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Mar 13, 2009
    #10
  11. Tad J McClellan wrote:
    > elhombre <> wrote:
    >
    >> I'm sure this is a typical newbie error but I cannot see why this prints
    >>
    >> FILE wordcount is 17 when it should print c:\original.txt word count is 17.

    >
    >> open(FILE, $_) or die "File $_ does not exist";

    >
    >> print FILE . " word count is " . $wordCount . "\n";

    >
    >
    > There is no way to get a filename from a filehandle.


    Unless you put it there in the first place:

    use vars '$FILE';

    $FILE = 'filename';

    open FILE or die "$FILE: $!";


    > There may, in fact, be no filename associated with a filehandle:
    >
    > open FILE, 'date|' or die "problem running date program $!";
    >
    > What "filename" should FILE have now?
    >
    >
    > If you want to use the filename later, save it into a variable.



    John
    --
    Those people who think they know everything are a great
    annoyance to those of us who do. -- Isaac Asimov
     
    John W. Krahn, Mar 13, 2009
    #11
  12. elhombre wrote:
    > I'm sure this is a typical newbie error but I cannot see why this prints
    >
    > FILE wordcount is 17 when it should print c:\original.txt word count is
    > 17.
    >
    > If I try
    >
    > print $_ . " word count is " . $wordCount . "\n";
    >
    > it complains that $_ is unitialised and I cannot see why.
    >
    > Any ideas ?
    >
    >
    > foreach (@ARGV) {
    > open(FILE, $_) or die "File $_ does not exist";
    > while (<FILE>) {
    > my @words = split;
    > foreach my $word (@words) {
    > $wordCount++;
    > }
    > }
    > print FILE . " word count is " . $wordCount . "\n";
    > close FILE;
    > $wordCount = 0;
    > }


    Try it like this:

    while ( <> ) {
    $wc += split;
    eof && print "$ARGV word count is $wc\n" and $wc = 0;
    }



    John
    --
    Those people who think they know everything are a great
    annoyance to those of us who do. -- Isaac Asimov
     
    John W. Krahn, Mar 13, 2009
    #12
  13. elhombre

    elhombre Guest

    > Try it like this:
    >
    > while ( <> ) {
    > $wc += split;
    > eof && print "$ARGV word count is $wc\n" and $wc = 0;
    > }
    >
    >
    >
    > John
    > --

    I will try that. Thanks John.
     
    elhombre, Mar 13, 2009
    #13
  14. elhombre

    elhombre Guest

    >
    > Try it like this:
    >
    > while ( <> ) {
    > $wc += split;
    > eof && print "$ARGV word count is $wc\n" and $wc = 0;
    > }
    >
    >
    >
    > John


    Hi John, it doesn't like it and is complaining that "Use of implicit split
    to @_ is deprecated "

    Wayne
     
    elhombre, Mar 13, 2009
    #14
  15. elhombre wrote:
    >>
    >> Try it like this:
    >>
    >> while ( <> ) {
    >> $wc += split;
    >> eof && print "$ARGV word count is $wc\n" and $wc = 0;
    >> }

    >
    > Hi John, it doesn't like it and is complaining that "Use of implicit
    > split to @_ is deprecated "


    while ( <> ) {
    $wc += () = split;
    eof && print "$ARGV word count is $wc\n" and $wc = 0;
    }


    John
    --
    Those people who think they know everything are a great
    annoyance to those of us who do. -- Isaac Asimov
     
    John W. Krahn, Mar 13, 2009
    #15
  16. elhombre

    Tim McDaniel Guest

    In article <>,
    Gunnar Hjalmarsson <> wrote:
    >You are trying to alias $_ to both a file name and a line. In cases
    >when you have an outer and an inner loop, you need to be specific in
    >at least one of them.


    That's true in general. It's usually a necessary practice: when I'm
    in two loops, I usually needed to refer to both loop variables.

    But foreach loops have a special rule. In man perlsyn,

    The "foreach" loop iterates over a normal list value and sets the
    variable VAR to be each element of the list in turn. If the
    variable is preceded with the keyword "my", then it is lexically
    scoped, and is therefore visible only within the loop. Otherwise,
    the variable is implicitly local to the loop and regains its
    former value upon exiting the loop. If the variable was
    previously declared with "my", it uses that variable instead of
    the global one, but it's still localized to the loop. This
    implicit localisation occurs _only_ in a "foreach" loop.

    For example, in Perl 5.010:

    $ perl -E '
    foreach (qw(1 2 3)) {
    say "outer $_";
    foreach (qw(a b c)) {
    say "inner $_";
    }
    say "outer again $_";
    }'

    produces

    outer 1
    inner a
    inner b
    inner c
    outer again 1
    outer 2
    inner a
    inner b
    inner c
    outer again 2
    outer 3
    inner a
    inner b
    inner c
    outer again 3

    --
    Tim McDaniel,
     
    Tim McDaniel, Mar 13, 2009
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. B.J.
    Replies:
    4
    Views:
    757
    Toby Inkster
    Apr 23, 2005
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,071
    Smokey Grindel
    Dec 2, 2006
  3. Michael Bray
    Replies:
    5
    Views:
    470
    Elijah Manor
    Mar 19, 2007
  4. FAQ server
    Replies:
    1
    Views:
    110
  5. Nick the Gr33k
    Replies:
    32
    Views:
    383
    Grant Edwards
    Jun 17, 2013
Loading...

Share This Page