我正在用C语言编写一个程序来处理文本文件并跟踪每个唯一的单词(通过使用一个结构,该结构具有该单词的char数组和其出现次数的计数)并将此结构存储到数据结构。但是,分配包括:“整个txt文件可能非常大,无法保存在主内存中。请在程序中考虑这一点。”
我下课后问他,他说要一次读X行文本文件(我认为20,000是他的建议?),分析它们并更新结构,直到你到达终点该文件。
任何人都可以帮助解释这样做的最佳方法并告诉我使用哪些功能?我对C.非常非常新。
(我目前的程序对于小文件是准确和正确的,我只需要让它容纳大量文件)。
非常感谢!!
编辑:
fp = fopen(argv[w], "r");
if ((fp) == NULL){
fprintf( stderr, "Input file %s cannot be opened.\n", argv[w] );
return 2;
}
/* other parts of my program here */
char s[MaxWordSize];
while (fscanf(fp,"%s",s) != EOF){
nonAlphabeticDelete(s); // removes non letter characters
toLowerCase(s); //converts the string to lowercase
//attempts to add to data structure
pthread_mutex_lock(&lock);
add(words, &q, s);
pthread_mutex_unlock(&lock);
}
这是有效的,我只需要通过文本文件将其调整为一次X行。
答案 0 :(得分:1)
getline()怎么样? 以下是联机帮助页http://man7.org/linux/man-pages/man3/getline.3.html
中的示例 #define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
FILE *stream;
char *line = NULL;
size_t len = 0;
ssize_t read;
stream = fopen("/etc/motd", "r");
if (stream == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, stream)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
free(line);
fclose(stream);
exit(EXIT_SUCCESS);
}
答案 1 :(得分:0)
最好通过阅读一些手册来完成,但我可以提供一个开端。
FILE *fp;
fp=fopen("fileToRead.txt", "rb");
if (!fp) { /* handle failure! */ }
#define GUESS_FOR_LINE_LENGTH 80
char sentinel = '\0';
while ((sentinel = getc(fp)) != EOF)
{
ungetc(sentinel, fp);
char buffer[20000*GUESS_FOR_LINE_LENGTH];
size_t numRead = fread(buffer, 1, 20000*GUESS_FOR_LINE_LENGTH, fp);
if (numRead < 20000*GUESS_FOR_LINE_LENGTH) { /*last run */ }
/* now buffer has numRead characters */
size_t lastLine = numRead - 1;
while (buffer[lastLine] != '\n') { --lastLine; }
/* process up to lastLine */
/* copy the remainder from lastLine to the front */
/* and fill the remainder from the file */
}
这更像是伪代码。由于您大多数都有一个工作程序,因此您应该将其作为指南。
答案 2 :(得分:0)
首先尝试一次读一行。扫描行缓冲区中的字边界并微调字计数部分。使用哈希表来存储单词和计数似乎是一种很好的方法。使输出可选,以便您可以测量读/解析/查找性能。
然后制作另一个程序,对核心部分使用相同的算法,但使用mmap
读取文件的相当大的部分并扫描内存块。棘手的部分是处理块边界。
比较两个程序对一组巨大文件的输出,确保计数相同。您可以通过多次连接同一文件来创建大文件。
比较时间。使用time
命令行实用程序。禁用此基准测试的输出以专注于读/解析/分析部分。
将时间与wc
或cat - > /dev/null
等其他程序进行比较。一旦获得类似的性能,瓶颈就是从大容量存储中读取的速度,没有太多的空间可以改进。
编辑:看看你的代码,我有这些评论:
fscanf
可能不是正确的工具:至少你应该保护缓冲区溢出。你应该如何处理foo,bar
1个字或2个字?
我建议使用fgets()
或fread
并沿缓冲区移动指针,跳过非字字节,将字节字节转换为小写,间接通过256字节数组,避免复制。
通过预处理器变量使锁定内容可选。如果words
结构仅由单个线程访问,则不需要它。
您是如何实施add
的?什么是q
?