variable scope and use strict

R

Rocky

I am trying to use strict all the time now. I have a problem with the
following code. When I use strict the value of $highest won't leave the
foreach construct. I know this is by design but I cannot figure out how
make that variable available outside the loop. Any advice?

Also if someone could tell me where to find perldoc regarding "use
strict;" or scoping in general I would appreciate it.


#!/usr/bin/perl
my $number = 1;
my $dir = "/etc/backup";
opendir DIR1, $dir;
my @files = readdir(DIR1);
closedir DIR1;
foreach my $filename (@files)
{
push(@filenum, $1) if ($filename =~ /^CUX(\d+)\.txt$/);
#my $highest = (sort { $a <=> $b } @filenum)[-1];
}
$highest = (sort { $a <=> $b } @filenum)[-1];
$final = $highest + $number;
print "CUX00" . "$final" . ".txt\n";
 
T

Tore Aursand

I am trying to use strict all the time now.

But you don't. Your code doesn't use strict at all. It doesn't use
warnings, either;

#!/usr/bin/perl
#
use strict;
use warnings;
I have a problem with the following code. When I use strict the value
of $highest won't leave the foreach construct. I know this is by design
but I cannot figure out how make that variable available outside the
loop. Any advice?

my $dir = "/etc/backup";

Needless use of double quotes;

my $dir = '/etc/backup';
opendir DIR1, $dir;

Always check if 'open()' and 'opendir()' succeeds;

opendir( DIR1, $dir ) or die "$!\n";

Eventually;

if ( opendir(DIR1, $dir) ) {
closedir( DIR1 );
}
else {
# Something bad happened; Error message in $!
}
my @files = readdir(DIR1);
closedir DIR1;
foreach my $filename (@files) {
push(@filenum, $1) if ($filename =~ /^CUX(\d+)\.txt$/); #my
$highest = (sort { $a <=> $b } @filenum)[-1];
}
$highest = (sort { $a <=> $b } @filenum)[-1]; $final = $highest
+ $number;
print "CUX00" . "$final" . ".txt\n";

You could always make sure that you have the correct set of files when you
first read them in with 'readdir';

my @files = grep { /^CUX\d+\.txt$/ } readdir( DIR1 );

It seems to be that you're trying to find the filename which have the
highest number. This could be done like this;

opendir( DIR1, $dir ) or die "$!\n";
my @files = sort { $a <=> $b } grep { /^CUX\d+\.txt$/ } readdir( DIR1 );
closedir( DIR1 );

print 'Highest valued filename: ' . $files[-1] . "\n";
Also if someone could tell me where to find perldoc regarding "use
strict;" or scoping in general I would appreciate it.

I guess 'perldoc strict' would get you going.
 
R

Rocky

But you don't. Your code doesn't use strict at all. It doesn't use
warnings, either;

#!/usr/bin/perl
#
use strict;
use warnings;
I usually put use strict; but didn't here so that the script would work
Needless use of double quotes;
is this because the value of $dir does not contain another variable and
does not need to be interpolated?
my $dir = '/etc/backup';
opendir DIR1, $dir;

Always check if 'open()' and 'opendir()' succeeds;

opendir( DIR1, $dir ) or die "$!\n";

Eventually;

if ( opendir(DIR1, $dir) ) {
closedir( DIR1 );
}
else {
# Something bad happened; Error message in $!
}
Can I open and close a directory before I push it's contents into an array?
my @files = readdir(DIR1);
closedir DIR1;
foreach my $filename (@files) {
push(@filenum, $1) if ($filename =~ /^CUX(\d+)\.txt$/); #my
$highest = (sort { $a <=> $b } @filenum)[-1];
}
$highest = (sort { $a <=> $b } @filenum)[-1]; $final = $highest
+ $number;
print "CUX00" . "$final" . ".txt\n";

You could always make sure that you have the correct set of files when you
first read them in with 'readdir';

my @files = grep { /^CUX\d+\.txt$/ } readdir( DIR1 );

It seems to be that you're trying to find the filename which have the
highest number. This could be done like this;

opendir( DIR1, $dir ) or die "$!\n";
my @files = sort { $a <=> $b } grep { /^CUX\d+\.txt$/ } readdir( DIR1 );
closedir( DIR1 );

print 'Highest valued filename: ' . $files[-1] . "\n";
your kung foo is very strong
The filename is returned to a korn shell script, but the filename is
highest + 1 so that the korn shell script can create the file and add
details about last night's backups.
I guess 'perldoc strict' would get you going.
I read the strict perldoc and that was good but I am still missing
something.
thank you for your help.
 
R

Richard Morse

Rocky said:
I am trying to use strict all the time now. I have a problem with the
following code. When I use strict the value of $highest won't leave the
foreach construct. I know this is by design but I cannot figure out how
make that variable available outside the loop. Any advice?

Also if someone could tell me where to find perldoc regarding "use
strict;" or scoping in general I would appreciate it.


#!/usr/bin/perl
my $number = 1;
my $dir = "/etc/backup";
opendir DIR1, $dir;
my @files = readdir(DIR1);
closedir DIR1;
foreach my $filename (@files)
{
push(@filenum, $1) if ($filename =~ /^CUX(\d+)\.txt$/);
#my $highest = (sort { $a <=> $b } @filenum)[-1];
}
$highest = (sort { $a <=> $b } @filenum)[-1];
$final = $highest + $number;
print "CUX00" . "$final" . ".txt\n";

