我在C中使用以下程序来过滤大约200,000行的日志文件。但程序在大约12000行后停止响应。任何解释为什么会发生这种情况并解决它? 代码在GCC(windows)中编译。
PS:代码正在正确执行,并为小文件提供所需的输出。
#include<stdio.h>
#include<string.h>
int check(char *url)
{
//some code to filter the data and return either 0 or 1 depending upon input
}
int main()
{
FILE *fpi, *fpo;
fpi=fopen("access.log","r");
fpo=fopen("edited\\filter.txt","w");
char date[11],time[9],ip[16],url[500],temp[3];
while(!feof(fpi))
{
printf(".");
fscanf(fpi," %s %s %s %s %s %s",date,time,temp,ip,temp,url);
if(check(url))
fprintf(fpo,"%s %s %s %s %s %s\n",date,time,temp,ip,temp,url);
}
fclose(fpi);
fclose(fpo);
printf("\n\n\nDONE! :)");
return 0;
}
答案 0 :(得分:6)
输入文件中的一行可能包含一个大于您传递给fscanf()
的字符串变量的字段。它可能会导致缓冲区溢出,从而导致某处无限循环。只是猜测。我建议你用%s
格式字符串中的fscanf()
分隔输出字符串变量的最大长度。
例如,这将确保没有缓冲区溢出并且结果字符串终止:
fscanf(fpi," %10s %8s %2s %15s %49s %2s", date, time, temp, ip, temp, url);
date[10] = '\0';
time[8] = '\0';
ip[15] = '\0';
temp[2] = '\0';
url[499] = '\0';
另外,你正在读两次temp。后者读取将覆盖前者。这是你的意图吗?
另一个改进,假设输入文件是行终止的,并且每个日志都在一个单独的行中,是使用fgets()
来读取一行,然后才使用sscanf()
中间缓冲区。这样,您可以确保没有格式错误超出单行。此外,sscanf返回读取项目的数量,在您的情况下 - 6.检查返回值会更安全。