刷新输入流C的问题

我无法在这里刷新stdin,有没有办法刷新stdin?如果没有,那么如何使getchar()从用户输入一个字符作为输入,而不是输入缓冲区中scanf留下的“\ n”? ?

 #include“stdio.h”#include“stdlib.h”int main(int argc,char * argv []){FILE * fp;  char another ='y';  struct emp {char name [40]; 年龄; 漂浮bs;  }; 结构;  if(argc!= 2){printf(“请写1个目标文件名\ n”);  } fp = fopen(argv [1],“wb”);  if(fp == NULL){puts(“无法打开文件”); 出口(1);  } while(another =='y'){printf(“\ n输入名称,年龄和基本工资”);  scanf(“%s%d%f”,e.name,&e.age,&e.bs); 的fwrite(&E,的sizeof(e)中,1,FP);  printf(“添加另一条记录(Y / N)”);  fflush(标准输入); 另一= getchar函数();  } fclose(fp); 返回0;  } 

编辑: – 更新的代码,仍然无法正常工作

 #include“stdio.h”
 #include“stdlib.h”

 int main(int argc,char * argv []){
     FILE * fp;
     char another ='y';
     struct emp {
         char name [40];
        年龄;
        漂浮bs;
     };
    结构;
     unsigned int const BUF_SIZE = 1024;
     char buf [BUF_SIZE];

     if(argc!= 2){
         printf(“请写1个目标文件名\ n”);
     }
     FP =的fopen(argv的[1], “WB”);
     if(fp == NULL){
         puts(“无法打开文件”);
        出口(1);
     }
    而(另一个=='y'){
         printf(“\ n输入名称,年龄和基本工资:”);
         fgets(buf,BUF_SIZE,stdin);
         sscanf(buf,“%s%d%f”,e.name,&e.age,&e.bs);
        的fwrite(&E,的sizeof(e)中,1,FP);
         printf(“添加另一条记录(Y / N)”);
        另一= getchar函数();
     }
     FCLOSE(FP);
    返回0;
 }

输出为: - 

 dev @ dev-laptop:〜/ Documents / c ++ _ prac / google_int_prac $ ./a.out emp.dat

输入姓名,年龄和基本工资:deovrat 45 23
添加另一条记录(Y / N)y

输入姓名,年龄和基本工资:添加另一个记录(是/否)y

输入姓名,年龄和基本工资:添加另一条记录(是/否)

更新:您需要在循环结束时添加另一个getchar()以使用Y / N后面的’\ n’。 我不认为这是最好的方法,但它会使你的代码现在正常运作。

 while(another=='y') { printf("\nEnter name,age and basic salary : "); fgets(buf, BUF_SIZE, stdin); sscanf(buf, "%s %d %f", e.name, &e.age, &e.bs); fwrite(&e,sizeof(e),1,fp); printf("Add another record (Y/N)"); another=getchar(); getchar(); } 

我建议将要解析的数据(最多包括’\ n’)读入缓冲区,然后使用sscanf()解析出来。 这样您就可以使用换行符,并且可以对数据执行其他健全性检查。

fflush(stdin)是未定义的行为(a) 。 相反,让scanf “吃掉”换行符:

 scanf("%s %d %f\n", e.name, &e.age, &e.bs); 

其他人都对scanf是一个糟糕的选择提出了一个很好的观点。 相反,你应该使用fgetssscanf

 const unsigned int BUF_SIZE = 1024; char buf[BUF_SIZE]; fgets(buf, BUF_SIZE, stdin); sscanf(buf, "%s %d %f", e.name, &e.age, &e.bs); 

(a)参见,例如, C11 7.21.5.2 The fflush function

int fflush(FILE *stream) – 如果指向输入流或未输入最新操作的更新流,则fflush函数会将该流的任何未写入数据传递到主机环境以写入文件; 否则,行为未定义。

使用它而不是getchar():

  char another[BUF_SIZE] = "y"; while( 'y' == another[0] ) { printf( "\nEnter name,age and basic salary : " ); fgets( buf, BUF_SIZE, stdin ); sscanf( buf, "%s %d %f", e.name, &e.age, &e.bs ); fwrite( &e, sizeof(e) , 1, fp ); printf( "Add another record (Y/N)" ); fgets( another, BUF_SIZE, stdin ); } 

使用fflush(stdin)并不是一个好习惯,因为它有未定义的行为。 通常,像scanf()这样的函数会在stdin中留下尾随的换行符。 因此,最好使用比scanf()更“干净”的函数。 你可以用fgets()和sscanf()的组合替换你的scanf(),你可以取消fflush(stdin)。

我会推荐很多其他人建议的fgets() + sscanf()方法。 你也可以使用scanf("%*c"); 在调用getchar() 。 这基本上会吃一个角色。

如果你在windows下这样做,你可以使用winapi在你的getch()之前刷新输入缓冲区。

 #include  hStdin = GetStdHandle(STD_INPUT_HANDLE); FlushConsoleInputBuffer(hStdin); 

-要么-

 #include  FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); 
  • 正如其他人已经指出的那样,你不应该在文件中写一个结构。 相反,尝试以格式化方式编写数据。 这样,您可以通过查找最后和倒数第二个分隔符(例如分号)逐行解析文本文件。 请记住某些字符,如'-''.' 可能出现在字符串化的浮点字段中。

     int write_data(FILE *fh, struct emp *e) { if(fh == NULL || e == NULL) return -1; fprintf(fh, "%s;%d;%f", e->name, e->age, e->bs); return 0; } 
  • 另一件事是每个人如何继续推荐相同的scanf系列函数,但没有人会检查返回值是否等于要读取的字段数。 我认为这是一个坏主意,有效地要求麻烦。 即使使用strtol / strtod方式,您也需要进行错误检查:

     int parse_int(char *buf, long *result) { if(buf == NULL || result == NULL) return -1; errno = 0; *result = strtoul(buf, NULL, 0); if(errno != 0) { perror("strtoul"); return -1; } return 0; } 
  • 上面的两个代码示例以静默方式返回,如果您打算一直使用现有对象调用它们,这很好; 但是,请考虑打印错误消息,并在文档中说明人们在使用您的函数时应检查返回值。

stdin不是可以冲洗的东西,你只能刷新输出流。 即你根本不需要在stdin上调用flush。