-4

Please, some one can explain for me why this program does not work ? I'm trying to read and write from the file by using r+. The file test.txt exists and the writing is executed correctly. However, the reading does not work.

int main() {

    FILE* fichier = NULL;
    int age, TAILLE_MAX=10;
    char chaine[TAILLE_MAX];

    fichier = fopen("test.txt", "r+");
    if (fichier != NULL)
    {

        printf("give your age ? ");
        scanf("%d", &age);
        fprintf(fichier, "Hello you have %d year old", age);

        while (fgets(chaine, TAILLE_MAX, fichier) != NULL)
        {
            printf("%s", chaine); //does not print
        }fclose(fichier);
    }

    return 0;
}

By does not work I mean it does not display any thing ! Even if the file contains some the sentence you have ... year old. There is no Error. Just the program does not print the content of the file

Mehdi
  • 1,960
  • 6
  • 32
  • 45

2 Answers2

1

you are writing and reading to file at the same time, which is not good practice, but the reason your code does not work is because of buffering. The fprintf(fichier, "Hello you have %d year old", age); is likely not happening until your fclose(fichier) statement is happening. I added the two statements to your code, see below. Also once you do your fprintf your file pointer fichier is not at the end of the file which is the wrong place for the next thing you try to do which is read the age number you just wrote, so you have to move the file pointer fichier back somehow - I just used rewind which will work if test.txt was a newly created file. Otherwise you will need some method of moving the file pointer fichier backwards just enough to read what you just wrote.

int main() {

FILE* fichier = NULL;
int age, TAILLE_MAX=10;
char chaine[TAILLE_MAX];

fichier = fopen("test.txt", "r+");
if (fichier != NULL)
{

    printf("give your age ? ");
    scanf("%d", &age);
    fprintf(fichier, "Hello you have %d year old", age);

    fflush( fichier );  /* force  write to FILE */
    rewind( fichier );  /* rewind FILE pointer to beginning */

    while (fgets(chaine, TAILLE_MAX, fichier) != NULL)
    {
        printf("%s", chaine); //does not print
    }
}
fclose(fichier);
return 0;
}

in your original code, the statement

while (fgets(chaine, TAILLE_MAX, fichier) != NULL)

fails to read anything and returns NULL, so the printf("%s", chaine); will not happen. This is happening because of output buffering and the fprintf() statement not happening when you think it should.

This output buffering is normal and if you want a printf to happen at that exact moment then you need to use fflush() read here to learn more: Why does printf not flush after the call unless a newline is in the format string?

Community
  • 1
  • 1
ron
  • 889
  • 5
  • 18
  • 1
    You don't need to flush if you're using the same `FILE*`. When you rewind, `fgets()` will use the output buffer if it hasn't flushed it. – Barmar Apr 07 '17 at 20:57
  • good catch, would be same if he used `fseek` instead of `rewind`. I initially wrote it with `fflush` to illustrate the main problem that was happening, then realized the second problem of the file pointer location after a simple `fflush` was used. – ron Apr 07 '17 at 21:06
  • Yes, it's the same. All `stdio` functions share the buffer. – Barmar Apr 07 '17 at 21:21
1

The problem is you try to read from the filehandle after you've written to it.

fichier is like a cursor in an editor, and it only ever has one position in the file. When you open the file with r+ fichier is at the beginning of the file. When you print to fichier it overwrites whatever was at the beginning of the file. Then when you try to read, it reads from where the print left off.

For example, if I start test.txt with some text in it, specifically more than will be printed.

$ cat test.txt
First line
Second line
Third line

Then I run the program.

$ ./test
give your age ? 41
rd line

Notice it printed rd line because that's what's left over after it writes Hello you have 41 year old.

$ cat test.txt
Hello you have 41 year oldrd line

I'm not sure what you're trying to accomplish, but you probably need to fseek to move the cursor to the correct position.


As a side note, wrapping the whole program in if (fichier != NULL) is awkward. And you have no error message if the file does not open, it will quietly and mysteriously do nothing. Instead, check for an error, display an informative message, and exit the program.

#include <string.h>
#include <errno.h>
#include <stdlib.h>

char file[] = "test.txt";
FILE *fichier = fopen(file, "r+");
if (fichier == NULL) {
    fprintf(stderr, "Could not open '%s' for r+: %s\n", file, strerror(errno));
    exit(1);
}

This is known as early exit and makes code much, much simpler. By taking care of errors immediately, the code can follow a happy path without always needing to be nested in a conditional.

Schwern
  • 127,817
  • 21
  • 150
  • 290