每次输入后刷新stdin – 哪种方法不是错误的?
在Mark Lakata指出在我的问题中没有正确定义垃圾之后我想出了这个.我会保持更新,以避免混淆.
我正在尝试获取一个函数,我可以在提示用户输入之前调用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("%dn",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程序员. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |