啊哈磊_编程从这里起步

标题: 关于do while的疑惑 [打印本页]

作者: 哎呀呀    时间: 2014-3-2 09:38
标题: 关于do while的疑惑
自己写的如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c;
    do
    {
        printf("输入字母\n");
        c=getchar();
        printf("%c\n",c);
  if(c=='y'||c=='Y')
   {
    printf("是\n");
    break;
            }
        else if(c=='n'||c=='N')
   {
    printf("否\n");
    break;
            }
        else
   printf("wrong!\n");
    }
    while(1);
system("pause");
return 0;
}

我想让他提示出入,如果是y就跳出来,是n也会跳出来。
如是不是y和n这两种情况,就重新输入。
但运行结果是
提示输入,我输了下c,然后就提示wrong ,接着又执行了一遍,然后才让我输入,不懂。
以下是运行结果:
-----------/另人糊涂结果/---------------------
输入字母
c                                                 (我就在这输入了一个c,下面就全运行了)
c
wrong!
输入字母                                      (在这一步我什么都没做,直接就往下运行了)

wrong!
输入字母                                     (第二次提示让我输入,)
------------------------------------------------
我不明白我还没有输入为什么就被赋值为空格了,我不明白为什么会跳过第个二输入字母的提示,
求大神解答



作者: rosynirvana    时间: 2014-3-2 09:38
因为你输入的是: c 回车
第一次读取的是c,第二次读取的是回车

读取之后把缓冲区清掉就可以了
作者: cad20020601    时间: 2014-3-2 09:41
沙发。。。。。
作者: 4399APPLE    时间: 2014-3-2 11:54
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6.     char c[100];
  7.     do
  8.     {
  9.         printf("输入字母\n");
  10.         scanf("%s",c);
  11.         printf("%s\n",c);
  12.         if(!(strcmp(c,"y")||!(strcmp(c,"Y"))))
  13.         {
  14.             printf("是\n");
  15.             break;
  16.         }
  17.         else if(!(strcmp(c,"n")||!(strcmp(c,"N"))))
  18.         {
  19.             printf("否\n");
  20.             break;
  21.         }
  22.         else
  23.             printf("wrong!\n");
  24.     }while(1);
  25.     system("pause");
  26.     return 0;
  27. }
复制代码

作者: 哎呀呀    时间: 2014-3-2 12:28
rosynirvana 发表于 2014-3-2 12:20
因为你输入的是: c 回车
第一次读取的是c,第二次读取的是回车

是getchar函数的原因吗?
是不是scanf函数也存在这种情况呢?
我把把刚才那个getchar换成了scanf也存在了
有点乱了被这个搞得.
作者: 哎呀呀    时间: 2014-3-2 12:30
4399APPLE 发表于 2014-3-2 11:54

用getchar函数不可以吗?为什么改成这种结果?不懂哟
作者: 哎呀呀    时间: 2014-3-2 12:37
rosynirvana 发表于 2014-3-2 12:20
因为你输入的是: c 回车
第一次读取的是c,第二次读取的是回车

我用了fflush(stdin)就好了,谢谢您.
作者: 4399APPLE    时间: 2014-3-2 13:09
哎呀呀 发表于 2014-3-2 12:37
我用了fflush(stdin)就好了,谢谢您.

有个地方要你注意:
fflush(stdin);是不正规的作法,并不能“正规的”清除缓冲区
建议这样:
  1. while((c=getchar())!='\n'&&c!=EOF)
  2.     ;
复制代码

另外,while的那个分号不是我打错了,自己去GOO.
作者: 李掌柜    时间: 2014-3-2 14:59
哎呀呀 发表于 2014-3-2 12:37
我用了fflush(stdin)就好了,谢谢您.

