Pradeep Kumar
Pradeep Kumar

Reputation: 471

fscanf not returning EOF or fscanf going to infinite loop in C

I am trying to write a few lines to a file. After the line are written, when I try to read those lines from file using fscanf it is going into infinite loop. fprintf is working but fscanf is going to an infinite loop.

#include<stdio.h>
#include<stdlib.h>

  void main()
       {
        FILE *fp;
        int roll;
        char name[25];
        float marks;
        char ch;
        fp = fopen("file.txt","w");           
        if(fp == NULL)
        {
            printf("\nCan't open file or file doesn't exist.");
            exit(0);
        }

        do
        {
             printf("\nEnter Roll : ");
             scanf("%d",&roll);

             printf("\nEnter Name : ");
             scanf("%s",name);
             printf("\nEnter Marks : ");
             scanf("%f",&marks);

             fprintf(fp,"%d%s%f",roll,name,marks);

             printf("\nDo you want to add another data (y/n) : ");
             ch = getche();

             }while(ch=='y' || ch=='Y');

            printf("\nData written successfully...");
              
              
              
            printf("\nData in file...\n");

            while((fscanf(fp,"%d%s%f",&roll,name,&marks))!=EOF)
            printf("\n%d\t%s\t%f",roll,name,marks);
                
              

            fclose(fp);
       }

Upvotes: 0

Views: 293

Answers (1)

William Pursell
William Pursell

Reputation: 212198

You have opened the file for writing (mode "w"), so your scanf calls are almost certainly failing. Even if you fix the mode, it is not at all surprising that:

while((fscanf(fp,"%d%s%f",&roll,name,&marks))!=EOF)

goes into an infinite loop. If the next character in the stream is not a valid character in an integer, then scanf will return zero and not consume it. It will repeatedly attempt to read that character as an integer and repeatedly fail. The correct approach here is probably to stop using scanf entirely, but a quick work-around may be something like:

int rv;
while( (rv = fscanf(fp,"%d%s%f",&roll,name,&marks)) != EOF ){
    if( rv == 3 ){
        printf(...);
    } else {
        /* probably the right thing to do is break out of
           the loop and emit an error message, but maybe 
           you just want to consume one character to progress
           in the stream. */
        if( fgetc(fp) == EOF ){
            break;
        }
    }
}

it would be more common to write while( 3 == fscanf(...)) and just emit an error message on bad input, but something like the above kludge might be useful (depending on your use case).

But you need to fix the open mode. Probably you just want to close the file after the write loop (you certainly need to flush it before you can expect to read from the file) and re-open in with mode "r".

Upvotes: 2

Related Questions