我正在尝试使用getline()和realloc()将文件读入字符串数组。我过去使用了非常相似的代码来标记字符串,一切正常。我会将示例输入文件视为
1
2
3
4
5
以下是代码:
char** read_input(const char* input_file, char* line){
FILE *fp;
size_t len = 0;
size_t nums = 0;
ssize_t read;
char** res = NULL;
if ((fp = fopen(input_file, "r")) == NULL){
printf("Incorrect file\n", strerror(errno));
exit(EXIT_FAILURE);
}
while ((read = getline(&line, &len, fp)) != -1){
if ((res = realloc(res, sizeof(char*) * ++nums)) == NULL)
exit(EXIT_FAILURE);
char to_strip[sizeof(read) * sizeof(char)];
strcpy(to_strip, line);
if (line[read - 1] == '\n')
to_strip[read - 1] = 0;
else
line[read] = 0;
res[nums - 1] = to_strip;
}
free(line);
if ((res = realloc(res, sizeof(char*) * (nums + 1))) == NULL)
exit(EXIT_FAILURE);
res[nums - 1] = 0;
return res;
}
循环之后,如果我打印数组的内容,我得到:
5
5
5
5
5
尽管如果我在循环中调用print,在每次分配到res之后,我得到正确的数字。这真的让我很难过,因为除了realloc之外我无法看到什么是错的,但我认为realloc保留了数组内容。感谢。
答案 0 :(得分:2)
您正在忙于调用未定义的行为,因为您每次都在重新分配的数组中存储指向to_strip
的指针,并且指针在循环的每次迭代时都超出范围,并在每次迭代时被覆盖这就是你最后看到相同价值的原因。如果您在循环中打印了所有值而不仅仅是当前值,那么您首先会看到1
,然后是2 2
,然后是3 3 3
,然后是4 4 4 4
,最后是{ {1}}。如果在打印结果之前从此函数返回后做了足够的工作,您会看到垃圾,因为该空间将用于其他目的。
您需要复制存储在重新分配的数组中的行。最简单的方法是使用5 5 5 5 5
:
strdup()
不要忘记释放字符串以及指向字符串的指针数组。
请不要忘记在您返回之前关闭您打开的文件。
将res[nums - 1] = strdup(to_strip);
传递给函数似乎很奇怪。它必须是空指针或指向可以传递给line
的空格。既然你在返回之前realloc()
空间,那么调用函数需要知道你已经释放它传递给你的空间 - 而且由于你不知道它有多大,你告诉它free()
它大小为零,所以它必须被释放。没有该参数,界面会更清晰;在函数开头使用本地getline()
。
答案 1 :(得分:1)
这是一个问题:
ssize_t read;
char to_strip[sizeof(read) * sizeof(char)];
strcpy(to_strip, line);
sizeof(read)
- 可能是4或8 - 是为要复制字符串的缓冲区分配的奇怪数量。我想你的意思是char to_strip[ read + 1 ];
。但是,稍后您就有了这句话:
res[nums - 1] = to_strip;
将指向to_strip
的指针放入res
。但是,to_strip
在for
循环结束时不再存在,因此这些将是狂野的指针。如果您的目的是存储从文件中读取的所有文本以供以后访问,那么您将需要为每一行分配内存。
Jonathan Leffler对strdup
的建议可能是最简单的解决方案;感谢他清除我对getline
的错误使用。
您也可以完全取消to_strip
,因为您可以直接在\n
覆盖line
。