I _think_ (although I'm not certain), you're asking how to make a
variable available outside a loop.

Try this example:

#!/usr/bin/perl
use strict;
use warnings;

my $highest;
$highest = 0;
foreach (1 .. 9) {
if ($_ > $highest) {
$highest = $_;
}
}

print $highest, "\n";
__END__

The key point (if I understand your question) is to declare the variable
before you enter the loop (I also initialized it to 0, so I didn't get a
warning about uninitialized values being used in the comparison). Then
it remains available once you leave the loop.

One trick -- make sure you don't rescope the variable inside the loop
(ie, don't use 'my $highest' inside the loop), because that would hide
the original $highest from the statements inside the loop.

HTH,
Ricky
 
R

Rocky

Rocky said:
I am trying to use strict all the time now. I have a problem with the
following code. When I use strict the value of $highest won't leave the
foreach construct. I know this is by design but I cannot figure out how
make that variable available outside the loop. Any advice?

Also if someone could tell me where to find perldoc regarding "use
strict;" or scoping in general I would appreciate it.


#!/usr/bin/perl
my $number = 1;
my $dir = "/etc/backup";
opendir DIR1, $dir;
my @files = readdir(DIR1);
closedir DIR1;
foreach my $filename (@files)
{
push(@filenum, $1) if ($filename =~ /^CUX(\d+)\.txt$/);
#my $highest = (sort { $a <=> $b } @filenum)[-1];
}
$highest = (sort { $a <=> $b } @filenum)[-1];
$final = $highest + $number;
print "CUX00" . "$final" . ".txt\n";

I _think_ (although I'm not certain), you're asking how to make a
variable available outside a loop.

Try this example:

#!/usr/bin/perl
use strict;
use warnings;

my $highest;
$highest = 0;
foreach (1 .. 9) {
if ($_ > $highest) {
$highest = $_;
}
}

print $highest, "\n";
__END__

The key point (if I understand your question) is to declare the variable
before you enter the loop (I also initialized it to 0, so I didn't get a
warning about uninitialized values being used in the comparison). Then
it remains available once you leave the loop.

One trick -- make sure you don't rescope the variable inside the loop
(ie, don't use 'my $highest' inside the loop), because that would hide
the original $highest from the statements inside the loop.

HTH,
Ricky
perfect. Thank you
 
D

David K. Wall

is this because the value of $dir does not contain another
variable and does not need to be interpolated?

Yes. It's a stylistic choice; like proper indentation, it can make your
code easier to read. Using single quotes indicates to the reader that
there's no need to look for variable interpolation, and conversely,
double quotes are a signal to look for variable interpolation.

It's not a major issue in this case, but using appropriate quoting is a
good habit to develop.
 
T

Tore Aursand

is this because the value of $dir does not contain another variable and
does not need to be interpolated?

As David already has pointed out (in an excellent way): Yes.
Can I open and close a directory before I push it's contents into an
array?

You mean before you _read_ from the directory? No. That doesn't make
sense, does it?

opendir( DIR, $dir ) or die "$!\n";
opendir( DIR1, $dir ) or die "$!\n";
my @files = sort {$a <=> $b} grep {/^CUX\d+\.txt$/} readdir(DIR1);
closedir( DIR1 );

print 'Highest valued filename: ' . $files[-1] . "\n";
The filename is returned to a korn shell script, but the filename is
highest + 1 so that the korn shell script can create the file and add
details about last night's backups.

No problem adding 1 to the value extracted above.
 
L

Lack Mr G M

|>
Why do you remember everything, when all you want is the maximum?
And reading in all file names just to process them sequentially isn't
necessary.

my $number = 1;
opendir DIR1, $dir or die "opendir: $!\n";
my $highest; # Now defined outside of the loop, so visible after it
while (1) {
my $filename = readdir(DIR1);
last if (not defined $filename);
if ($filename =~ /^CUX(\d+)\.txt$/)) {
$highest = $1 if ($1 > $highest);
}
}
closedir DIR1 or die "closedir: $!\n";
my $final = $highest + $number;
print "CUX00" . "$final" . ".txt\n";
 
T

Tore Aursand

my $number = 1;
opendir DIR1, $dir or die "opendir: $!\n";
my $highest; # Now defined outside of the loop, so visible after it
while (1) {
my $filename = readdir(DIR1);
last if (not defined $filename);
if ($filename =~ /^CUX(\d+)\.txt$/)) {
$highest = $1 if ($1 > $highest);
}
}
closedir DIR1 or die "closedir: $!\n";
my $final = $highest + $number;
print "CUX00" . "$final" . ".txt\n";

I don't like this code at all. Why do you call readdir() in scalar
context when there's no need to? Do you fear that there are too many
files to fit in memory? If so, you could at least have dropped that
'while (1)' thing;

while ( my $filename = readdir(DIR) ) {
if ( $filename =~ /^CUX(\d+)\.txt$/ ) {
$highest = $1;
}
}

I still prefer the other suggestion I had (in a previous posting), though;
Using 'sort' and 'grep'.
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top