Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 为什么这会复制或覆盖列表的内容?_Arrays_Perl_List_Hash_Push - Fatal编程技术网

Arrays 为什么这会复制或覆盖列表的内容?

Arrays 为什么这会复制或覆盖列表的内容?,arrays,perl,list,hash,push,Arrays,Perl,List,Hash,Push,我是Perl新手,我不太明白我的代码出了什么问题。我相信我正确地使用了语法,但我怀疑问题可能出在这一行: push @students, \%information; 我想让学生列表包含学生信息的散列。我所期望的是,在每次添加student之后,会创建另一个学生信息散列,并链接到列表的最新索引。但是如果我同时输入学生数据,最新的会覆盖上一个,所以当你打印它时,你会在上一个列表条目中看到最新输入信息的副本。如果我输入一个学生并在添加后立即查看,然后输入另一个学生,则最新的学生将覆盖前一个学生。有

我是Perl新手,我不太明白我的代码出了什么问题。我相信我正确地使用了语法,但我怀疑问题可能出在这一行:

push @students, \%information;
我想让学生列表包含学生信息的散列。我所期望的是,在每次添加student之后,会创建另一个学生信息散列,并链接到列表的最新索引。但是如果我同时输入学生数据,最新的会覆盖上一个,所以当你打印它时,你会在上一个列表条目中看到最新输入信息的副本。如果我输入一个学生并在添加后立即查看,然后输入另一个学生,则最新的学生将覆盖前一个学生。有人能解释一下吗?谢谢大家!

这是我的密码:

use strict;
use warnings;

my $userchoice = 0;
my $i;
my @students    = ();    #empty array
my %information = ();

