#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».