有人可以解释这个输出吗?

时间:2013-07-14 06:29:41

标签: c scanf undefined-behavior

当我遇到这个时,我正在经历一些程序。

#include<stdio.h>
void main()
{
char z;
do
{
    printf("1st line\n");
    printf("2nd line\n");
            scanf("%c",&z);

    switch(z)
    {
        case 'a':printf("this is case a\n");
            break;
        case 'b':printf("this is case b\n");
            break;
        case 'c':printf("Exit\n");
            return;
            break;
        default:
            printf("this is default\n");
            break;
    }
}while(1);

}

第一次输入时,输出正确。但是在给出第一个输入并且第二次开始循环之后,根本不执行scanf语句。 printf语句虽然执行,但也是默认情况。

  

第1行
  第二行
  b
  这是案例b
  第1行
  第二行
  这是默认的   第1行
  第二行

3 个答案:

答案 0 :(得分:6)

当您为第一次b来电输入scanf时,您也点击了。当scanf("%c", &z)处理此输入时,它会在输入流中保留换行符。

第二组输出是由scanf读取b后面的换行符所致。由于\n既不是a,也不是b,也不是c,因此会遇到默认情况。

您可以通过修改scanf字符串来修复行为,使其更符合您的期望:

scanf(" %c", &z);

注意%c之前的空格字符。这将导致scanf在处理输入之前跳过空格字符(包括换行符)。

答案 1 :(得分:4)

  1. int main()

  2. 此处没有未定义的行为。只是scanf()不能像你认为的那样发挥作用。 %c消耗一个角色。 A 字符。 一个。并且它不会消耗在您按Enter后在stdin缓冲区中留下的换行符。 (所以“第二个scanf没有被执行”不是真的 - 它被执行并且它处理剩下的任何东西。)现在,换行符不是a,b或c中的任何一个,所以{{1} }语句继续执行switch标签。


  3. 如果您想从标准输入中读取字符,可靠的方法是:

    default:

    替代:

    char buf[LINE_MAX];
    fgets(buf, sizeof buf, stdin);
    switch (buf[0]) {
        // etc.
    }
    

    请勿使用int c = fgetc(stdin); while (fgetc(stdin) == '\n') ; 。 (至少直到你明白它的作用为止。)这是邪恶的。

答案 2 :(得分:1)

没有大问题,你只需忽略在每个角色后处理'\ n'输入,你可以这样做:

scanf("%c\n",&z);

这样你就可以避免处理'\ n'。