【问题标题】:How do I make the STDIN in the Array stop? (PERL) [duplicate]如何使阵列中的 STDIN 停止? (PERL)[重复]
【发布时间】:2018-01-03 20:14:05
【问题描述】:

我的@array 不会停止接受 STDIN...

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

【问题讨论】:

  • 这是很奇怪的代码,可能有错误,而且逻辑复杂。你想做什么?
  • 我正在尝试使用标准输入并且对标准输入有限制...
  • 我正在制作一个有输入的数组,但我希望数组的限制只有五个
  • 你说的是字符数,还是中间有空格的项目数?向我们展示一些输入...
  • Duplicate ... 不幸的是,由于另一个原因,我已经投票结束这个问题,但最好以重复的形式关闭。

标签: arrays perl defined undef


【解决方案1】:

如上所述,将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 中详细说明了其中的大部分内容,但我想在从文件句柄读取时解决context 的业务。

“钻石”运算符&lt;&gt; 是上下文感知的。来自I/O Operators (perlop)

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

在通常的 while 循环中,&lt;&gt; 在标量上下文中

while (my $line = <$fh>)

它与while (&lt;$fh&gt;) 相同,因为它默认分配给$_ variable,一个标量。

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

my @lines = <$fh>;

然后&lt;&gt; 运算符在列表上下文中工作。它读取所有行,直到看到 EOF(文件结尾),此时它返回所有行,这些行分配给 @lines。请记住,每一行都有其换行符。您可以通过

将它们全部删除
chomp @lines;

因为chomp 也适用于列表。

对于STDIN,当输入来自键盘时,这会引发一个问题,因为&lt;&gt; 会等待更多输入,因为 EOF 不会自行出现。它通常在 Unixy 系统上以 Ctrl+D 给出(在 Windows 上为 Ctrl+Z)。

因此,原则上,您可以使用@array = &lt;STDIN&gt; 并使用Ctrl+D 退出输入,但这对于预期的键盘输入可能有点尴尬,因为它主要意味着需要逐行处理。如果STDIN 来自一个文件,这并不罕见,

script.pl < input.txt

或者命令行上的管道

some command with output | script.pl

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

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


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

【讨论】:

  • 谢谢,这帮了很多忙,但是您知道其他方法吗?这是唯一的方法吗?因为从我读过的文章中,我相信还有另一种方法可以做到吗?我不确定
  • @Soup 那么,什么样的“其他方式”?有许多方法来做事。但是当谈到STDIN 时,这几乎就是它的完成方式。逐行执行,从每个 (chomp) 中删除换行符。完成后退出
  • 我不确定我是否理解,所以这里有一点。 STDIN 是指从终端到程序的输入,&lt; &gt; 是从内部“文件句柄”读取的运算符。因此,只要您的程序有while (&lt;STDIN&gt;),它就会停在该行并等待用户输入内容。它在标准输入 (STDIN) 处等待。一旦用户在他们输入的内容后点击返回,该行从&lt;&gt; 运算符返回,while 的主体运行,然后返回等待更多。这个过程是逐行进行的,不涉及数组。
  • 为什么大家都想read five lines from STDIN
  • @SinanÜnür Hah ... :) 至少这里只是一个数字,5(在代码中)
【解决方案2】:
my @array = undef;
while (@array = undef){

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

my @array = undef;

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

my @array = ();

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

my @array;

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

while (@array = undef) {

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

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

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

my $number_of_elements = @an_array;

ifwhile 条件中的布尔逻辑检查是单个标量值。所以如果你想检查一个数组是否包含任何元素,你可以使用这样的代码:

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

当数组包含元素时循环,你可以简单地写:

while (@array) {
  # do something
}

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

while (!@array) {
  # do something
}

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

until (@array) {
  # do something
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2016-09-29
    • 2010-12-22
    • 2017-01-11
    相关资源
    最近更新 更多