计算文件中每个字母的出现次数?
Posted
技术标签:
【中文标题】计算文件中每个字母的出现次数?【英文标题】:Count occurrences of each letter in a file? 【发布时间】:2013-01-03 18:15:00 【问题描述】:即使文件大小为 4GB 或更大,如何以优化的方式找到字母 A-Z 的出现(忽略大小写)? C++/C 中可能有哪些不同的实现?
一个实现是:
伪代码
A[26]=0
loop through each character ch in file
If isalpha(ch)
A[tolower(ch)-'A']+ = 1
End If
end loop
【问题讨论】:
如果你操作的是4GB的文件,那么这个程序的运行时间将会被磁盘I/O支配。优化计数将毫无意义。您需要优化 I/O 部分。 根据您的应用程序和周围的东西,它可能是一个选项,可以将已经计算的统计数据缓存在磁盘上/在数据库中及其修改时间。只是给出一个想法...... 对不起,伙计。但是对于这样的问题,您必须考虑使用 apache hadoop 和 map reduce。顺便说一句,他们引入的第一个基本问题与您的重复。 @SRINI794,您的磁盘通常没有并行硬件路径。 @SRINI794,这就是 Raymond Chen 试图提出的观点——你可以将计数速度提高 1000 倍,但这并没有什么不同,你还在等待磁盘。更多线程实际上会伤害您,因为它们可能会从磁盘的不同部分读取。 【参考方案1】:我认为剩下的优化不多。
不是为每个元素计算 tolower()-'A'
,而是计算每个字符的出现次数(在 char[256]
累加器中),然后进行区分大小写的计算(可能更有效或不更有效,试试吧) .
一定要使用缓冲输入(fopen
,也许用setvbuf
分配更大的缓冲区)。
例如:
acum[256]=0
loop through each character 'c' in file
acum[c]++
end loop
group counts corresponding to same lowercase/uppercase letters
另外,请记住,这假定为 ASCII 或派生(一个八位字节 = 一个字符)编码。
【讨论】:
必须小心 256 的数组,因为一半的字符值将是负数。A[c+128]++
@MarkRansom:如果使用 getc
和 ch
是 int,则不会。
@leonbloy,有趣的问题。我一直使用fread
或read
一次得到一堆,所以我不太了解getc
的行为。
也许内存映射文件可能有一些好处,但除此之外,这与不分块文件一样好。【参考方案2】:
对于 4GB,这不会是瞬时的。我知道如何更快地完成您正在做的事情。
此外,您的代码不会处理制表符、空格或其他字符。您需要使用isalpha()
,并且只有在返回 true 时才增加计数。
请注意,isalpha()
非常快。但是,同样,如果输入非常大,这段代码不会是即时的。
TCHAR a[26] = 0 ;
for (int i = 0; i < length; i++)
if (isalpha(text[i]))
a[tolower(text[i]) - 'a']++;
【讨论】:
是的,我知道我的执行速度很慢!!我只是想知道是否有更快的方法来实现这个? 我想我已经回答了,除了显示你的代码缺少的东西。以上是关于计算文件中每个字母的出现次数?的主要内容,如果未能解决你的问题,请参考以下文章