Why is this program not showing the first line again and again?
#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;
}
ret开发者_如何学运维urn 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;
}
If the contents of testFile is:-
abc
def
ghi
The three printf statements should show "abc" three times.. But the output is:-
abc
def
ghi
I know I am wrong in the concept somewhere. Pls help.
Usage of realloc()
is incorrect.
realloc(line,i+1); // wrong
// OK
void *new_line = realloc(line,i+1);
if (!new_line)
{
free(line);
return NULL;
}
line = new_line;
Because line
is passed by value, it's not changed. The actual re-allocated memory is in the return value. Therefore Edit: just realized that's even though it's a bug, it's not what would cause repeating lines. Other points are still valid.line
remains the same over and over again, and you are seeing the same line over and over again.
What's worse:
- You have a memory leak by losing the newly re-allocated pointer every time.
- You are potentially accessing freed memory, because old
line
value may become invalid after reallocation, if it was reallocated in a different part of the heap. - You are re-allocating memory every character, which is potentially an expensive operation.
But I am passing file pointer by value. So i should get output "abc" again and again
Ah, I understand your confusion.
A file pointer only points to the actual file structure. State such as the current offset are not part of the pointer but are part of the internal structure.
Another way to think about this is that the actual object representing the file is FILE. To get pass-by-reference semantics, you pass a pointer to the object. Since you are passing by reference, each line picks up where the last one left off.
fgetc()
advances the file pointer (which is "where the next character to be read is located"). That's how you're able to call it in a loop and read a whole line of characters.
After it advances past the newline character, it naturally moves on to the next character, which is the beginning of the next line.
You could modify the file pointer with the fseek()
function. For example, calling fseek(inFile, 0, SEEK_SET)
would reset it to the beginning of the file, causing the next fgetc()
call to start over from the first character of the file.
精彩评论