把代码贴出来,好让新手知道你们在说什么~~
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5. char c;
  6.     do
  7.     {
  8.         printf("输入字母\n");
  9.         c=getchar();
  10.         printf("%c\n",c);
  11.         if(c=='y'||c=='Y')
  12.         {   
  13.              printf("是\n");
  14.              break;
  15.         }
  16.         else if(c=='n'||c=='N')
  17.         {
  18.                     printf("否\n");
  19.                     break;
  20.             }
  21.             else
  22.             fflush(stdin);    //清空缓存区
  23.                    printf("wrong!\n");
  24.     }while(1);
  25.         system("pause");
  26.         return 0;
  27. }
复制代码

作者: rosynirvana    时间: 2014-3-2 16:47
哎呀呀 发表于 2014-3-2 12:28
是getchar函数的原因吗?
是不是scanf函数也存在这种情况呢?
我把把刚才那个getchar换成了scanf也存在了 ...

getchar一次读一个字符
你输入了两个字符
另一个留在缓冲区内
下一次读取的就是上次输入的回车

fflush(stdin); 只在微软提供的C函数库上有效
这里你不要求严格的除错,那么多写一个getchar就行
  1. printf("输入字母\n");
  2. c=getchar();
  3. getchar();   
  4. printf("%c\n",c);
复制代码


然后就会从缓冲区再读取一个字符,丢弃掉
如果输入没有错误(例如输入一连串的空格再回车的),丢弃掉的就是多余的那个回车
作者: rosynirvana    时间: 2014-3-2 16:55
哎呀呀 发表于 2014-3-2 12:28
是getchar函数的原因吗?
是不是scanf函数也存在这种情况呢?
我把把刚才那个getchar换成了scanf也存在了 ...

scanf非常复杂而且容易出错,近些年的教科书为了省事都直接教用scanf的
其实C最权威的教科书上是在书第七章(一共8章)才提到scanf

这里用scanf大概有两种写法,一种是,大概也就是你出问题的那种
  1. char ch;
  2. scanf("%c", &ch);
复制代码

这里用的占位符是%c,读取一个字符,和getchar一样,会读取缓冲区残留的那个回车

另外一种
  1. char ch[5];
  2. scanf("%4s", ch);
复制代码

这里的占位符是%4s,也就是长度不超过4的字符串。
注意%s占位符会忽略开头的空白字符(空格,回车以及tab制表符),读取到空白字符的时候会结束读取
所以在一个循环连续读取的时候,回车这个占位符就会被忽略,就不再存在这个问题
然后要用字符的时候
  1. if(ch[0] == 'Y')
复制代码
之类的就可以了
作者: rosynirvana    时间: 2014-3-2 17:03
哎呀呀 发表于 2014-3-2 12:30
用getchar函数不可以吗?为什么改成这种结果?不懂哟

最后再说一下缓冲区这个名词

用C标准库函数读取键盘输入(getch之类不是标准库函数),是先把输入的内容送入一个缓冲区内,然后当你确认输入(按了回车键)或者缓冲区满了,才会把输入的内容送给程序处理

仔细考虑一下你输入的过程

第一个字符是c,缓冲区没有刷新,程序认为缓冲区是空的,会等待输入
第二个字符是\n(回车),缓冲区刷新,程序发现缓冲区有东西了,开始处理
程序进行处理,看到了一个getchar(),那么从缓冲区读取一个字符

这时候缓冲区有一个字符\n

第二轮循环,程序发现缓冲区有东西,一个\n,然后getchar()读取,进行处理
就是你看到的结果
作者: 哎呀呀    时间: 2014-3-7 10:39
rosynirvana 发表于 2014-3-2 17:03
最后再说一下缓冲区这个名词

用C标准库函数读取键盘输入(getch之类不是标准库函数),是先把输入的内 ...

非常感恩您细致的讲解,真心感谢。
作者: 哎呀呀    时间: 2014-3-7 10:40
4399APPLE 发表于 2014-3-2 13:09
有个地方要你注意:
fflush(stdin);是不正规的作法,并不能“正规的”清除缓冲区
建议这样:

好的,明白了,非常感谢您。




欢迎光临 啊哈磊_编程从这里起步 (https://bbs.codeaha.com/) Powered by Discuz! X3.2