Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > accessing arrays in a different sub-routine

Reply
Thread Tools

accessing arrays in a different sub-routine

 
 
erik
Guest
Posts: n/a
 
      03-28-2005
I tried to find the answer on the web, camel book, and did not know
which perldoc to look in(perlop did not have it). I also tried a few
different things to make it work, any nothing has worked.

I dynamically create an array from an expect output. I want to then
print it out in a different array. I research references private vs.
global scalars and did not find my answer. This is my code:

#!/usr/bin/perl
################################################## ###############
# Global Variables #
################################################## ###############
use warnings;
use Expect;
use CGI(":standard");
$Expect::Log_Stdout = 0;
$device = param("device");
$username = param("username");
$password = param("password");
$enable = "enable";
$save = "wr mem";
$enable_password = param("enable_password");
$service_type = param("service_type");
my $datetemp = `date +%x_%r`;
my @dateStamp = split('\n',$datetemp);
my @bandwidth_array;
my $bandwidth_array;
(SNIP)
################################################## ################
# Now we check for bandwidth statement #
################################################## #################
sub bandwidth_router_check{
$timeout ="15";
my $bandwidth = "The router has at least 1 bandwidth statement";
my $no_bandwidth = "The router is missing a bandwidth statement";
$command->clear_accum();
print $command "show config \| inc band\r";
unless ($command->expect($timeout, -re, '#')) {
return "Never got telnet prompt".$command->exp_error()."\n";
}
my $bandwidth_capture = $command->exp_before();
my @bandwidth_array = split ('\n', $bandwidth_capture);

#HERE WE CHECK LOGGING

if ($bandwidth_capture =~ /band.*/)
{
push (@band_tests, $bandwidth);
$band_action = "OK";
}
else{
push (@band_tests, $no_bandwidth);
$band_action = "FAIL";
}

print "bandwidth_array 1 is $bandwidth_array[1]\n"; #THIS PRINT WORKS
GREAT!

};#end sub


Then I call it in a different sub-routine.

################################################## ################# #
Prints the main parameters that should be in ALL routers #
################################################## #################
sub print_main_report
{
my @bandwidth_array;
my $bandwidth_array;

print "Content-type: text/html\n\n";
print "<html><head><title>QA REPORT</title></head>";
print "<body bgcolor=#000000>";
print "<p align=center><b><font color=#FFFFFF size=5>ROUTER QA
REPORT</font></b></p>";
print "<br>";
print "<p align=center><font color=#FFFFFF><b>Date: $dateStamp[0]
EST<b></font></p>";
print "<br>";
print "<body><font color=#FFFFFF><b>QA Report for:
$device<b></font></body>";
print "<br>";

print "<br>";
#we print for bandwidth
if ($band_action eq "OK")
{
print "<body><font
color=33CC33>@band_tests.............$band_action</font></body>";
}
else{
print "<body><font
color=FF0000>@band_tests.............$band_action</font></body>";
}
print "<br>";
print "<body>bandwidth_array 1 is $bandwidth_array[1]</body>";
#THIS DOES NOT PRINT AN ELEMENT, IT PRINT AN EMPTY ELEMENT.
print "<br>";
}

Can anyone give me some input? I tried to may the refences to it global
instead of scoped, but that did not do it. How should this sort of
thing be done?

 
Reply With Quote
 
 
 
 
erik
Guest
Posts: n/a
 
      03-28-2005
I dynamically create an array from an expect output. I want to then
print it out in a different array. I research references private vs.
global scalars and did not find my answer. This is my code:

I had a typo here, should read:

I dynamically create an array from an expect output. I want to then
print it out in a different sub-routine. I research references private
vs.
global scalars and did not find my answer. This is my code:

 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      03-28-2005
erik wrote:
> I tried to find the answer on the web, camel book, and did not know
> which perldoc to look in(perlop did not have it). I also tried a few
> different things to make it work, any nothing has worked.
>
> I dynamically create an array from an expect output. I want to then
> print it out in a different array.


This is non-sensical. Arrays do not print anything.

> I research references private vs.
> global scalars and did not find my answer.


I don't think you researched enough.

> This is my code:
> #!/usr/bin/perl
> ################################################## ###############
> # Global Variables #
> ################################################## ###############
> use warnings;


You are forgetting "use strict;"

> use Expect;
> use CGI(":standard");
> $Expect::Log_Stdout = 0;


> $device = param("device");
> $username = param("username");
> $password = param("password");
> $enable = "enable";
> $save = "wr mem";
> $enable_password = param("enable_password");
> $service_type = param("service_type");


There is no reason to make any of these package variables. They should
all be declared with 'my'

> my $datetemp = `date +%x_%r`;
> my @dateStamp = split('\n',$datetemp);
> my @bandwidth_array;


