fscanf не возвращает EOF или fscanf переходит в бесконечный цикл в C

#c #loops #scanf

Вопрос:

Я пытаюсь записать несколько строк в файл. После записи строки, когда я пытаюсь прочитать эти строки из файла fscanf , он переходит в бесконечный цикл. fprintf работает, но fscanf переходит в бесконечный цикл.

 #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",amp;roll);

             printf("nEnter Name : ");
             scanf("%s",name);
             printf("nEnter Marks : ");
             scanf("%f",amp;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",amp;roll,name,amp;marks))!=EOF)
            printf("n%dt%st%f",roll,name,marks);
                
              

            fclose(fp);
       }
 

Комментарии:

1. Распечатайте полезные сообщения об ошибках, запишите их в stderr и завершите работу с ненулевым значением при фатальной ошибке. напр.: const char *path = "file.txt"; fp = fopen(path,"w"); if(fp == NULL) { perror(path); exit(EXIT_FAILURE); }

2. Никогда не используйте %s без максимальной ширины поля, которая не более чем на единицу меньше размера записываемого буфера. например scanf("$s",name);

3. Вы открыли файл для записи. Почему вы fscanf вообще рассчитываете работать?

Ответ №1:

Вы открыли файл для записи (режим «w»), поэтому ваши scanf вызовы почти наверняка завершаются неудачно. Даже если вы исправите режим, совсем не удивительно, что:

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

входит в бесконечный цикл. Если следующий символ в потоке не является допустимым символом целого числа, то scanf он вернет ноль и не будет его использовать. Он будет неоднократно пытаться прочитать этот символ как целое число и неоднократно терпеть неудачу. Правильный подход здесь, вероятно, состоит в том, чтобы scanf полностью прекратить использование, но быстрый обходной путь может быть чем-то вроде:

 int rv;
while( (rv = fscanf(fp,"%d%s%f",amp;roll,name,amp;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;
        }
    }
}
 

чаще всего было бы писать while( 3 == fscanf(...)) и просто выдавать сообщение об ошибке при неправильном вводе, но что-то вроде приведенного выше клуда может быть полезно (в зависимости от вашего варианта использования).

Но вам нужно исправить открытый режим. Вероятно, вы просто хотите закрыть файл после цикла записи (вам, безусловно, нужно очистить его, прежде чем вы сможете ожидать чтения из файла) и снова открыть в режиме «r».