我正在参加我的第一个C编程课程,我遇到了一个问题,试图编写一个一次读取一行文本文件的函数。这是我的代码:
#define LINELENGTH 81
int getLine(char* line, FILE* file) {
if (line == NULL) {
line = malloc(sizeof(char) * LINELENGTH);
}
fgets(line, LINELENGTH, file);
int length = strcspn(line, "\n");
if (line[length] == '\n') {
line[length] = '\0';
line = realloc(line, sizeof(char) * (length + 1));
return length;
} else {
char* addThis = NULL;
int addedLength = getLine(addThis, file);
length += addedLength;
line = realloc(line, sizeof(char) * length);
strcat(line, addThis);
free(addThis);
addThis = NULL;
return length;
}
}
int main() {
FILE *text = fopen("test.txt", "r");
char* line = NULL;
getLine(line, text);
printf("The first line is \"%s\"", line);
fclose(text);
free(line);
return 0;
}
我的测试输入文件现在只包含一行“test”
当我运行程序时,我得到“第一行是”(null)“”。不是我所希望的。当我通过调试器中的函数步进时,一切似乎在getLine中正常工作。但是当函数返回时,我剩下的都是null。
感谢任何帮助。感谢。
答案 0 :(得分:2)
对getLine
的调用是按值传递char*
指针。在该函数中对line
的赋值不会导致分配的指针返回给调用者。函数声明应该是:
int getLine(char** line, FILE* file) {...
然后将结果分配给*line
。对函数的调用需要传递地址:
getLine( &line, text );
您还可以在函数内部使用局部变量,然后在返回之前将最终结果分配给*line
。这可能会使代码更容易理解。否则,每次使用line
时,都需要取消引用指针,并且它(我的意见在这里)有点麻烦。因此,可以将函数定义中的参数更改为getLine( char** retLine, ... )
。然后声明char* line;
形式的局部变量。然后在return
语句之前,分配它:
*retLine = line;
一个非常不完整的例子:
int getLine( char **retLine, FILE *file ) {
*retLine = NULL; // make sure we don't return garbage if error occurs
char *line = malloc( ... );
// do stuff with line, fill it up, etc.
...
// assign the final result to the output param
*retLine = line;
return length;
}
这基本上是一个偏好问题。否则,必须进行解除引用。例如,
*line = malloc(...);
int length = strcspn( *line, ... );
等
答案 1 :(得分:1)
“line”是一个指针,你的getLine函数只改变'line'的复制值,它不会改变它自己的“line”指针。对于您的情况,您应该尝试
int main() {
// ..
line = malloc(sizeof(char) * LINELENGTH);
getLine(line, text);
// ..
}
答案 2 :(得分:0)
您需要更改getLine
函数以及调用它的方式,以便它可以修改传递它的指针。现在,您只需在分配或重新分配行时修改函数内的本地副本。
而不是
int getLine(char* line, FILE* file) {
你需要
int getLine(char **line, FILE *file) {
然后,在getLine
内,您需要取消引用line
,只要您使用它来指向它所指向的指针,例如:
*line = malloc(sizeof(char) * LINELENGTH);
...和...
(*line)[length] = '\0';
......以及line
的其他用途。
如果你可以摆脱递归和strcat
,你也可以提高你的功能效率,虽然上面的改变应该让它起作用。
答案 3 :(得分:0)
好像你走了很长一段路,我会做这样的事情:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char line[1000];
int main()
{
FILE *file;
file = fopen("test.txt", "r");
fgets(line, sizeof(line), file);
printf("First line: %s", line);
memset(line, 0, strlen(line));
fclose(file);
return 0;
}
如果需要,您可以将其合并到一个函数中。 或者,如果你想让它列出整个文件,你可以简单地这样做:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char line[1000];
int main()
{
FILE *file;
file = fopen("test.txt", "r");
while(!feof(file))
{
fgets(line, sizeof(line), file);
printf(line);
memset(line, 0, strlen(line));
}
fclose(file);
return 0;
}
答案 4 :(得分:0)
考虑到你没有指针指针。
我建议更改方法签名如下:
char* getLine(int *len, FILE* file);
// instead of assigning the value to line like in your case, return it.
用法是:
int main() {
.
.
.
int length;
char* line = NULL;
line = getLine(&len, text);
.
.
}
另外,我发现你没有使用返回值,即main()中行的长度。所以你可以完全省略长度字段,并有一个像这样的方法定义:
char* getLine(FILE* file);