This variable, having been declared lexical outside of any subroutine,
will be accessable anywhere below its declaration.

> my $bandwidth_array;


That's a remarkably poor choice of a variable name. For one, you
already have an array named "bandwidth_array". (Just because Perl
allows this doesn't make it a good idea). For two, this isn't an array,
it's a scalar.


> (SNIP)
> ################################################## ################
> # Now we check for bandwidth statement #
> ################################################## #################
> sub bandwidth_router_check{
> $timeout ="15";
> my $bandwidth = "The router has at least 1 bandwidth statement";
> my $no_bandwidth = "The router is missing a bandwidth statement";
> $command->clear_accum();
> print $command "show config \| inc band\r";
> unless ($command->expect($timeout, -re, '#')) {
> return "Never got telnet prompt".$command->exp_error()."\n";
> }
> my $bandwidth_capture = $command->exp_before();
> my @bandwidth_array = split ('\n', $bandwidth_capture);


You are declaring a new lexical array. This array will be valid for the
duration of this subroutine, and will then disappear. For the remainder
of this subroutine, this new variable masks the existing lexical you
decalred above.

>
> #HERE WE CHECK LOGGING
>
> if ($bandwidth_capture =~ /band.*/)
> {
> push (@band_tests, $bandwidth);
> $band_action = "OK";
> }
> else{
> push (@band_tests, $no_bandwidth);
> $band_action = "FAIL";
> }
>
> print "bandwidth_array 1 is $bandwidth_array[1]\n"; #THIS PRINT WORKS
> GREAT!


Of course it does. You're printing the second element of the variable
you just declared in this subroutine.

>
> };#end sub
>
>
> Then I call it in a different sub-routine.
>
> ################################################## ################# #
> Prints the main parameters that should be in ALL routers #
> ################################################## #################
> sub print_main_report
> {
> my @bandwidth_array;


Now here's another entirely new lexical. This one again masks the first
one you declared, and is valid for the duration of this subroutine. It
has absolutely nothing whatsoever to do with either the variable you
declared in the previous subroutine, or with the variable you declared
at the top of the file.

> my $bandwidth_array;


<snip>

> print "<body>bandwidth_array 1 is $bandwidth_array[1]</body>";
> #THIS DOES NOT PRINT AN ELEMENT, IT PRINT AN EMPTY ELEMENT.


Of course it does. You're trying to print the second element of an array
you never added anything to.

> print "<br>";
> }
>
> Can anyone give me some input? I tried to may the refences to it global
> instead of scoped, but that did not do it. How should this sort of
> thing be done?


You generally have two options:
1) Make a variable that is lexically scoped to the entire file. You put
one declaration near the top of the file, just as you did here. You
then simply *use* that variable. Don't declare any more variables of
the same name.
2) Have the function that first sets the variable declare the variable
lexically scoped to the function itself, and then pass that variable (or
at least its value) around using array parameters and function return
values.


You should probably read "Coping with Scoping", which talks about the
different scopes of variables.
http://perl.plover.com/FAQs/Namespaces.html


Paul Lalli
 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      03-28-2005
"erik" <(E-Mail Removed)> wrote in news:1112037688.658680.167210
@g14g2000cwa.googlegroups.com:

> my $datetemp = `date +%x_%r`;


In addition to Paul Lalli's excellent commnents elsethread, let me please
ask, WHY?

No need to spawn an external program to just a get a timestamp.

perldoc -f time
perldoc -f localtime

> my @dateStamp = split('\n',$datetemp);


perldoc -f chomp

See also the strftime function in the POSIX module.

The only reason you declare and use @dateStamp is to get rid of the EOL at
the end of $datetemp. You might think the above is harmless, but puzzling
gems like this make your programs hard to read later.

Sinan
 
Reply With Quote
 
erik
Guest
Posts: n/a
 
      03-28-2005
I just read that, thanks. That sheds some light. So basically with my
example above, and due to it's dynamic nature, the only way I can get
this working is a sub-function within a subfunction. I really didn't
want to do that, but I take it I have no choice. I thought I could do
my $bandwidth_array; in my printing sub-routine but like you said, it
in't DOING anything.

I liked this line from the coping with scope.

When to Use my and When to Use local
Always use my; never use local.

Wasn't that easy?

BTW, what was wrong with the name that I gave my array
@bandwidth_array? You lost me on that one.

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      03-28-2005
"erik" <(E-Mail Removed)> wrote in news:1112049496.433969.94040
@g14g2000cwa.googlegroups.com:

> I just read that, thanks.


Please quote an appropriate amount of context when replying.

