gpt4 book ai didi

arrays - 尝试打印数组的一个元素以某种方式打印所有元素

转载 作者:行者123 更新时间:2023-12-02 07:27:00 25 4
gpt4 key购买 nike

我正在编写一个脚本,以从文件aryData中获取整数列表,对其进行排序,然后打印排序后的数组,最高值和最低值。

aryData

89 62 11 75 8 33 95 4


但是,当打印最大值或最小值时,将打印数组的所有元素。

这是我的Perl代码

#!/bin/perl

use strict;
use warnings;

print "Enter filename to be sorted: ";
my $filename = <STDIN>;
chomp( $filename );

open( INFILE, "<$filename" );
my @nums = <INFILE>;
close INFILE;

my @sorted = sort { $a cmp $b } @nums;

open my $outfile, '>', "HighLow.txt";

print $outfile "Sorted numbers: @sorted";
print $outfile "Smallest number: $sorted[0] \n";
print $outfile "Largest number: $sorted[-1] \n";


输出 HighLow.txt

Sorted numbers: 89 62 11 75 8 33 95 4
Smallest number: 89 62 11 75 8 33 95 4
Largest number: 89 62 11 75 8 33 95 4

最佳答案

该答案将包含大部分代码审查,并解释与问题不直接相关的概念。

让我们看一下读取数组中的代码部分。

open(INFILE, "<$filename");
my @nums = <INFILE>;
close INFILE;


这段代码适合您的工作,但是有一些安全性和样式问题,我将在下面进一步介绍。

因此,您有一个文件名,并且逐行读取了一个文件。每行进入数组 @nums中的一个元素。由于您的东西无法按您想要的方式工作,因此调试此步骤所需的第一步是尝试查看阵列。

您尝试执行此操作不是一个坏主意。

print "Sorted numbers: @sorted";


Interpolating Perl中用双引号引起来的 ""字符串中的数组将数组元素与变量 $,联接在一起,该变量也称为 output field separator。默认情况下,它是空格

my @foo = (1, 2, 3);
print "@foo";


这将给出以下输出

1 2 3


不幸的是,您的输入文件已经有空格作为分隔符,并且所有数字都在一行上。因此,您根本看不到阵列设置不正确。当您自己注意到它时,那就是那一刻的facepalm时刻之一。您可以通过查看排序的数字来注意到它。您确实对它们进行了排序,但未对它们进行排序。


Sorted numbers: 89 62 11 75 8 33 95 4



找出数组中内容的更好方法是使用 Data::Dumper,它使您可以使用 serialize数据结构。它包含在Perl中。

use Data::Dumper;

my @foo = (1, 2, 3);
print Dumper \@foo;


该模块为您提供 Dumper函数。它喜欢在引用上更好地工作,因此您需要添加反斜杠以创建对 @foo的引用。在这一点上,这完全不相关。请记住,如果变量没有 $,则应在前面加上反斜杠。

$VAR1 = [
1,
2,
3
];


这很有用。它告诉我们三个要素。现在,让我们看看您的代码。我使用的是伪文件句柄 DATA,而不是实际文件,该伪句柄从程序末尾的 __DATA__部分读取。这对于测试和示例来说非常有用。

use Data::Dumper;

my @nums = <DATA>;
my @sorted = sort { $a cmp $b } @nums;

print Dumper \@sorted;

__DATA__
89 62 11 75 8 33 95 4


此打印

$VAR1 = [
'89 62 11 75 8 33 95 4
'
];


我们可以在这里看到两件事。首先,所有数字都在一行上,因此它们进入了第一个元素。第二,该行的末尾有换行符。您已经知道可以使用 chomp删除它。

因此,让我们尝试解决此问题。现在我们知道我们需要 split数字行。 There are many different ways完成此任务。我将详细介绍其中涉及的步骤。

use Data::Dumper;

my $line = <DATA>; # only read one line
chomp $line; # remove the line ending

my @nums = split / /, $line;
my @sorted = sort { $a cmp $b } @nums;

print Dumper \@sorted;

__DATA__
89 62 11 75 8 33 95 4


我们将 split与空模式 / /一起使用,将数字字符串转换为数字列表,并将其放入数组中。然后我们进行排序。

$VAR1 = [
'11',
'33',
'4',
'62',
'75',
'8',
'89',
'95'
];


如您所见,我们现在有了一个排序的数字列表。但是它们不是数字排序的。相反,它们是 sorted asciibetically。这是因为 cmp is the operatorASCII字符数排序。这也是Perl的 sort的默认行为,因此您可以省略整个 { $a cmp $b }块。就像说 sort @nums一样。

但是我们想按数字的数值对它们进行排序,因此我们需要使用 <=>排序运算符。

use Data::Dumper;

my $line = <DATA>; # only read one line
chomp $line; # remove the line ending

my @nums = split / /, $line;
my @sorted = sort { $a <=> $b } @nums;

print Dumper \@sorted;

__DATA__
89 62 11 75 8 33 95 4


现在程序将输出正确的输出。

$VAR1 = [
'4',
'8',
'11',
'33',
'62',
'75',
'89',
'95'
];


我将它留给您,以将其重新放入您的实际程序中。



最后,谈谈您的 open。您正在使用所谓的glob文件句柄。诸如 INFILE之类的东西是全局标识符。它们在整个程序中都有效,甚至在您可能加载的其他模块中也是如此。尽管在这个很小的程序中并没有真正起作用,但将来可能会引起问题。例如,如果Data :: Dumper模块要打开文件并使用相同的标识符 INFILE,而您没有调用 close INFILE,则您的程序可能会崩溃或做一些很奇怪的事情,因为它将重用同一句柄。

相反,您可以使用词汇文件句柄。词汇变量仅在特定范围内有效,例如函数或循环体。它只是一个普通变量,用 my声明。超出范围时,它将自动为您调用 close

open my $fh, "<foo";
my @nums = <$fh>;
close $fh;


您正在用两个参数调用 open。这也不是一个好主意。现在,您具有模式 <,但是如果您忽略该模式并执行 open my $fh, "$file"并从用户那里读取 $file,则它们可能会传递诸如 | rm -rf slash之类的错误信息。然后,Perl将管道 |视为模式,打开管道并删除所有内容。而是使用三个参数打开。

open my $fh, '<', 'foo';


现在,您已经明确设置了模式,因此很安全。

最后一点是,您应始终检查 open是否有效。这很简单。

open my $fh, '<', 'foo' or die $!;


variable $!包含 open遇到的错误。仅当 or调用的返回值为false时,才会触发 open。然后 die使程序终止。您可能会收到的错误看起来像这样。


/home/foo/code/scratch.pl第6154行没有此类文件或目录。


因此,完整的文件读取应如下所示。

open my $fh, '<', $filename or die "Could not read $filename: $!";
my @nums = <$fh>;
close $fh;

关于arrays - 尝试打印数组的一个元素以某种方式打印所有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45049747/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com