我无法在这里刷新stdin,有没有办法刷新stdin?如果没有,那么如何让getchar()从用户输入一个字符作为输入,而不是扫描文件中的“\ n”输入缓冲区??
#include "stdio.h" #include "stdlib.h" int main(int argc,char*argv[]) { FILE *fp; char another='y'; struct emp { char name[40]; int age; float bs; }; struct emp e; if(argc!=2) { printf("please write 1 target file name\n"); } fp=fopen(argv[1],"wb"); if(fp==NULL) { puts("cannot open file"); exit(1); } while(another=='y') { printf("\nEnter name,age and basic salary"); scanf("%s %d %f",e.name,&e.age,&e.bs); fwrite(&e,sizeof(e),1,fp); printf("Add another record (Y/N)"); fflush(stdin); another=getchar(); } fclose(fp); return 0; }
编辑: - 更新的代码,仍然无法正常工作
#include "stdio.h" #include "stdlib.h" int main(int argc,char*argv[]) { FILE *fp; char another='y'; struct emp { char name[40]; int age; float bs; }; struct emp e; unsigned int const BUF_SIZE = 1024; char buf[BUF_SIZE]; if(argc!=2) { printf("please write 1 target file name\n"); } fp=fopen(argv[1],"wb"); if(fp==NULL) { puts("cannot open file"); exit(1); } 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(); } fclose(fp); return 0; } output for this is :- dev@dev-laptop:~/Documents/c++_prac/google_int_prac$ ./a.out emp.dat Enter name,age and basic salary : deovrat 45 23 Add another record (Y/N)y Enter name,age and basic salary : Add another record (Y/N)y Enter name,age and basic salary : Add another record (Y/N)
答案 0 :(得分:9)
fflush(stdin)
是未定义的行为(a)。相反,让scanf
“吃掉”换行符:
scanf("%s %d %f\n", e.name, &e.age, &e.bs);
其他人都认为scanf
是一个糟糕的选择。相反,您应该使用fgets
和sscanf
:
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)
- 如果 stream 指向输入流或未输入最新操作的更新流, fflush 函数会导致任何未写入的操作要传递到主机环境的该流的数据,以写入该文件; 否则,行为未定义。
答案 1 :(得分:6)
更新:您需要在循环结束时添加另一个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()解析出来。这样您就可以使用换行符,并且可以对数据执行其他健全性检查。
答案 2 :(得分:3)
使用此代替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 );
}
答案 3 :(得分:2)
使用fflush(stdin)并不是一个好习惯,因为它有未定义的行为。通常,像scanf()这样的函数会在stdin中留下尾随的换行符。因此,最好使用比scanf()更“干净”的函数。你可以用fgets()和sscanf()的组合替换你的scanf(),你可以取消fflush(stdin)。
答案 4 :(得分:2)
我会推荐许多其他人建议的fgets()
+ sscanf()
方法。您也可以在致电scanf("%*c");
之前使用getchar()
。这基本上会吃掉一个角色。
答案 5 :(得分:1)
如果你在windows下这样做,你可以使用winapi在你的getch()之前刷新输入缓冲区。
$I->seeResponseMatchesJsonType([
'user' => 'null|string'
]);
-OR -
#include <windows.h>
hStdin = GetStdHandle(STD_INPUT_HANDLE);
FlushConsoleInputBuffer(hStdin);
答案 6 :(得分:1)
正如其他人已经指出的那样,你不应该在文件中写一个结构。相反,尝试以格式化方式编写数据。这样,您可以通过查找最后和倒数第二个分隔符(例如分号)逐行解析文本文件。请注意,字符串化的浮点字段中可能会出现'-'
或'.'
等特定字符。
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;
}
上面的两个代码示例以静默方式返回,如果您打算一直使用现有对象调用它们,这很好;但是,请考虑打印错误消息,并在文档中说明人们在使用您的功能时应检查返回值。
答案 7 :(得分:0)
stdin不可刷新,您只能刷新输出流。即您根本不需要在stdin上调用flush。