我正在尝试使用 C 中的脚本处理一个 250MB 的文件。该文件基本上是一个数据集,我只想读取其中的一些列,并且(更重要的是)将其中的一个(最初是一个字符串)分解为一系列人物。
但是,即使我有足够的 RAM 可用,每次运行时代码都会被 konsole(使用 KDE Neon)杀死。
来源如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *arquivo;
char *line = NULL;
size_t len = 0;
int i = 0;
int j;
int k;
char *vetor[500];
int acertos[45];
FILE *licmat = fopen("licmat.csv", "w");
//creating the header
fprintf(licmat,"CO_CATEGAD,CO_UF_CURSO,ACERTO09,ACERTO10,ACERTO11,ACERTO12,ACERTO13,ACERTO14,ACERTO15,ACERTO16,ACERTO17,ACERTO18,ACERTO19,ACERTO20,ACERTO21,ACERTO22,ACERTO23,ACERTO24,ACERTO25,ACERTO26,ACERTO27,ACERTO28,ACERTO29,ACERTO30,ACERTO31,ACERTO32,ACERTO33,ACERTO34,ACERTO35\n");
if ((arquivo = fopen("MICRODADOS_ENADE_2017.csv", "r")) == NULL) {
printf ("\nError");
exit(0);
}
//reading one line at a time
while (getline(&line, &len, arquivo)) {
char *ptr = strsep(&line,";");
j=0;
//breaking the line into a vector based on ;
while(ptr != NULL)
{
vetor[j]=ptr;
j=j+1;
ptr = strsep(&line,";");
}
//filtering based on content
if (strcmp(vetor[4],"702")==0 && strcmp(vetor[33],"555")==0) {
//copying some info
fprintf(licmat,"%s,%s,",vetor[2],vetor[8]);
//breaking the string (32) into isolated characters
for (k=0;k<27;k=k+1) {
fprintf(licmat,"%c", vetor[32][k]);
if (k<26) {
fprintf(licmat,",");
}
}
fprintf(licmat,"\n");
}
i=i+1;
}
free(line);
fclose(arquivo);
fclose(licmat);
}
Run Code Online (Sandbox Code Playgroud)
输出是完美的,直到脚本被终止。输出文件只有 640KB 长,只有大约 10000 行。
可能是什么问题?
在我看来,您似乎错误地处理了由 管理的内存缓冲区getline()- 根据需要分配/重新分配 - 通过使用strsep(),这似乎操纵了相同的指针值。
一旦line已更新,以反映该行一些其他的元素,它不再指向分配内存的开始,然后轰下一次getline()需要用它做任何事情。
使用不同的变量传递给strsep():
while (getline(&line, &len, arquivo) > 0) { // use ">=" if you want blank lines
char *parseline = line;
char *ptr = strsep(&parseline,";");
// do the same thing later
Run Code Online (Sandbox Code Playgroud)
这里的关键是:你不允许在最后(你这样做)使用lineother的值free(),并且你也不能让任何其他例程这样做。
编辑:更新以反映getline()在错误时返回 <0 (h/t to @user3121023)