Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get "can't use string as a SCALAR ref while strict refs" in Perl?

Tags:

perl

use strict;
my @array=('f1','f2','f3');
my $dir ='\tmp';
foreach (@array) {
  my $FH = $_;
  open ("$FH", ">$dir/${FH}.txt") or die $!;
}

foreach (@array) {
  my $FH = $_;
  close($FH);
}

i got "Can't use string ("f1") as a symbol ref while "strict refs" in use at bbb.pl line 6." error . What is the isuse ?

like image 769
Tree Avatar asked Oct 27 '10 15:10

Tree


2 Answers

First: 2 arg open is bad, 3 arg open is better.

open( .. , ">", "$dir/${FN}.txt")   

second, what on earth are you doing with open("$FH" ..

argument 1 to open is supposed to be an actual filehandle of sorts which can be connected to a datastream. passing it a string will not work.

INSANE:  open( "Hello world", .... )  # how can we open hello world, its not a file handle
WORKS:   open( *FH,.... )  # but don't do this, globs are package-globals and pesky
BEST:    open( my $fh, .... ) # and they close themself when $fh goes out of scope! 

third

foreach my $filename ( @ARRAY ){ 
}

Forth:

dir = \tmp ? are you sure? I think you meant /tmp , \tmp is something different altogether.

Fifth:

use warnings;

using strict is good, but you should use warnings too.

Sixth: Use names for variables that are explanatory, we know @ is an array @array is not more helpful.

ALL TOGETHER

use strict;
use warnings;

my @filenames=('f1','f2','f3');
my @filehandles = ();
my $dir ='/tmp';
foreach my $filename (@filenames) {
   open (my $fh,'>', "${dir}/${filename}.txt") or die $!;
   push @filehandles, $fh;
}
# some code here, ie: 
foreach my $filehandle ( @filehandles ) { 
   print {$filehandle}  "Hello world!";
}
# and then were done, cleanup time
foreach my $filehandle ( @filehandles ){ 
   close $filehandle or warn "Closing a filehandle didn't work, $!";
}

Alternatively, depending on what you were trying to do, this may have been better code:

use strict;
use warnings;

my @filenames=('f1','f2','f3');
my $dir ='/tmp';
foreach my $filename (@filenames) {
   open (my $fh,'>', "${dir}/${filename}.txt") or die $!;
   print {$fh}  "Hello world!";
}

I don't explicitly close $fh, because its not needed, as soon as $fh goes out of scope ( at the end of the block in this case ) it is closed automatically.

like image 89
Kent Fredric Avatar answered Nov 14 '22 21:11

Kent Fredric


You are using a string "f1" as the first argument to open which expects a filehandle.

You probably wanted to do:

my @filehandles = (); # Stash filehandles there so as to not lose filenames
foreach (@array) {
    my $FH = $_;
    open (my $fh, ">", "$dir/${FH}.txt") or die $!;
    push @filehandles, $fh;
}
like image 42
DVK Avatar answered Nov 14 '22 21:11

DVK