字数统计程序有什么问题?

时间:2010-10-21 17:44:08

标签: perl testing count word

我的测试中有一个问题:

  

计算文件中行数和单词数的程序有什么问题?

open F, $ARGV[0] || die $!;
my @lines = <F>;
my @words = map {split /\s/} @lines;
printf "%8d %8d\n", scalar(@lines), scalar(@words);
close(F); 

我的推测是:

  1. 如果文件不存在,程序将不会告诉我们。
  2. 如果文件中有标点符号,程序会对它们进行计数,例如

    abc cba
    , , ,dce
    

    将是五个字,但另一方面wc输出相同的结果,因此可能被视为正确的行为。

  3. 如果F是一个大文件,最好迭代线而不是将其转储到lines数组中。
  4. 你有什么不那么琐碎的想法吗?

3 个答案:

答案 0 :(得分:5)

在第一行,您有一个优先级问题:

open F, $ARGV[0] || die $!;

相同
open F, ($ARGV[0] || die $!);

表示如果文件名为false,则执行die,而不是open失败。你想说

open(F, $ARGV[0]) || die $!;

open F, $ARGV[0] or die $!;

另外,如果$ARGV[0]包含对open有意义的字符,则应使用open的3参数形式。

open F, '<', $ARGV[0] or die $!;

另一方面,分割/\s/意味着你在连续的空白字符之间得到一个“单词”。您可能需要/\s+/,或者作为amphetamachine建议,/\W+/,这取决于您想要如何定义“单词”。

如果该行以空格开头,那么仍会留下空的“单词”问题。您可以在' '上拆分以抑制(这是一种特殊情况),或者您可以先修剪前导空格,或插入grep { length $_ }来清空空“字”,或放弃split并使用不同的方法来计算单词。

逐行处理而不是一次读取整个文件也是一个很好的改进,但它并不像前两个那样重要。

答案 1 :(得分:3)

  • 您的猜想#1不正确:如果open失败,您的程序将会死亡。(请参阅cjm的回答操作顺序。)
  • 你使用的是全局文件句柄,而不是词法变量。
  • 您没有使用open
  • 的三参数形式
  • 你可以从stdin中读取,这为输入提供了更大的灵活性 - 用户可以提供文件,或将输入传递给stdin。
  • 最后,我不会编写自己的代码来解析单词;我会找到CPAN,比如Lingua::EN::Splitter
use strict; use warnings;
use Lingua::EN::Splitter qw(words);
my ($wordcount, $lines);
while (<>)
{
    my $line = $_;
    $lines++;
    $wordcount += scalar(words $line);
}

printf "%8d %8d\n", $lines, $wordcount;

答案 2 :(得分:1)

如果文件不存在,open F, $ARGV[0] || die $!将有效退出。

这里有一些改进:

{local $/; $lines = <F>;} # read all lines at once

my @words = split /\W+/, $lines;