我的测试中有一个问题:
计算文件中行数和单词数的程序有什么问题?
open F, $ARGV[0] || die $!;
my @lines = <F>;
my @words = map {split /\s/} @lines;
printf "%8d %8d\n", scalar(@lines), scalar(@words);
close(F);
我的推测是:
如果文件中有标点符号,程序会对它们进行计数,例如
abc cba , , ,dce
将是五个字,但另一方面wc
输出相同的结果,因此可能被视为正确的行为。
F
是一个大文件,最好迭代线而不是将其转储到lines
数组中。你有什么不那么琐碎的想法吗?
答案 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)
open
失败,您的程序将会死亡。open
。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;