CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Access elements and Length of an array when I have only the reference

 



rpaskudniak
User


Jul 6, 2010, 4:10 PM

Post #1 of 5 (883 views)
Access elements and Length of an array when I have only the reference Can't Post

Greetings.

At the risk of reinventing the wheel -the CPAN module Text::ParseWords - (Thanks, BillKSmith), I would like to know how to do this: I want to pass an array reference to a subroutine and:
- Determine the number of items in the array
- Get a value from inside that array e.g. $my_array[3]
- Diddle the array e.g shift, push, change a value. The code I would like to run would look something like:

Code
my @one_list = (1, 2, 3, 4); 
print "@one_list\n";
append_one(\@one_list); # Notice: Passing array reference
print "@one_list\n";

sub append_one
{
my @my_list = @_; #This is definitely messed up code

printf("Before push: Top entry in array is %d\n", $#my_list);
push (@my_list, 5);
printf("After push: Top entry in array is %d\n", $#my_list);
}

Y'all know, of course, that the code presented above will NOT work as desired; in the subroutine, @my_list is an array of one entry - the array reference that was passed. Pushing the five only appends the 5 to that tiny array, leaving the original array untouched. (The Before and After values are 0 and 1.) I am guessing at *-dereferencing of a scalar and using that in an array context but I would need a syntax for that.

How can I accomplish my nefarious designs?Angelic

Note: Even if I already knew how to access the values in the array, I would not scan up until an entry is undefined. In Perl, an array might have many entries undefined before the last one.

Thanks much!
--------------------
-- Rasputin Paskudniak (In perpetual pursuit of undomesticated, semi-aquatic avians)


(This post was edited by rpaskudniak on Jul 6, 2010, 4:13 PM)


BillKSmith
Veteran

Jul 6, 2010, 8:12 PM

Post #2 of 5 (877 views)
Re: [rpaskudniak] Access elements and Length of an array when I have only the reference [In reply to] Can't Post

Perl provides several solutions to this problem. (ref perldoc perlref). Here is one.




Code
  

sub append_one {
# my @my_list = @_; #This is definitely messed up code
(my $my_list) = @_;
printf("Before push: Top entry in array is %d\n", $#my_list);
# push (@my_list, 5);
push (@{$my_list}, 5);
printf("After push: Top entry in array is %d\n", $#my_list);
}



There is a simple rule that often produces awkward code, but always works. Anywhere that you would normally use a symbol, you can replace that symbol with a reference surrounded by {}. My change to your push statement is an application of this rule.
Good Luck,
Bill


rpaskudniak
User


Jul 7, 2010, 8:50 PM

Post #3 of 5 (821 views)
Re: [rpaskudniak] Access elements and Length of an array when I have only the reference [In reply to] Can't Post

Thanks, Bill.

Your solution was real close but it took some experimentation to get it quite right. While the perldoc didn't quite address this, I managed to glean something from it and your code. Here's the code that worked; note that I have removed some of the parentheses you had used.

Code
#!/usr/bin/perl -w #-d 
#
# testglob.pl
#
use strict;
use diagnostics;

my @one_list = (1, 2, 3, 4);
print "Whole list before call: @one_list\n";
append_one(\@one_list);
print "Whole list after call: @one_list\n";

sub append_one
{
my $list_ref = shift (@_);

#printf("Before push: Top entry in array is %d\n", $#($list_ref));
for (my $lc = 0; defined($list_ref->[$lc]); $lc++)
{ printf("Entry[%d]=%d\n", $lc, $list_ref->[$lc]); }

print "Pushing one more value on the array\n";
push (@$list_ref, 5);

#printf("After push: Top entry in array is %d\n", $#($list_ref));
for (my $lc = 0; defined($list_ref->[$lc]); $lc++)
{ printf("Entry[%d]=%d\n", $lc, $list_ref->[$lc]); }
}

This produced:

Quote
Jake@Maxwell ~/scripts$ ./testglob.pl
Whole list before call: 1 2 3 4
Entry[0]=1
Entry[1]=2
Entry[2]=3
Entry[3]=4
Pushing one more value on the array
Entry[0]=1
Entry[1]=2
Entry[2]=3
Entry[3]=4
Entry[4]=5
Whole list after call: 1 2 3 4 5

OK, this was a great start. However, the first part of my question remains unanswered. You can see the commented printfs in append_one(), where I am trying to obtain the equivalent of $#array from the array reference. I have tried many permutations of $, #, {}, () and all earn me a syntax error. Short of forcing the caller to explicitly pass $#array to the subroutine, how can I access the $# of the array, given only the reference? I used the "defined()" operator here just to get by, but that is a rigged test. I already described why I don't want to rely on this as a loop terminator in general.

This is getting to be FUN! Thanks much!
--------------------
-- Rasputin Paskudniak (In perpetual pursuit of undomesticated, semi-aquatic avians)


BillKSmith
Veteran

Jul 8, 2010, 4:27 AM

Post #4 of 5 (810 views)
Re: [rpaskudniak] Access elements and Length of an array when I have only the reference [In reply to] Can't Post

Use my rule. Replace the symbol "array" with "{$array_ref}"


Code
  

$#{$array_ref}

Good Luck,
Bill


rpaskudniak
User


Jul 8, 2010, 8:46 PM

Post #5 of 5 (796 views)
Re: [BillKSmith] Access elements and Length of an array when I have only the reference [In reply to] Can't Post

Bill,

This one worked exactly as you now prescribed it. Apparently, the {} around the $array_ref reference is a manner of dereference operator, sufficient for the $# prefix to get at the desired value. HMMmm.. Before I posted this thread, I had been looking into globs for my solution. (Note the name of the source file - testglob.pl.) The {$array_ref} seems almost like the glob. I had been wondering if I would need to dig into the symbol table. But that's for another thread...

Thanks extremely for the help. I can now go back to what I was trying to do when I posted the thread Split when there is an escaped delimiter within a field. I will resume that thread to tell y'all how I plan to take care of that issue.
--------------------
-- Rasputin Paskudniak (In perpetual pursuit of undomesticated, semi-aquatic avians)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives