gpt4 book ai didi

C、解析大型 csv 文件时出现段错误

转载 作者:行者123 更新时间:2023-11-30 20:15:34 25 4
gpt4 key购买 nike

我编写了一个简单的程序,可以打开一个 csv 文件,读取它,创建一个新的 csv 文件,然后只写入一些列(我不想要所有列,并且希望删除一些列将使该文件更易于管理)。该文件有 1.15GB,但是 fopen() 没有问题。在第一个进度 printf() 之后不久,段错误发生在我的 while 循环中。

我只测试了 csv 的前几行,下面的逻辑符合我的要求。当 index == 0 时出现的奇怪部分是由于最后一列的格式为 (xxx, yyy)\n (,在逗号分隔值文件中是很荒谬的)。

这是代码,while循环是问题所在:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
long size;
FILE* inF = fopen("allCrimes.csv", "rb");
if (!inF) {
puts("fopen() error");
return 0;
}
fseek(inF, 0, SEEK_END);
size = ftell(inF);
rewind(inF);

printf("In file size = %ld bytes.\n", size);
char* buf = malloc((size+1)*sizeof(char));
if (fread(buf, 1, size, inF) != size) {
puts("fread() error");
return 0;
}
fclose(inF);
buf[size] = '\0';

FILE *outF = fopen("lessColumns.csv", "w");
if (!outF) {
puts("fopen() error");
return 0;
}

int index = 0;
char* currComma = strchr(buf, ',');
fwrite(buf, 1, (int)(currComma-buf), outF);

int progress = 0;
while (currComma != NULL) {
index++;
index = (index%14 == 0) ? 0 : index;
progress++;
if (progress%1000 == 0) printf("%d\n", progress/1000);

int start = (int)(currComma-buf);
currComma = strchr(currComma+1, ',');
if (!currComma) break;
if ((index >= 3 && index <= 10) || index == 13) continue;

int end = (int)(currComma-buf);
int endMinusStart = end-start;
char* newEntry = malloc((endMinusStart+1)*sizeof(char));
strncpy(newEntry, buf+start, endMinusStart);
newEntry[end+1] = '\0';

if (index == 0) {
char* findNewLine = strchr(newEntry, '\n');
int newLinePos = (int)(findNewLine-newEntry);
char* modifiedNewEntry = malloc((strlen(newEntry)-newLinePos+1)*sizeof(char));
strcpy(modifiedNewEntry, newEntry+newLinePos);
fwrite(modifiedNewEntry, 1, strlen(modifiedNewEntry), outF);
}
else fwrite(newEntry, 1, end-start, outF);
}
fclose(outF);

return 0;
}

编辑:事实证明,问题在于 csv 文件在我没有预料到的地方有 , ,这导致逻辑失败。我最终编写了一个新的解析器,它删除了逗号数量不正确的行。它删除了 243,875 行(约占文件的 4%)。我将发布该代码,因为它至少反射(reflect)了有关 free() 的一些评论:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
long size;
FILE* inF = fopen("allCrimes.csv", "rb");
if (!inF) {
puts("fopen() error");
return 0;
}
fseek(inF, 0, SEEK_END);
size = ftell(inF);
rewind(inF);

printf("In file size = %ld bytes.\n", size);
char* buf = malloc((size+1)*sizeof(char));
if (fread(buf, 1, size, inF) != size) {
puts("fread() error");
return 0;
}
fclose(inF);
buf[size] = '\0';

FILE *outF = fopen("uniformCommaCount.csv", "w");
if (!outF) {
puts("fopen() error");
return 0;
}

int numOmitted = 0;
int start = 0;
while (1) {
char* currNewLine = strchr(buf+start, '\n');
if (!currNewLine) {
puts("Done");
break;
}

int end = (int)(currNewLine-buf);
char* entry = malloc((end-start+2)*sizeof(char));
strncpy(entry, buf+start, end-start+1);
entry[end-start+1] = '\0';

int commaCount = 0;
char* commaPointer = entry;
for (; *commaPointer; commaPointer++) if (*commaPointer == ',') commaCount++;

if (commaCount == 14) fwrite(entry, 1, end-start+1, outF);
else numOmitted++;

free(entry);
start = end+1;
}
fclose(outF);
printf("Omitted %d lines\n", numOmitted);

return 0;
}

最佳答案

您正在分配但从未释放。可能你的内存不足,你的 malloc 之一返回 NULL ,以及随后对 str(n)cpy 的调用段错误。

添加free(newEntry); , free(modifiedNewEntry);紧接着各自的fwrite调用应该可以解决您的内存不足问题。

还请注意,在循环内您计算缓冲区的偏移量 buf其中包含整个文件。这些偏移量保存在 int 类型的变量中对于您正在处理的数字来说,其在您的系统上的最大值可能太小。另请注意,添加大 int s 可能会导致负值,这是导致段错误的另一个可能原因(buf 中的负偏移量会将您带到缓冲区外的某个地址,甚至可能无法读取)。

关于C、解析大型 csv 文件时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18799448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com