我正在尝试获取一个函数,我可以在提示用户输入之前调用printf(“输入您的选择:);然后执行scanf并确保只有在提示后输入的内容才会被scanf扫描为有效输入.
据我所知,所需的功能是完全冲洗标准输入的东西.这就是我想要的.因此,出于该功能的目的,“垃圾”是用户输入中的所有内容,即在该用户提示之前的整个用户输入.
在C中使用scanf()时,总是存在输入缓冲区中存在额外输入的问题.所以我在寻找一个我在每次scanf调用后调用的函数来解决这个问题.我使用this,this,this和this来获得这些答案
//First approach scanf("%*[^\n]\n"); //2ndapproach scanf("%*[^\n]%*c"); //3rd approach int c; while((c = getchar()) != EOF) if (c == '\n') break;
所有这三个都是通过命中试验和参考文献找到的.但是在我的所有代码中使用任何这些代码之前,我想知道这些代码中是否有任何错误?
编辑:
感谢Mark Lakata第3个错误.我在问题中纠正了它.
EDIT2:
在Jerry Coffin回答后,我在代码中使用该程序测试了前两种方法:使用GNU GCC编译器阻止IDE 12.11(版本未在编译器设置中声明).
#include<stdio.h> int main() { int x = 3; //Some arbitrary value //1st one scanf("%*[^\n]\n"); scanf("%d",&x); printf("%d\n",x); x = 3; //2nd one scanf("%*[^\n]%*c"); scanf("%d",&x); printf("%d",x); }
我使用了以下2个输入
第一次测试输入(2个换行但在垃圾输入中间没有空格)
abhabdjasxd 23 bbhvdahdbkajdnalkalkd 46
对于第一个,我得到了printf语句的以下输出
23 46
即两个代码都正常工作.
第二个测试输入:(2个在垃圾输入中间有空格的换行符)
hahasjbas asasadlk 23 manbdjas sadjadja a 46
对于第二个,我得到了printf语句的以下输出
23 3
因此我发现第二个不会处理额外的垃圾输入空格.因此,它不是垃圾输入的万无一失.
`` hahasjbas asasadlk 23 manbdjas sadjadja a 46
答案是
3 3
即在这个测试案例中都失败了.
解决方法
第二个读取并忽略字符,直到它遇到一个新行然后再读取(并丢弃)一个字符.
如果您有(例如)双倍行距文本,则会显示差异,例如:
line 1 line 2
让我们假设你读到了第1行中间的某个地方.如果你执行第一个,你读入的下一个字符将是第2行的’l’.如果你执行第二个字符,你读到的下一个字符将是是第1行和第2行之间的新行.
至于第三个,如果我要做这个,我会做类似的事情:
int ch; while ((ch=getchar()) != EOF && ch != '\n') ;
……是的,这确实可行 – &&强制执行序列点,因此首先计算其左操作数.然后有一个序列点.然后,当且仅当左操作数计算为true时,它才会计算其右操作数.
至于性能差异:既然你正在处理I / O,那么所有这些都将永远受I / O约束的问题几乎没有.尽管其显而易见的复杂性,但scanf(和公司)通常是经过多年使用并经过多年精心优化的代码.在这种情况下,手动循环可能会慢得多(例如,如果getchar的代码没有内联扩展),或者它可能大约相同的速度.如果编写标准库的人不称职,那么唯一可能显着提高速度的方法就是它.
至于可维护性:IMO,任何声称知道C的人都应该知道scanf的扫描集转换.这既不是新的也不是火箭科学.任何不了解它的人都不是一个称职的C程序员.