Arrays Perl:为Foreach循环中的数组元素分配引用
我真的很想自己弄明白,但是我的脸现在因为不断地撞到这堵砖墙而疼痛 我试图加载9个文本文件,每个文件由7行7个字符组成的矩阵组成,用空格分隔,然后将每个引用的矩阵保存到数组中的一个元素中。我读取的每个文件都很好,但当我访问数组时,所有元素都是相同的。我一直在寻找解决方案,要么我的问题在任何地方都没有得到回答,要么(更有可能)我不理解答案。下面是我代码中的问题部分:Arrays Perl:为Foreach循环中的数组元素分配引用,arrays,perl,reference,foreach,Arrays,Perl,Reference,Foreach,我真的很想自己弄明白,但是我的脸现在因为不断地撞到这堵砖墙而疼痛 我试图加载9个文本文件,每个文件由7行7个字符组成的矩阵组成,用空格分隔,然后将每个引用的矩阵保存到数组中的一个元素中。我读取的每个文件都很好,但当我访问数组时,所有元素都是相同的。我一直在寻找解决方案,要么我的问题在任何地方都没有得到回答,要么(更有可能)我不理解答案。下面是我代码中的问题部分: my @boardarray = (1, 2, 3, 4, 5, 6, 7, 8, 9); sub LoadBoards {
my @boardarray = (1, 2, 3, 4, 5, 6, 7, 8, 9);
sub LoadBoards {
my (@board, $infile, @allboards);
my $i = 1;
@allboards = @boardarray;
foreach (@allboards) {
my $infile = "board" . $i . "\.brd";
open FILE, "< $infile" or die $!;
my $line = 0;
while (<FILE>) {
chomp $_;
my @chars = split (/ /,$_);
$board[$line] = [@chars];
$line++;
}
my $tempboard = \@board;
DisplayOneBoard($tempboard); print ("\n"); #Test A
$boardarray[$i-1] = \@board; #Problem line?
DisplayOneBoard($boardarray[$i-1]); print ("\n"); #Test B
DisplayOneBoard($boardarray[0]); print ("\n----\n"); #Test C
$i++;
}
}
my@boardarray=(1,2,3,4,5,6,7,8,9);
副装载板{
我的(@board,$infle,@allboards);
我的$i=1;
@allboards=@boardarray;
foreach(@allboards){
my$infle=“board”。$i.\.brd”;
打开文件“<$infle”或die$!;
我的$line=0;
而(){
大口大口;
my@chars=拆分(//,$);
$board[$line]=[@chars];
$line++;
}
我的$tempboard=\@board;
DisplayOneBoard($tempboard);打印(“\n”);#测试A
$boardarray[$i-1]=\@board;#问题行?
DisplayOneBoard($boardarray[$i-1]);打印(“\n”);#测试B
DisplayOneBoard($boardarray[0]);打印(“\n----\n”);#测试C
$i++;
}
}
-我已经尝试将变量分配为@boardarray的元素,没有任何更改。-我在foreach循环中使用@boardarray,并将其更改为复制的@allboards,但没有任何改进。
我希望“测试A”和“测试B”行相同,“测试C”行保持我加载的第一个矩阵。但是,对于每个迭代,这三种方法都是相同的。
(对于迭代1,它们都是矩阵1。对于迭代2,它们都是矩阵2,等等)。
最后,所有元素都是完全相同的矩阵(矩阵9)
任何协助都将不胜感激。谢谢。问题是,您每次都在循环中使用相同的
@板。当您将对该板的引用推送到@boardarray
上时,您每次都在推一个指向相同@board
的引用。修复方法很简单,只需将my@board
移动到foreach
循环的内部;这样每次都会创建一个新的@板。通过进一步分解代码,并使用数组作为堆栈与push/pop:
sub load_file {
my ($filename) = @_;
open my $file, '<', $filename or die $!;
my @array;
while (<$file>) {
chomp $_;
my @chars = split (/ /,$_);
push @array, \@chars; ### adds a reference to the char line
### array to the end of the array
}
return \@array; ### return a ref to the 2-d array
}
sub load_files {
my ($num) = @_;
my %boards; ### A hash, so we can refer to loaded arrays
### with a string ID
for my $filenum ( 1 .. $num ) {
my $filename = "board" . $filenum . "\.brd";
$boards{$filenum} = load_file($filename);
}
return \%boards; ### return a ref to the hash of 2-d arrayrefs
}
### use it now...
my $boards = load_files(9); ### load 9 files.
DisplayOneBoard($boards->{6}); ### dereference our hashref, pass board in
### key '6'to be displayed
子加载\u文件{
我的($filename)=@;
打开我的$file,'我看不到你在这段代码中的任何地方更新了$I
。我在foreach循环的最底部做了一个$I++
。谢谢。我必须在第一个子部分中更改这行:打开文件,'谢谢--我已经更正了代码。如果文件打开,通常最好使用词法文件句柄而不是glob(即标量),因为它可以在子对象之间传递,并且您可以获得其他一些隐含的好处,例如当文件句柄超出范围时自动关闭。因此,open$file…
将在使用while()…
读取时起作用。filenum错误是懒惰复制的:)我还注意到,这使得元素0变为空。一个简单的更改也解决了这个问题。$boards{$filenum-1}=load_file($filename);
关于文件句柄的好建议。我也做了这个更改。我从自己出版的书中使用了glob,所以我也做了同样的更改。它确实使0变为空,但使用了$boards{$filenum-1}=load_file($filename)
意味着$boards{'6'}
将包含“board7\.brd”的内容。如果您真的只想将boards视为一个数组,请将其声明为数组,并使用push@boards加载它,加载\u文件($filename)