来自简单c while循环的意外行为

时间:2015-07-19 00:34:08

标签: c

我很享受使用GNU Linux大约一年了,并且认为我会通过学习更多关于编程语言C的深入研究,许多Linux内部构建都是如此。今天,我做了一个简单的程序,本来应该帮助我了解while循环,但却让我感到困惑。该计划的目标非常简单:要求用户每行输入一个字符,直到他们输入“魔法”字样。字符' g,此时应用程序将关闭。这是我写的:

#include <stdio.h>

int main(int argc, char*argv[])
{
    char user_input;

    while (user_input != 'g') {
        printf("Please enter a character: ");
        scanf("%c", &user_input);
    }

    printf("You guessed the magic char, \'g\'!\n");

    return 0;
}

我预计,在运行时,应用程序的行为如下:

Please enter a character: d
Please enter a character: dddd
Please enter a character: g
You guessed the magic char, 'g'!

然而,这是我得到的行为:

Please enter a character: d
Please enter a character: dd
Please enter a character: Please enter a character: Please enter a character:
Please enter a character: Please enter a character: Please enter a character: g

当应用程序遇到输入&#39; n&#39;字符,它附加&#39;请输入一个字符:&#39;到它的输出&#39; n&#39;倍。任何人都可以解释为什么会发生这种情况以及我可以做些什么来防止这种行为?

根据L.P。的回答,我将代码修改为以下内容:

#include <stdio.h>

void clear_buffer();

int main(int argc, char *argv[])
{
    char user_input = '\0';

    do {
        printf("Enter guess: ");
        scanf("%c", &user_input);
        clear_buffer();
    } while (user_input != 'g');

    return 0;
}

void clear_buffer()
{
    while(getchar() != '\n' && getchar() != EOF);
}

然而,当我输入以下内容时:     请输入字符:dddd 然后按回车键,我给了一个空白的换行符,直到我再次按回车键...有没有办法解决这个问题?

3 个答案:

答案 0 :(得分:4)

两件事。 一:永远不要对未初始化的变量进行测试。 二:清除缓冲区。这是一个小小的烦恼。这就是为什么你有这种行为的原因。 虽然我同意上面的代码片段,但我有一种习惯,就是不喜欢直接放置这样的东西,当由于它的大量使用时,它应该被制作成一个函数。

void clearBuffer() {                                   
  int c;                   
  while(((c = getchar()) != '\n') && (c != EOF));                                                     
} 

在使用scanf()函数扫描字符后,忘记首先添加应该运行clearBuffer()函数。

不要在c中测试变量,也不要在大多数其他任何语言中进行良好练习,不要先初始化它。

所以你应该使用do-while循环而不是while循环。如上所述,在您的代码中遇到意外行为的评论中,这将有助于阻止您,并且当事情开始变得更加复杂时,这是一种总体良好的做法。

答案 1 :(得分:3)

读取缓冲区中的所有字符(如果有),直到换行符为char并丢弃它们:

int c;

....

        scanf("%c", &user_input);
        while ((c=getchar()) != EOF && c != '\n');

如评论中所述,您需要使用某些内容初始化user_input。自动变量未在C中初始化。

答案 2 :(得分:2)

如果你想要简单的答案:scanf(" %c", &user_input);工作正常(请记住%c之前的空格字符)。这仅在用户一次输入一个字符时有效。 Blue Moon 已经提到了更正式的方法。

这是因为scanf消耗了输入的第一个字符上的\n字符。当您输入一个字符然后按Enter键时,scanf将使用该字符直到换行符。但是,换行仍然在输入缓冲区中,scanf在下一个while循环迭代中消耗了该换行符。