Why does this not print the filenames ?

E

elhombre

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;
}
 
J

Jürgen Exner

elhombre said:
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

Jürgen Exner

Jürgen Exner said:
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
 
G

Gunnar Hjalmarsson

elhombre said:
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.
 
E

elhombre

Jürgen Exner said:
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.


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


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.
 
G

Gunnar Hjalmarsson

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.

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.)
 
M

Michael Austin

elhombre said:
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
 
E

elhombre

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.
 
T

Tad J McClellan

elhombre said:
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.
 
G

Gunnar Hjalmarsson

Gunnar said:
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


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.
 
J

John W. Krahn

Tad said:
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
 
J

John W. Krahn

elhombre said:
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
 
E

elhombre

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
 
J

John W. Krahn

elhombre said:
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
 
T

Tim McDaniel

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top