David Newman wrote:

> Greetings. I have a newbie question about passing arrays into a subroutine
> (and getting return values as well).

Hi David,

I can't help much as far as passing or returning whole arrays, but there is a much 
better way to access arrays from inside a function.  I'll show you some tips for using 
references intead.

> My script uses arrays for various values -- one array each for TCP port
> numbers, UDP port numbers, and the different bytes of IP addresses.
>
> Since I have to populate each of these arrays, I was hoping to be able to
> use one subroutine for all of them, just by feeding the subroutine the name
> of the array, the starting value, and the number of elements in the array.

You mgiht have to shift your concept of array to get best use out of Perl arrays.  
They are really more like lists, and we generally avoid direct indexing when using 
them.  For holding associatied values, Perl provides the associative array, or hash.

> Unfortunately, the following doesn't work. I'm not even sure whether a
> subroutine can return an array.
>
> Thanks in advance for any pointers.
>
> Regards,
> David Newman
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;

     # Great start!

>
> my $count = 10;
> my @ports;
> my $start = 1025;
> &spin(@ports);

Try:
&spin([EMAIL PROTECTED]);
This send the function a reference to the @ports array.  This ensures that, rather 
than working with a local copy of the array, you are wroking with the original.


> sub spin {

    my $ports_ref = $_[0];   #$ports_ref  is now a scalar which points to the @ports 
array

>         for (; $count > 0; $count--) {
>                 push (@$ports_ref, $start++);  #push the $start value into the array

                                                                  #pointed to by 
ports_ref

>         }
> }
>
> foreach (@ports) {
>         print "$_\n";
> }

The changes shown above will serve the immediate purpose.  I just tested, and you get:
1025
1026
...
1034

But do you notice something just a bit funky about the code shown?  The $count and 
$start scalars are never passed to the function, yet the sub both uses their values 
and modifies them anyway.  This is because they are both declared in the global 
namespace.  The practice is almost ubiquitous, but very dangerous.  Any data you care 
enough about to protect is better declared inside a function, so that other code in 
your program can access it only as explicitly passed.

Try running the example below.  In particular, note the different outcome for the 
values of $start and $count, based on whether they are passed by reference or value.  
You might also try to "bomb" any of these varaiables from outside of the function, and 
see if it's possible.  I think you will find that it is not.

HTH,

Joseph

#!/usr/bin/perl

use strict;
use warnings;

test_ports();
sub test_ports {
  my $count = 10;
  my @ports;
  my $start = 1025;
  &spin([EMAIL PROTECTED], $count, \$start);
  foreach (@ports) {
          print "$_\n";
  }
  print "In calling function, \$start is now $start\n";
  print "In calling function, \$count is now $count\n";
}

sub spin {
  my ($ports_ref, $count, $start_ref) = @_;
  for (; $count > 0; $count--) {
    push (@$ports_ref, ${$start_ref}++);
  }
  print "Inside called function, \$\$start_ref is now $$start_ref\n";
  print "Inside called function, \$count is now $count\n";
}



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to