【发布时间】:2019-08-15 04:30:40
【问题描述】:
我正在尝试编写一个函数来将文本文件转换为 CSV 文件。 输入文件有 3 行以空格分隔的条目。我必须找到一种将一行读入字符串并将输入文件中的三行转换为 CSV 文件中的三列的方法。
文件如下所示:
Jake Ali Maria
24 23 43
Montreal Johannesburg Sydney
我必须把它变成这样的东西:
Jake, 24, Montreal
...etc
我想我可以创建一个 char **line 变量,该变量将保存对三个独立 char 数组的三个引用,一个用于输入文件的三行中的每一行。即,我的目标是让*(line+i) 存储文件的i+1'th 行。
我想避免硬编码char 数组大小,例如
char line1 [999];
fgets(line1, 999, file);
所以我写了一个while循环将fgets一行的片段放入一个预定大小的小缓冲区数组中,然后strcat和realloc根据需要将内存作为字符串存储,*(line+i)作为指向字符串的指针,其中i 第一行是0,第二行是1,依此类推。
这是有问题的代码:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define CHUNK 10
char** getLines (const char * filename){
FILE *file = fopen(filename, "rt");
char **lines = (char ** ) calloc(3, sizeof(char*));
char buffer[CHUNK];
for(int i = 0; i < 3; i++){
int lineLength = 0;
int bufferLength = 0;
*(lines+i) = NULL;
do{
fgets(buffer, CHUNK, file);
buffLength = strlen(buffer);
lineLength += buffLength;
*(lines+i) = (char*) realloc(*(lines+i), (lineLength +1)*sizeof(char));
strcat(*(lines+i), buffer);
}while(bufferLength ==CHUNK-1);
}
puts(*(lines+0));
puts(*(lines+1));
puts(*(lines+2));
fclose(file);
}
void load_and_convert(const char* filename){
char ** lines = getLines(filename);
}
int main(){
const char* filename = "demo.txt";
load_and_convert(filename);
}
这仅适用于i=0。但是,在使用 GDB 进行此操作时,我发现我收到了 realloc(): invalid pointer 错误。缓冲区加载正常,只有当我在 for 循环中为 i=1 调用 'realloc' 时才会崩溃,当我到达第二行时。
我设法在一个小示例中存储了我想要的字符串,以尝试查看发生了什么,但输入都在同一行。也许这与 fgets 从新行读取有关?
我真的很感激这方面的帮助,我整天都被困住了。
非常感谢!
***编辑
我按照建议尝试使用calloc而不是malloc来初始化变量**lines,但我仍然遇到同样的问题。我已将修改添加到我上传的原始代码中。
***编辑
删除文件并重新编译后,上面的方法现在似乎可以工作了。感谢大家帮助我!
【问题讨论】:
-
您分配了
line(这是用词不当,因为它不是一行),它是指向三个char*s 的指针。你永远不会初始化line的内容(也就是说,你永远不会让这三个char*s 中的任何一个指向任何地方)。因此,当您执行realloc(*(line + i), ...)时,第一个参数是未初始化的垃圾。 -
你需要初始化
line中的值。另外,不要使用*(line + i),而是使用line[i],这样更清晰。 -
void load_and_convert无法将lines返回给调用者。它所做的只是创建一个 memory-leak。 -
#define CHUNK 10是你自己最大的敌人。为什么?它违反了基本规则永远不要吝啬缓冲区大小!最好给自己一次阅读一行的最佳机会,而不是零碎阅读。当您真正开始将数据列转换为.csv输出的行时,这将变得非常明显。您需要在每个lines[i]指针指向的内存块中存储一行数据,然后为.csv输出构建另一个char**。 (提示:您的CHUNK-1测试未正确处理验证) -
此外,您是否会拥有一个每行字段多于行的数据文件?如果是这样,您将需要提前仔细计划。包含的数据文件,例如
"Jake Ali Maria Sam"和"24 23 43 31"等...将比恰好具有相同数量的字段和行的数据文件花费更多的精力来处理。
标签: c dynamic-memory-allocation realloc