0

I am taking the output from a file in tabular form.

This is how the file.txt will look like. suppose its a 4*4 matrix

1 2 3 4
a b c d
e f g h
i j k l

Now i want to fetch a particular element of the table say 2nd row and 3rd column. I am using the below code but i am not getting the ouput.

I am storing the table in a array and taking the ref of it.

open(FH, "file.txt);
@Table = <FH>;
close FH;
$ref = \@Table;
print "${$ref[2][3]}";

The ouput should be "c"

Please tell me why ouput is not coming

Axeman
  • 29,660
  • 2
  • 47
  • 102
Nitesh
  • 157
  • 10

3 Answers3

2

What you mean to write is

print "$ref->[2][3]";

or

print "@$ref[2]->[3]";

From your description, I assume you've declared @Table something like this:

my @Table = ([1, 2, 3, 4], 
     ['a', 'b', 'c', 'd'], 
     ['e', 'f', 'g', 'h'],
     ['i', 'j' 'k' 'l']);

That is, I'm pretty sure you left off my since you aren't using use strict;. How do I know this? You would have gotten a message saying Global symbol "@ref" requires explicit package name if you had used it. What you're trying to access with $ref[2] is an element in the array @ref; not an element in the array ref $ref. It's also possible that you used parens (( and )) to enclose the inner arrays instead of brackets ([ and ]), which is a problem, because that would cause Perl to flatten the array into

my @Table = (1, 2, 3, 4, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' 'k' 'l');

which isn't what you want.

There are multiple problems with ${$ref[2][3]}. First of all, the proper way to access elements within an array ref is $ref->[2]->[3], which can also be written as $ref->[2][3] (I usually avoid that notation, since I think it's less intuitive). Had you succeeded in fetching that element, you would have wound up with ${"h"}, which is a problem, because Perl complains that Can't use string ("h") as a SCALAR ref.

EDIT: Since the question changed quite a bit after my answer, here's an applicable solution for the record:

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

my $ref = [];

open (my $fh, "<", "file.txt") or die "Unable to open file $!\n";
push @$ref, [split] for (<$fh>);
close $fh;

print $ref->[1]->[2],"\n"; # print value at second row, third column

I saw this Perl references quick-reference posted in another answer on SO the other day. You would benefit from having a look at it. And never write Perl code without use strict;use warnings;. That's asking for trouble.

flesk
  • 7,439
  • 4
  • 24
  • 33
  • I want to fetch 2nd row and 3rd column. say $i = 2 and $j = 3. – Nitesh Dec 12 '11 at 08:55
  • yes $ref->[2][3] and ${$ref[2][3]} are same.. But i am not getting the output. My doubt is that i want to get a particular element of the table(say 2nd row and 3 column). How to do it – Nitesh Dec 12 '11 at 08:57
  • @Nitesh: Then you have to use `$ref->[1][2]` since Perl uses zero-based indexes. No, they're not the same. – flesk Dec 12 '11 at 09:00
  • I think the below code will work read line by line and then store each line in an array then make a one array like @Table = qw/\@array1 \@array2 \@array3 \@array4/; and then all same code as i mentioned – Nitesh Dec 12 '11 at 09:04
  • Whats the difference between $ref->[2][3] and ${$ref[2][3]} – Nitesh Dec 12 '11 at 09:08
  • @Nitesh: `$ref->[2][3]` accesses the array ref `$ref`. `${$ref[2][3]}` accesses the array `@ref` and tries to take the scalar ref at the element at that position. – flesk Dec 12 '11 at 09:18
2

Here is a code that works as you want:

# ALWAYS use these 2 lines at the begining of your programs
use strict;
use warnings;

my $file = 'file.txt';
# use lexical file handler, 3 arg open and test if open is OK
open my $fh, '<', $file or die "unable to open '$file' for reading:$!";
my @Table;
while(<$fh>) {
    push @Table,[split];
}
close $fh;
my $ref = \@Table;
# this prints the third element of the second line
# array index start at 0
print $ref->[1][2];

output:

c
Toto
  • 89,455
  • 62
  • 89
  • 125
  • Thanks. can u use this also print ${$ref}[1][2]; – Nitesh Dec 12 '11 at 09:22
  • @Nitesh: No, you can't. Like I mentioned in my answer, you can use `print @{$ref}[2]->[3]`, but I don't know why you'd want to do that. – flesk Dec 12 '11 at 09:26
1

No, it shouldn't be 'c'. Not if you want the 3rd row ( indexes: 0, 1, 2 ) and 4th column (indexes: 0, 1, 2, 3 ).

Perl is a zero-index language, like C and Java and any number other languages. If you want $table->[2][3] to be 'c', you need to assign it in a certain way.

Also, simply making an array of the lines is not going to work. @Table = <FH>; just creates a single-dimensional array with the four lines in it. You would need to do at least this:

@Table = map { [ split ' ' ] } <FH>;

However, that's still not going to fix the index issue. But this will:

@Table = ( undef, map { [ undef, split ' ' ] } <FH> );

I do not recommend setting $[!!

Axeman
  • 29,660
  • 2
  • 47
  • 102