如何在 C 中刷新输入流?
我无法在这里刷新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];
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;
}
输出:
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)
I am not able to flush stdin here, is there a way to flush it? If not then how to make getchar()
to take a character as input from user, instead of a "\n" left by scanf()
in the input buffer??
#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;
}
EDIT: updated code, still not working properly
#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:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
fflush(stdin)
是未定义的行为(a)。相反,让scanf
“吃掉”换行符:其他人都认为
scanf
是一个糟糕的选择。相反,您应该使用fgets
和sscanf
:(a) 请参阅,例如,
C11 7.21.5.2 fflush 函数:
fflush(stdin)
is undefined behaviour(a). Instead, makescanf
"eat" the newline:Everyone else makes a good point about
scanf
being a bad choice. Instead, you should usefgets
andsscanf
:(a) See, for example,
C11 7.21.5.2 The fflush function
:更新:您需要在循环末尾添加另一个 getchar() 来消耗 Y/N 后面的 '\n'。我认为这不是最好的方法,但它会让您的代码按现在的方式工作。
我建议将要解析的数据(直到并包括“\n”)读取到缓冲区中,然后使用 sscanf() 解析它。通过这种方式,您可以使用换行符,并且可以对数据执行其他健全性检查。
Update: You need to add another getchar() at the end of your loop to consume the '\n' that follows the Y/N. I don't think this is the best way to go, but it will make your code work as it stands now.
I would suggest reading the data you want to parse (up to and including the '\n') into a buffer and then parse it out using sscanf(). This way you consume the newline and you can perform other sanity checks on the data.
使用它代替 getchar():
Use this instead of getchar():
使用 fflush( stdin ) 不是一个好习惯,因为它具有未定义的行为。一般来说,像 scanf() 这样的函数会在 stdin 中留下尾随换行符。因此,最好使用比 scanf() “更干净”的函数。您可以将 scanf() 替换为 fgets() 和 sscanf() 的组合,并且可以取消 fflush( stdin )。
It's not a good practice to use fflush( stdin ) as it has undefined behavior. Generally, functions like scanf() leaves trailing newlines in stdin. So, it is better to use functions that are "cleaner" than scanf(). You can replace your scanf() with a combination of fgets() and sscanf() and you can do away with fflush( stdin ).
我会推荐很多其他人建议的
fgets()
+sscanf()
方法。您还可以在调用getchar()
之前使用scanf("%*c");
。这基本上会吃掉一个角色。I would recommend the
fgets()
+sscanf()
approach that a lot of other people have suggested. You could also usescanf("%*c");
before the call togetchar()
. That will essentially eat a character.如果您在 Windows 下执行此操作,则可以在 getch() 之前使用 winapi 刷新输入缓冲区。
-或者-
If you are doing this under windows, you can use winapi to flush input buffer before your getch().
-or-
正如其他人已经指出的那样,您不应该将结构写入文件。相反,尝试以格式化的方式写入数据。这样,您的文本文件就可以通过查找最后一个和倒数第二个分隔符(例如分号)来逐行解析。请记住,字符串化浮点字段中可能会出现某些字符,例如
'-'
或'.'
。另一件事是每个人都在推荐相同的 scanf 系列函数,但没有人检查返回值是否等于要读取的字段数。我认为这是一个坏主意,实际上是自找麻烦。即使使用
strtol
/strtod
方式,您也需要进行错误检查:上面的两个代码示例会默默返回,如果您计划使用现有对象来调用它们,那么这很好。时间;不过,请考虑打印一条错误消息,并在文档中说明人们在使用函数时应该检查返回值。
As others already pointed out, you should not write a struct to a file. Instead, try to write the data in a formatted manner. This way your text file can be parsed line-by-line by finding the last and second-to-last delimiters, for example semicolons. Keep in mind that certain characters like
'-'
or'.'
may occur in the stringified float field.The other thing is how everybody keeps recommending the same scanf family of functions, but nobody ever checks whether the return value is equal to the number of fields to be read. I think that is a bad idea, effectively asking for trouble. Even with the
strtol
/strtod
way you need error checking:the two code examples above return silently which is fine if you plan to call them using existing objects all the time; consider printing an error message, though, and illustrate in your documentation that people should check the return values when using your functions.
stdin 不是可刷新的东西,您只能刷新输出流。也就是说,您根本不需要在标准输入上调用刷新。
stdin is not something flushable, you can flush only output streams. I.e. you don't need to call flush on stdin at all.