0

I am trying to write some C code that appends a line of text to a file, and then simply display it line by line. When I open the file in append mode and add a line using fprintf, the line gets added and I can see it when I open the file with a text editor. However when I call a function to display all lines (which works fine before the new text is appended), I get all the lines until the last but excluding the new appended line.

Here is the code I'm working with. The first function just adds a new line, and the second function just reads all the lines. The read_csv() works initially when I haven't appended any lines through code and have just used a text editor to add my initial lines.

void add_record(const char* csv_filename)
{
    FILE *f = fopen(csv_filename,"at");
    char str="My appended line "
    fprintf(f,"%s",str);
    fclose(f);

}
void read_csv(const char* csv_filename)
{
    FILE *f = fopen(csv_filename,"rt");
    char str[MAX];
    fgets(str,MAX,f);
    while(!feof(f))
      { fputs(str,stdout);
        fputs("\n",stdout);
        fgets(str,MAX,f);
      }
    fclose(f);
    
}

Now I found two fixes to my problem but I don't exactly understand why they work.

Fix 1 : Adding an extra fgets() prints the missing appending line when I'm trying to display it, however when I use it to display my original text file it prints the last line twice..so not a good fix.

fgets(str,MAX,f)
while(!feof(f))
      { fputs(str,stdout);
        fputs("\n",stdout);
        fgets(str,MAX,f);
      }
   fgets(str,MAX,f)

Fix 2 : Adding a new line character at the along with the string appended fixes the problem perfectly and everything is smooth. All the lines get displayed when I call read_csv().

char str="My appended line "
    fprintf(f,"%s\n",str)

Looking at the docs for fgets(), it says it reads until either a new line character or eof has reached(whichever occurs first), so I don't understand why my appended line get ignored by fgets().

When fgets() reaches the last line(which it skips) the situation I presume is something like this: it gets a string with " text text text eof",and it breaks out the loop skipping the print statement. But then when I use an extra fgets() outside the while loop it works. Also when I add a new line and the situation is a string like " text text text \n eof", it doesn't quit the loop and goes on to display it.

I would really appreciate if I could get some info on what is happening and why these two fixes work. I suspect it is something to do with the feof detecting an eof or some specifics about fgets but I couldn't find anything satisfactory online.

Thank you so much in advance for taking the time to read and respond.

Community
  • 1
  • 1
Rahul
  • 177
  • 3
  • 9
  • 2
    `while(!feof(f))` is always wrong, you are failing to read after the last line. Why don't you check the return value of `fgets`? – KamilCuk Mar 24 '19 at 02:46
  • Thanks for your reply. Could I ask why the while condition is always wrong? As it displays all lines perfectly if I call it before I have appended a line. – Rahul Mar 24 '19 at 02:49
  • Because then `fgets` does not set `feof` as it quits after reading newline. So the `feof` condition is not set, as the stream didn't read eof. Then the next `fgets` reads zero characters and set's feof. – KamilCuk Mar 24 '19 at 02:50
  • [Why is “while (!feof(file))” always wrong?](https://stackoverflow.com/q/5431941/364696) – ShadowRanger Mar 24 '19 at 02:53
  • I tried checking the return value of **fgets()**, and it was **NULL** just after exiting the loop, which means it reached the end of file, correct? – Rahul Mar 24 '19 at 02:55
  • [fgets()](https://en.cppreference.com/w/c/io/fgets) it means it failed, there may more reasons to fail then end of file. – KamilCuk Mar 24 '19 at 02:58
  • I even checked the value for [feof](https://en.cppreference.com/w/c/io/feof) , which was non-zero meaning the eof indicator was set and that's why **fgets** failed, right? – Rahul Mar 24 '19 at 03:04

0 Answers0