> That sheds some light. So basically with my
> example above, and due to it's dynamic nature, the only way I can get
> this working is a sub-function within a subfunction. I really didn't
> want to do that, but I take it I have no choice.


You lost me here.

Here is a simple example of what you can do:

#! /usr/bin/perl

my $files = read_files_in_current_dir();

$files or die "No files in current directory\n";

my_print($files);

sub read_files_in_current_dir {
opendir my $dir, '.'
or die "Cannot open current directory: $!";
[ grep { -f } readdir $dir ];
}

sub my_print {
print "$_\n" for sort @{ shift() };
}

__END__

The first subroutine you call generates the array you want, and returns
a reference to it. Then, you pass that reference to other subroutines
that work on the array.

No need for nested subroutines.

> BTW, what was wrong with the name that I gave my array
> @bandwidth_array? You lost me on that one.


For me, the '@' in front of the name already signifies that the variable
is an array, why replicate that information?

Sinan
 
Reply With Quote
 
Ala Qumsieh
Guest
Posts: n/a
 
      03-28-2005
A. Sinan Unur wrote:

> "erik" <(E-Mail Removed)> wrote in news:1112049496.433969.94040
> @g14g2000cwa.googlegroups.com:


>>BTW, what was wrong with the name that I gave my array
>>@bandwidth_array? You lost me on that one.

>
>
> For me, the '@' in front of the name already signifies that the variable
> is an array, why replicate that information?


Actually, Paul was commenting on this:

>> my $bandwidth_array;


This is a scalar, not an array (note the leading '$' sigil). Having the
name of a scalar end in '_array' can lead to confusion.

--Ala
 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      03-29-2005
I wrote, but erik didn't quote:
> You generally have two options:
> 1) Make a variable that is lexically scoped to the entire file. You
> put one declaration near the top of the file, just as you did here.
> You then simply *use* that variable. Don't declare any more variables
> of the same name.
> 2) Have the function that first sets the variable declare the variable
> lexically scoped to the function itself, and then pass that variable
> (or at least its value) around using array parameters and function
> return values.


erik wrote:
> I just read that, thanks. That sheds some light. So basically with my
> example above, and due to it's dynamic nature, the only way I can get
> this working is a sub-function within a subfunction. I really didn't
> want to do that, but I take it I have no choice.


How does anything I said above translate to this? I said nothing about
nested subroutines. I simply said to not re-declare your variable
within the subroutine. Just use the variable you already have:

my $foo;
sub fctn1{
$foo = 1;
}
sub fctn2{
print "Foo = $foo\n";
}

fctn1(); #$foo gets set here
fctn2(); #$foo gets printed here.

Your problem is that you had additional "my $foo;" statements within
fctn1 and fctn2. Get rid of them.

> BTW, what was wrong with the name that I gave my array
> @bandwidth_array? You lost me on that one.


Well, if you'd bother quoting what was said:

erik wrote:
> my $bandwidth_array;

I replied:
> That's a remarkably poor choice of a variable name. For one, you
> already have an array named "bandwidth_array". (Just because Perl
> allows this doesn't make it a good idea). For two, this isn't an
> array, it's a scalar.


you'd see that I did not say @bandwidth_array is a poor name. I said
that $bandwidth_array is a poor name. Those are two wholly unrelated
variables. They have nothing to do with one another. Naming the same
name implies that they do. Plus, naming a scalar variable
"something_array" is just a bad idea, I hope for obvious reasons.

Out of curiousity, have you read the posting guidelines for this group yet?

Paul Lalli
 
Reply With Quote
 
erik
Guest
Posts: n/a
 
      04-02-2005
No I haven't read the guidelines. I just looked and did not see them.
Would you mind posting the link and I will be glad to play nice in the
sandbox.

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      04-02-2005
"erik" <(E-Mail Removed)> wrote in news:1112404124.313308.95980
@g14g2000cwa.googlegroups.com:

> No I haven't read the guidelines. I just looked and did not see them.


They are posted here regularly. In fact, a fresh copy was posted today.

> Would you mind posting the link and I will be glad to play nice in the
> sandbox.


Would you mind typing

comp.lang.perl.misc posting guidelines

in that Google search box?

Sinan

--
A. Sinan Unur <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multidimensional arrays and arrays of arrays Philipp Java 21 01-20-2009 08:33 AM
Difference between accessing arrays and associative arrays using a int index shashi Perl Misc 17 04-13-2006 03:48 PM
two arrays problem (although different from the other two arrays) Kev Jackson Ruby 2 03-29-2006 03:58 PM
char arrays and integer arrays... why the difference? Bill Reyn C++ 3 06-22-2004 12:01 PM
Arrays.asList() returning java.util.Arrays$ArrayList Alexandra Stehman Java 5 06-17-2004 06:04 PM



Advertisments