【问题标题】:Why does this duplicate or overwrite the contents of the list?为什么这会重复或覆盖列表的内容?
【发布时间】:2014-10-29 12:25:08
【问题描述】:

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

push @students, \%information;

我想要的是学生列表包含学生信息的哈希值。我期望的是,每次添加学生后,都会创建学生信息的另一个哈希值,并链接到列表的最新索引。但是发生的情况是,如果我同时输入学生数据,最新的会覆盖以前的数据,因此当您打印它时,您会在上一个列表条目中看到最新输入信息的副本。如果我输入了一个学生并在添加后立即查看,然后输入另一个学生,最新的学生会覆盖之前的学生。有人可以阐明这一点吗?谢谢!

这是我的代码:

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";
        }
    }
}

【问题讨论】:

  • 您需要每次都使用对新哈希的引用,而不是每次都尝试引用相同的哈希。最简单的方法是在循环体内定义%information
  • 解决了!感谢乔纳森。它确实被重复了,因为列表类型引用了相同的哈希......谢谢!

标签: arrays perl list hash push


【解决方案1】:

这总是将相同哈希的引用推送到数组push @students,\%information; 举例说明:

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";
}

从输出中注意到每个地址都相同:

item 0 - HASH(0x4c8068) - 3
item 1 - HASH(0x4c8068) - 3
item 2 - HASH(0x4c8068) - 3

您可以通过在循环中声明 %information 来修复

while($userchoice!=4){
    my %information = ();

或者在你推送时强制一个新的引用:

push @students, { %information };

【讨论】:

    【解决方案2】:

    您的问题出现了,因为您在数组中为每个学生提供了对相同哈希的引用:

    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";
                }
            }
        }
    }
    

    【讨论】:

    • 感谢您提供的有用提示。我会记住的。
    【解决方案3】:

    如评论中所述:

    您需要每次都使用对新哈希的引用,而不是每次都尝试引用相同的哈希。最简单的方法是在循环体内定义%information

    您的代码目前是:

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

    如果你使用它,它会正常工作(或者,至少它的这方面会正常工作):

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

    【讨论】:

    • 正是我所做的,之后它运行良好。感谢您提供更多详细信息!
    猜你喜欢
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2016-11-14
    • 2021-09-09
    • 2012-09-26
    • 1970-01-01
    • 2012-05-29
    • 2012-08-07
    相关资源
    最近更新 更多