基本上在每个printf之前的windows的代码块我有“fflush(stdin);” 哪个有效。 当我将我的代码复制到Linux时,它不起作用,也没有“fflush(stdin);”的替代方案。 我发现了。 无论我采用哪种方式,输入似乎都没有在缓冲区中清除,或者我的代码中的某些内容不正确。
#include #include #include #include int main() { char pbuffer[10], qbuffer[10], kbuffer[10]; int p=0, q=0, k=0; int r, i, Q, count, sum; char a[3]; a[0]='y'; while(a[0]=='y' || a[0]=='Y') { printf("Enter ap value: n"); fgets(pbuffer, sizeof(pbuffer), stdin); p = strtol(pbuffer, (char **)NULL, 10); printf("Enter aq value: n"); fgets(qbuffer, sizeof(qbuffer), stdin); q = strtol(qbuffer, (char **)NULL, 10); printf("Enter ak value: n"); fgets(kbuffer, sizeof(kbuffer), stdin); k = strtol(kbuffer, (char **)NULL, 10); while(p0) { count++; r = Q%10; sum = sum + pow(r,k); Q = Q/10; } if ( p == sum && i>1 && count==k ) { printf("%dn",p); } p++; a[0]='z'; } while((a[0]!='y') && (a[0]='Y') && (a[0]!='n') && (a[0]!='N')) { printf("Would you like to run again? (y/n) "); fgets(a, sizeof(a), stdin); } } return 0; }
调用fflush(stdin)
不是标准的,因此行为未定义(有关更多信息,请参阅此答案 )。
你可以调用scanf
,传递一个格式字符串,指示函数读取所有内容,包括换行符'n'
,如下所示:而不是在stdin
上调用fflush
。
scanf("%*[^n]%1*[n]");
星号告诉scanf
忽略结果。
另一个问题是调用scanf
将字符读入变量a
,格式说明符为" %s"
:当用户输入非空字符串时,null终止符会创建缓冲区溢出,导致未定义的行为( char a
是一个字符的缓冲区) ;字符串"y"
有两个字符 – {'y', ' '}
,第二个字符写在缓冲区的末尾。 您应该将a
更改a
具有多个字符的缓冲区,并将该限制传递给scanf
:
char a[2]; do { printf("Would you like to run again? (y/n) n") scanf("%1s", a); } while(a[0] !='y' && a[0] !='Y' && a[0]!='n' && a[0]!='N' ); }
我认为你要做的事情比看起来更难。
我对你要做的事情的解释是禁用提前类型,这样如果用户在你的程序处理其他东西时键入一些字符,它们就不会出现在提示符下。 这实际上很难做到,因为它是一个操作系统级别的function。
在打印提示之前,您可以在设备上执行非阻塞读取,直到您在errno中获得EWOULDBLOCK。 或者tcsetattr函数系列可能有所帮助。 看起来有一种方法可以在那里消耗文件描述符的输入,但它可能与fgets / fscanf交互不良
更好的想法是不要担心它。 Unix用户习惯于预先输入类型,你想要的是他们想要的意外行为。
不需要刷新输入缓冲区。
OP使用fgets()
而不是scanf()
进行输入正确,OP应继续使用以下方法:
char a; while(a !='y' && a !='Y' && a!='n' && a!='N' ) { printf("Would you like to run again? (y/n) n"); if (fgets(kbuffer, sizeof(kbuffer), stdin) == NULL) Handle_EOForIOerror(); int cnt = sscanf(kbuffer, " %c", &a); // Use %c, not %s if (cnt == 0) continue; // Only white-space entered }
最好不要使用scanf()
因为它试图一次性处理用户IO和解析,并且做得不好。
某些现有OP的困境源于scanf(" %s", &a);
之后的fgets()
scanf(" %s", &a);
(这是UB,因为它应该是scanf(" %c", &a);
scanf()
将scanf()
与fgets()
混合通常会出现scanf(" %c", &a);
离开Enter或'n'
在输入缓冲区中强制代码要在下一个fgets()
之前调用输入缓冲区。否则fgets()
会得到陈旧的'n'
而不是新的信息行。
通过仅对用户IO使用fgets()
,需要否定刷新。
示例fgets()
包装器
char *prompt_fgets(const char *prompt, char dest, long size) { fputs(prompt, stdout); char *retval = fgets(dest, size, stdin); if (retval != NULL) { size_t len = strlen(dest); if (len > 1 && dest[len-1] == 'n') { // Consume trailing n dest[--len] = ' '; } else if (len + 1 == dest) { // Consume extra char int ch; do { ch == fgetc(stdin); } while (ch != 'n' && ch != EOF); } return retval; }
以上就是c/c++开发分享C:清除STDIN相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/519843.html