#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readLine(FILE *inFile) //Simply reads line in a text file till "\n"
{
char *line = realloc(NULL, 1);
char c;
int i=0;
while (!feof(inFile))
{
c = fgetc(inFile);
if (ferror(inFile)) printf("Error reading");
if (c == 10)
{
realloc(line,i+1);
line[i]= 10;
break;
}
realloc(line, i+1);
line[i++] = c;
}
return line;
}
int main(int argc,char **argv)
{
FILE *inFile;
inFile = fopen("testFile","r");
printf("%s",readLine(inFile));
printf("%s",readLine(inFile));
printf("%s",readLine(inFile));
return 0;
}
如果testFile的内容是: -
abc
def
ghi
三个printf语句应该显示“abc”三次..但输出是: -
abc
def
ghi
我知道我在某个地方的概念是错的。请帮助。
答案 0 :(得分:6)
realloc()
的使用不正确。
realloc(line,i+1); // wrong
// OK
void *new_line = realloc(line,i+1);
if (!new_line)
{
free(line);
return NULL;
}
line = new_line;
由于line
是按值传递的,因此不会更改。实际重新分配的内存在返回值中。 因此 编辑:刚才意识到即使这是一个bug ,它不会导致重复的线条。其他要点仍然有效。line
一遍又一遍地保持不变,你一遍又一遍地看到同一条线。
更糟糕的是:
line
值在重新分配后可能会变得无效,如果它在堆的不同部分重新分配。答案 1 :(得分:4)
fgetc()
使文件指针前进(即“要读取的下一个字符所在的位置”)。这就是你能够在循环中调用它并读取整行字符的方式。
在它超过换行符后,它会自然地移动到下一个字符,即下一行的开头。
您可以使用fseek()
功能修改文件指针。例如,调用fseek(inFile, 0, SEEK_SET)
会将其重置为文件的开头,导致下一个fgetc()
调用从文件的第一个字符重新开始。
答案 2 :(得分:4)
啊,我明白你的困惑。但是我按值传递文件指针。所以我应该一次又一次地输出“abc”
文件指针仅指向实际的文件结构。诸如当前偏移之类的状态不是指针的一部分,而是内部结构的一部分。
另一种思考方式是表示文件的实际对象是FILE。要获取pass-by-reference语义,可以传递指向该对象的指针。由于您是通过引用传递的,因此每一行都会在最后一行停止的位置进行传递。