while ( $userchoice != 4 ) {
    print "------------------------------\n";
    print "Welcome! What would you like to do?\n";
    print "[0]Create Student Record\n";
    print "[1]Edit Student Record\n";
    print "[2]View Student Record\n";
    print "[3]Delete Student Record\n";
    print "[4]Exit\n";
    print "Your Choice : ";
    $userchoice = <STDIN>;
    chomp($userchoice);

    if ( $userchoice == 0 ) {
        print "-----------\n";
        print "CREATE STUDENT RECORD.\n";
        if ( $#students <= 9 ) {
            print "Name : ";
            $information{"name"} = <STDIN>;
            chomp( $information{"name"} );
            push @students, \%information;
        }
        print "Student Record Full. " if ( $#students >= 10 );
    }

    if ( $userchoice == 2 ) {
        print "\nVIEW STUDENTS.\n";
        print "[0]View One Student\n";
        print "[1]View All Students\n";
        print "[2]Back to Main Menu\n";
        print "Your Choice : ";
        $userchoice = <STDIN>;
        if ( $userchoice == 1 ) {
            print "VIEW ALL STUDENTS.\n";

            print "STUDENT 1---------------\n";
            print "Name : ", $students[0]->{"name"}, " \n";
            print "STUDENT 2---------------\n";
            print "Name : ", $students[1]->{"name"}, " \n";
        }
    }
}
使用严格;
使用警告;
我的$userchoice=0;
我的$i;
我的@students=()#空数组
我的%信息=();
而($userchoice!=4){
打印“-----------------------------------\n”;
打印“欢迎!您想做什么?\n”;
打印“[0]创建学生记录\n”;
打印“[1]编辑学生记录\n”;
打印“[2]查看学生记录\n”;
打印“[3]删除学生记录\n”;
打印“[4]退出\n”;
打印“您的选择:”;
$userchoice=;
chomp($userchoice);
如果($userchoice==0){
打印“------------\n”;
打印“创建学生记录。\n”;
如果($#学生=10),;
}
如果($userchoice==2){
打印“\n查看学生。\n”;
打印“[0]查看一名学生\n”;
打印“[1]查看所有学生\n”;
打印“[2]返回主菜单\n”;
打印“您的选择:”;
$userchoice=;
如果($userchoice==1){
打印“查看所有学生。\n”;
打印“学生1---------\n”;
打印“姓名:”,$students[0]->{“姓名”},“\n”;
打印“学生2------------------\n”;
打印“姓名:”,$students[1]->{“姓名”},“\n”;
}
}
}

这总是将对同一哈希的引用推送到数组
push@students,\%信息
举例说明:

my %hash = ( index => 0 );
my @list = ();
foreach my $i (1..3) {
    $hash{index} = $i;
    push @list, \%hash;
}

for ( my $i=0; $i<@list; $i++ ) {
    print "item $i - $list[$i] - $list[$i]->{index}\n";
}
您可以通过在循环中声明%信息进行修复

while($userchoice!=4){
    my %information = ();
或者在推送时强制执行新引用:

push @students, { %information };
如评论中所述:


您需要每次使用对新哈希的引用,而不是每次尝试引用同一个哈希。最简单的方法是在循环体中定义
%信息

您的代码当前为:

my %information = ();

while ( $userchoice != 4 ) {
    print "------------------------------\n";
如果您使用以下方法,它将正常工作(或者至少,它的这一方面将正常工作):

while ( $userchoice != 4 ) {
    my %information = ();
    print "------------------------------\n";

出现问题的原因是您在数组中为每个学生放置了对相同哈希的引用:

push @students, \%information;
解决此问题的一个方法是为每个记录创建一个新的匿名哈希:

push @students, { %information };
然而,我相信你也可以从中吸取教训,限制变量的范围

声明变量时始终使用尽可能小的范围。这既有助于记录代码,也减少了意外误用此类变量的机会

以下是重写脚本以删除全局作用域中使用的所有变量:

use strict;
use warnings;

my @students = ();    #empty array

while (1) {
    print "------------------------------\n";
    print "Welcome! What would you like to do?\n";
    print "[0]Create Student Record\n";
    print "[1]Edit Student Record\n";
    print "[2]View Student Record\n";
    print "[3]Delete Student Record\n";
    print "[4]Exit\n";
    print "Your Choice : ";
    chomp( my $userchoice = <STDIN> );

    last if $userchoice == 4;

    if ( $userchoice == 0 ) {
        print "-----------\n";
        print "CREATE STUDENT RECORD.\n";
        if ( @students <= 10 ) {
            print "Name : ";
            chomp( my $name = <STDIN> );
            push @students, { name => $name };
        }
        print "Student Record Full. " if ( @students > 10 );
    }

    if ( $userchoice == 2 ) {
        print "\nVIEW STUDENTS.\n";
        print "[0]View One Student\n";
        print "[1]View All Students\n";
        print "[2]Back to Main Menu\n";
        print "Your Choice : ";
        chomp( my $userchoice = <STDIN> );
        if ( $userchoice == 1 ) {
            print "VIEW ALL STUDENTS.\n";

            for my $i ( 1 .. @students ) {
                print "STUDENT $i---------------\n";
                print "Name : ", $students[ $i - 1 ]{"name"}, " \n";
            }
        }
    }
}
使用严格;
使用警告;
我的@students=()#空数组
而(1){
打印“-----------------------------------\n”;
打印“欢迎!您想做什么?\n”;
打印“[0]创建学生记录\n”;
打印“[1]编辑学生记录\n”;
打印“[2]查看学生记录\n”;
打印“[3]删除学生记录\n”;
打印“[4]退出\n”;
打印“您的选择:”;
chomp(我的$userchoice=);
如果$userchoice==4,则为最后一个;
如果($userchoice==0){
打印“------------\n”;
打印“创建学生记录。\n”;
如果(@students$name};
}
如果(@students>10),则打印“学生记录已满”;
}
如果($userchoice==2){
打印“\n查看学生。\n”;
打印“[0]查看一名学生\n”;
打印“[1]查看所有学生\n”;
打印“[2]返回主菜单\n”;
打印“您的选择:”;
chomp(我的$userchoice=);
如果($userchoice==1){
打印“查看所有学生。\n”;
我的$i(1..@students){
打印“学生$i---------\n”;
打印“姓名:”,$students[$i-1]{“姓名”},“\n”;
}
}
}
}

你每次都需要引用一个新的散列,而不是每次都尝试引用同一个散列。最简单的方法是在循环体中定义
%信息。
得到了修复!感谢Jonathan。它确实被复制了,因为列表将引用排序为相同的散列…谢谢!到底是什么我做到了,之后效果很好。谢谢你提供更多的细节!谢谢你提供的有用提示。我会记住的。
use strict;
use warnings;

my @students = ();    #empty array

while (1) {
    print "------------------------------\n";
    print "Welcome! What would you like to do?\n";
    print "[0]Create Student Record\n";
    print "[1]Edit Student Record\n";
    print "[2]View Student Record\n";
    print "[3]Delete Student Record\n";
    print "[4]Exit\n";
    print "Your Choice : ";
    chomp( my $userchoice = <STDIN> );

    last if $userchoice == 4;

    if ( $userchoice == 0 ) {
        print "-----------\n";
        print "CREATE STUDENT RECORD.\n";
        if ( @students <= 10 ) {
            print "Name : ";
            chomp( my $name = <STDIN> );
            push @students, { name => $name };
        }
        print "Student Record Full. " if ( @students > 10 );
    }

    if ( $userchoice == 2 ) {
        print "\nVIEW STUDENTS.\n";
        print "[0]View One Student\n";
        print "[1]View All Students\n";
        print "[2]Back to Main Menu\n";
        print "Your Choice : ";
        chomp( my $userchoice = <STDIN> );
        if ( $userchoice == 1 ) {
            print "VIEW ALL STUDENTS.\n";

            for my $i ( 1 .. @students ) {
                print "STUDENT $i---------------\n";
                print "Name : ", $students[ $i - 1 ]{"name"}, " \n";
            }
        }
    }
}