每次输入后刷新stdin - 哪种方法不是错误的?

Ase*_*sal 6 c flush

Mark Lakata指出,垃圾无法正常在我的问题我定义想出了这一点.我会保持更新,以避免混淆.


我试图获得一个函数,我可以在提示用户输入之前调用,如printf("Enter your choice:);跟随a,scanf并确保只有在提示后输入的内容才会被scanf作为有效输入扫描.

据我所知,所需的功能是完全冲洗标准输入的东西.这就是我想要的.因此,对于此功能而言"garbage",用户输入中的所有内容,即在该用户提示之前的整个用户输入.


scanf()在C中使用时,总是存在输入缓冲区中存在额外输入的问题.所以我在寻找一个我在每次scanf调用后调用的函数来解决这个问题.我用这个,这个,这个这个来得到这些答案

//First approach
scanf("%*[^\n]\n");

//2ndapproach
scanf("%*[^\n]%*c");

//3rd approach
int c;
while((c = getchar()) != EOF) 
    if (c == '\n') 
        break;
Run Code Online (Sandbox Code Playgroud)

所有这三个都是通过命中试验和参考文献找到的.但是在我的所有代码中使用任何这些代码之前,我想知道这些代码中是否有任何错误?

编辑:

感谢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);
}
Run Code Online (Sandbox Code Playgroud)

我使用了以下2个输入

第一次测试输入(2个换行但在垃圾输入中间没有空格)

abhabdjasxd


23
bbhvdahdbkajdnalkalkd



46
Run Code Online (Sandbox Code Playgroud)

对于第一个,我通过printf语句得到了以下输出

23
46
Run Code Online (Sandbox Code Playgroud)

即两个代码都正常工作.

第二个测试输入:(2个在垃圾输入中间有空格的换行符)

hahasjbas asasadlk


23
manbdjas sadjadja a


46
Run Code Online (Sandbox Code Playgroud)

对于第二个,我通过printf语句获得了以下输出

23
3
Run Code Online (Sandbox Code Playgroud)

因此我发现第二个不会处理额外的垃圾输入空格.因此,它不是垃圾输入的万无一失.

我决定尝试第三个测试用例(垃圾包括非空白字符前后的换行符)

``
hahasjbas asasadlk


23

manbdjas sadjadja a


46
Run Code Online (Sandbox Code Playgroud)

答案是

3
3
Run Code Online (Sandbox Code Playgroud)

即在这个测试案例中都失败了.

Jer*_*fin 9

前两个略有不同:它们都读取并忽略所有字符直到新行.然后第一个跳过所有连续的空格,因此在执行之后,您读取的下一个字符将是非空格.

第二个读取并忽略字符,直到它遇到一个新行然后再读取(并丢弃)一个字符.

如果您有(例如)双倍行距文本,则会显示差异,例如:

line 1

line 2
Run Code Online (Sandbox Code Playgroud)

让我们假设你读到了第1行中间的某个地方.如果你执行第一个,你读入的下一个字符将是第2行的'l'.如果你执行第二个字符,你读到的下一个字符将是是第1行和第2行之间的新行.

至于第三个,如果我要做这个,我会做类似的事情:

int ch;
while ((ch=getchar()) != EOF && ch != '\n')
    ;
Run Code Online (Sandbox Code Playgroud)

...是的,这确实可以正常工作 - &&强制一个序列点,所以首先评估它的左操作数.然后有一个序列点.然后,当且仅当左操作数被求值时true,它才会计算其右操作数.

至于性能差异:既然你正在处理I/O,那么所有这些都将永远受I/O约束的问题几乎没有.尽管它有明显的复杂性,但scanf(和公司)通常是经过多年使用并经过多年精心优化的代码.在这种情况下,手动循环可能会慢得多(例如,如果代码getchar不是内联扩展的)或者它可能是大约相同的速度.如果编写标准库的人不称职,那么唯一可能显着提高速度的方法就是它.

至于可维护性:IMO,任何声称知道C的人都应该知道扫描集的转换scanf.这既不是新的也不是火箭科学.任何不了解它的人都不是一个称职的C程序员.