c/c++语言开发共享C:清除STDIN

基本上在每个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

      (0)
      上一篇 2020年12月5日
      下一篇 2020年12月5日

      精彩推荐