2017-09-22 1 views
0

J'ai le code suivant qui lit dans un tableau 6x6 à partir de STDIN et l'enregistre sous la forme d'un tableau de tableaux anonymes. J'essaie d'imprimer chaque élément avec $arr[i][j], mais le code ci-dessous ne fonctionne pas. Il imprime juste le premier élément encore et encore. Comment est-ce que je n'accède pas correctement à l'élément?Référencement d'un élément dans un tableau 2D en Perl

#!/user/bin/perl 

my $arr_i = 0; 
my @arr =(); 
while ($arr_i < 6){ 
    my $arr_temp = <STDIN>; 
    my @arr_t = split//, $arr_temp; 
    chomp @arr_t; 
    push @arr,\@arr_t; 
    $arr_i++; 
} 
foreach my $i (0..5){ 
    foreach my $j (0..5){ 
     print $arr[i][j] . "\n"; 
    } 
} 
+3

Toujours utiliser 'use strict; utiliser les avertissements qw (tous); – ikegami

Répondre

4

i et j ne sont pas les mêmes que les variables déclarées dans les foreach lignes. Changer:

print $arr[i][j] . "\n"; 

à:

print $arr[$i][$j] . "\n"; 

warnings me alertés à cette question. Vous devez ajouter ces lignes à tout votre code Perl:

use warnings; 
use strict; 
0

Pour démontrer le mantra perlienne qu'il ya "plus d'une façon de le faire":

use 5.10.0; # so can use "say" 
use strict; 
use warnings qw(all); 

sub get_data { 
    my ($cols, $rows) = @_; 
    my ($line, @rows); 
    my $i; 
    for ($i = 1; $i <= $rows and $line = <DATA>; $i++) { 
    chomp $line; 
    my $cells = [ split ' ', $line ]; 
    die "Row $i had ", scalar(@$cells), " instead of $cols" if @$cells != $cols; 
    push @rows, $cells; 
    } 
    die "Not enough rows, got ", $i - 1, "\n" if $i != $rows + 1; 
    \@rows; 
} 

sub print_data { 
    my ($cols, $rows, $data) = @_; 
    for (my $i = 0; $i < $rows; $i++) { 
    for (my $j = 0; $j < $cols; $j++) { 
     say $data->[$i][$j]; 
    } 
    } 
} 

my $data = get_data(6, 6); 
print_data(6, 6, $data); 

__DATA__ 
1 2 3 4 5 6 
a b c d e f 
6 5 4 3 2 1 
f e d c b a 
A B C D E F 
7 8 9 10 11 12 

Explication:

  • si nous utilisons say, cela évite les disgracieux print ..., "\n"
  • get_data est une fonction qui peut être appelée et/ou réutilisée, dans lieu de simplement faire partie du script principal
  • get_data sait quelles données il forme et attend renvoie une erreur si elle ne reçoit pas
  • [ ... ] crée un tableau anonyme et renvoie une référence à ce
  • get_data retours une matrice de référence de sorte que les données ne sont pas copiées
  • print_data est une fonction trop
  • les deux fonctions utilisent une boucle for classique au lieu de faire des listes de numéros, ce qui en Perl 5 a besoin d'allouer de la mémoire

Il existe également une version à deux lignes du programme (avec les bits environnants, et les données de test):

use 5.10.0; # so can use "say" 
my @lines = map { [ split ' ', <DATA> ] } (1..6); 
map { say join ' ', map qq{"$_"}, @$_ } @lines; 

__DATA__ 
1 2 3 4 5 6 
a b c d e f 
6 5 4 3 2 1 
f e d c b a 
A B C D E F 
7 8 9 10 11 12 

Explication:

  • utilisant map est le moyen premier à itérer sur les listes des choses où vous n'avez pas besoin de savoir combien vous avez vu (sinon, une boucle for est nécessaire)
  • l'ajout de " autour du contenu de la cellule est seulement de prouver qu'ils ont été traités. Sinon, la deuxième ligne pourrait être: map { say join ' ', @$_ } @lines;
+0

Eh? L'utilisation de 'map' dans un contexte vide est déconseillée. C'est exactement comme une boucle 'for', juste inefficace (et potentiellement trompeuse pour un lecteur humain parce que la liste des résultats n'est pas utilisée). C'est à dire: 'map {say join '', map qq {" $ _ "}, @ $ _} @ lines' est mieux écrit 'say join' ', map qq {" $ _ "}, @ $ _ pour @ lines'. – melpomene

+0

Si vous souhaitez modifier, je serai heureux d'accepter. –