为什么这个程序不是一次又一次地显示第一行?

时间:2010-01-10 07:35:57

标签: c gcc file-handling

#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

我知道我在某个地方的概念是错的。请帮助。

3 个答案:

答案 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是按值传递的,因此不会更改。实际重新分配的内存在返回值中。 因此line一遍又一遍地保持不变,你一遍又一遍地看到同一条线。 编辑:刚才意识到即使这是一个bug ,它不会导致重复的线条。其他要点仍然有效。

更糟糕的是:

  1. 每次丢失新重新分配的指针都会导致内存泄漏。
  2. 您可能正在访问释放的内存,因为旧的line值在重新分配后可能会变得无效,如果它在堆的不同部分重新分配。
  3. 您正在为每个角色重新分配内存,这可能是一项昂贵的操作。

答案 1 :(得分:4)

fgetc()使文件指针前进(即“要读取的下一个字符所在的位置”)。这就是你能够在循环中调用它并读取整行字符的方式。

在它超过换行符后,它会自然地移动到下一个字符,即下一行的开头。

您可以使用fseek()功能修改文件指针。例如,调用fseek(inFile, 0, SEEK_SET)会将其重置为文件的开头,导致下一个fgetc()调用从文件的第一个字符重新开始。

答案 2 :(得分:4)

  

但是我按值传递文件指针。所以我应该一次又一次地输出“abc”

啊,我明白你的困惑。

文件指针仅指向实际的文件结构。诸如当前偏移之类的状态不是指针的一部分,而是内部结构的一部分。

另一种思考方式是表示文件的实际对象是FILE。要获取pass-by-reference语义,可以传递指向该对象的指针。由于您是通过引用传递的,因此每一行都会在最后一行停止的位置进行传递。