1

我的@array 不会停止接受标准输入...

my @array = undef;
while (@array = undef){
    @array = <STDIN>;
    for (@array[x]=5){
        @array = defined;
    }
}
4

2 回答 2

3
my @array = undef;
while (@array = undef){

这两行没有做(我假设)你认为他们正在做的事情。

my @array = undef;

这定义了一个具有单个元素的数组,该元素是特殊值undef。我怀疑你真正想要的是:

my @array = ();

这会创建一个空数组。但是 Perl 数组在第一次创建时总是空的,所以可以简化为:

my @array;

第二行重复该错误并添加一个新错误。

while (@array = undef) {

我怀疑您想在这里检查一个空数组,并且您正在寻找类似“if”的东西@array is undefined。但是您错过了这样一个事实,即在 Perl 中,赋值运算符(如=)与比较运算符(如==)不同。所以这个line分配 undef@array而不是比较它。你真的想要@array == undef- 但这也不对。

您需要摆脱检查数组是否“已定义”的想法。您真正感兴趣的是数组是否为空。Perl 有一个聪明的技巧可以帮助你解决这个问题。

如果您在 Perl 期望看到单个(标量)值的地方使用 Perl 数组,它会为您提供数组中元素的数量。所以你可以编写如下代码:

my $number_of_elements = @an_array;

ifor条件中的布尔逻辑检查while是单个标量值。因此,如果要检查数组是否包含任何元素,可以使用如下代码:

if (@array) {
  # @array contains data
} else {
  # @array is empty
}

要在数组包含元素时循环,您可以简单地编写:

while (@array) {
  # do something
}

但是在这里,您想在数组为空时做一些事情。为此,您可以反转while条件逻辑(使用!“not”):

while (!@array) {
  # do something
}

或者您可以切换到使用until测试(与 相反while):

until (@array) {
  # do something
}

我将不得不停在那里。我希望这能让您深入了解您的代码有什么问题。恐怕这种程度的错误也会渗透到您的其余代码中。

于 2017-07-28T09:31:16.887 回答
3

如上所述,限制STDIN为五行

use warnings;
use strict;
use feature 'say';

my @input;

while (<STDIN>) {
    chomp;
    push @input, $_;
    last if @input == 5;
}

say for @input;

在发布的代码中还有其他内容需要评论。虽然在Dave Cross answer中详细阐述了其中的大部分内容,但我想在从文件句柄读取时解决上下文业务。

“钻石”运算符<>是上下文感知的。来自I/O 操作员 (perlop)

如果<FILEHANDLE>在查找列表的上下文中使用 a,则返回包含所有输入行的列表,每个列表元素一行。这种方式很容易增长到相当大的数据空间,因此请谨慎使用。

在通常的while循环中<>是在标量上下文中

while (my $line = <$fh>)

并且它是相同的,while (<$fh>)因为它默认分配给$_变量,一个标量。

但是如果我们分配给一个数组,比如说从一个文件句柄$fh中打开一个文件

my @lines = <$fh>;

然后<>运算符在列表上下文中工作。它读取所有行,直到看到 EOF(文件结尾),此时它返回所有行,这些行分配给@lines. 请记住,每一行都有其换行符。您可以通过以下方式将它们全部删除

chomp @lines;

因为chomp也适用于列表。

STDIN输入来自键盘时,这会引发一个问题,<>因为 EOF 不是自己出现的,因此会等待更多输入。它通常在 Unixy 系统上以Ctrl+D†给出(在 Windows 上为 Ctrl+Z)。

因此,原则上,您可以使用@array = <STDIN>并退出输入,Ctrl+D但这对于预期从键盘输入的输入可能有点尴尬,因为它主要意味着需要逐行处理。如果STDIN来自文件,则不那么不寻常,

script.pl < input.txt

或命令行上的管道

some command with output | script.pl

我们确实得到了 EOF(由EOT提供)。

但我还是会坚持while阅读的习惯STDIN,逐行处理。


  这Ctrl+D就是通常的引用方式,但实际上是dCtrl. 请注意,Ctrland c(标记为Ctrl+C)的作用完全不同;它发送SIGINT信号,如果没有被捕获,则终止整个程序。

于 2017-07-27T22:30:44.683 回答