neelanchaljain
neelanchaljain

Reputation: 21

How to use printf() and fprintf() simultaneously together

I was learning about file i/o and stucked, that when i use fprintf() to print a string in a file and then read that string using fscanf() then instead of string it prints some garbage value in output.

#include <stdio.h>

int main ()
{
  FILE *ptr = NULL;
  char string[6] = "Hello";
  char string1[6];

  ptr = fopen ("text.txt", "a+");

  fprintf (ptr, "%s", string);
  fscanf (ptr, "%s", string1);
  printf ("%s", string1);
  
  fclose(ptr);

  return 0;
}

Upvotes: 1

Views: 340

Answers (2)

chqrlie
chqrlie

Reputation: 145307

As posted, the program has undefined behavior because there is no seek operation between the fprintf() output operation and the fscanf() input request.

There are different ways to modify the program:

Resetting the file position at the start of file using rewind(ptr) or fseek(ptr, 0L, SEEK_SET) will cause fscanf() to read the first word in the file, which is not necessarily the one you just wrote as the file is open for append and read. Furthermore, you should give fscanf() a maximum number of characters to read for the word to avoid a buffer overrun. Also check for failure to open the file and report the error.

#include <stdio.h>

int main() {
    FILE *ptr = NULL;
    char string[6] = "Hello";
    char string1[100];

    ptr = fopen("text.txt", "a+");
    if (ptr == NULL) {
        fprintf(stderr, "cannot open text.txt for a+\n");
        return 1;
    }

    fprintf(ptr, "%s", string);   // string written at the end of file
    rewind(ptr);                  // seek back to the beginning of file
    fscanf(ptr, "%99s", string1); // read a word from the file
    printf("%s\n", string1);
  
    fclose(ptr);

    return 0;
}

If you intent to re-read the word you just wrote, you should save the offset of the end of file and seek back to it, or seek back relative to the current position:

#include <stdio.h>
#include <string.h>

int main() {
    FILE *ptr = NULL;
    char string[6] = "Hello";
    char string1[100];

    ptr = fopen("text.txt", "a+");
    if (ptr == NULL) {
        fprintf(stderr, "cannot open text.txt for a+\n");
        return 1;
    }

    fprintf(ptr, "%s", string);   // string written at the end of file
    fseek(ptr, -strlen(string), SEEK_CUR); // seek back 5 bytes
    fscanf(ptr, "%99s", string1); // re-read the word from the file
    printf("%s\n", string1);
  
    fclose(ptr);

    return 0;
}

Opening the file using "a+" will open an existing file or attempt to create it if it does exist and every output operation will be produced at the end of file. Mixing read and write operations on the same file is very tricky and not something beginner should start with. I recommend you only do one at a time, so open the file for writing or appending, output the string, then close the file and reopen it for reading and read from the file:

#include <stdio.h>

int main() {
    FILE *ptr = NULL;
    char string[6] = "Hello";
    char string1[100];

    ptr = fopen("text.txt", "a");
    if (ptr == NULL) {
        fprintf(stderr, "cannot open text.txt for appending\n");
        return 1;
    }

    fprintf(ptr, "%s", string);   // string written at the end of file
    fclose(ptr);

    ptr = fopen("text.txt", "r");
    if (ptr == NULL) {
        fprintf(stderr, "cannot open text.txt for reading\n");
        return 1;
    }

    fscanf(ptr, "%99s", string1); // read the first word from the file
    printf("%s\n", string1);
  
    fclose(ptr);

    return 0;
}

Upvotes: 1

pm100
pm100

Reputation: 50210

Your best bet is to close the file and reopen it if you intend to read back what you just wrote. You can have a file open for read and write but its just asking for trouble

#include <stdio.h>

int main ()
{
  FILE *ptr = NULL;
  char string[6] = "Hello";
  char string1[6];

  ptr = fopen ("text.txt", "a+");

  fprintf (ptr, "%s", string);
  fclose(ptr);  <<<<=== close it
  fopen ("text.txt", "r");  <<<<=== reopen in read
  fscanf (ptr, "%s", string1);
  printf ("%s", string1);
  
  fclose(ptr);

  return 0;
}

Upvotes: 0

Related Questions