C:多个scanf,当我输入一个scanf的值时,它会跳过第二个scanf

时间:2012-03-05 05:54:24

标签: c scanf

我有这段代码(由于逻辑是家庭作业的一部分而省略了函数):

#include <stdio.h>

int main()
{
    char c = 'q';
    int size; 

    printf("\nShape (l/s/t):");
    scanf("%c",&c);

    printf("Length:"); 
    scanf("%d",&size);

    while(c!='q')
    {
        switch(c)
        {
            case 'l': line(size); break; 
            case 's': square(size); break;
            case 't': triangle(size); break; 
        }


        printf("\nShape (l/s/t):");
        scanf("%c",&c);

        printf("\nLength:"); 
        scanf("%d",&size);
    }

    return 0; 
}

前两个Scanf的工作很好,没有问题,一旦我们进入while循环,我有一个问题,当你应该被提示输入一个新的形状char时,它会跳到{{1}长度并等待从那里获取一个char的输入,然后在循环的下一次迭代中稍后是一个小数。

Preloop迭代:

Scanf:形状。作品很棒 Scanf:长度。没问题

循环1.

Scanf:形状。跳过这个 Scanf:长度。问题是,这个scanf映射到形状char。

循环2
Scanf:形状。跳过这个 Scanf:长度。问题,这个scanf现在映射到int大小。

为什么这样做?

7 个答案:

答案 0 :(得分:38)

scanf("%c") ENTER 键中读取换行符。

当您输入我们说15时,您输入15,然后按 ENTER 键。所以输入缓冲区中现在有三个字符。 scanf("%d")读取15,将其解释为数字15,但换行符仍在输入缓冲区中。 scanf("%c")将立即读取此换行符,然后程序将转到下一个scanf("%d"),并等待您输入数字。

通常的建议是使用fgets读取整行输入,并在单独的步骤中解释每行的内容。解决您当前问题的更简单方法是在每个getchar()之后添加scanf("%d")

答案 1 :(得分:19)

基本问题是scanf()在缓冲区中的数字后面留下换行符,然后在下一遍中用%c读取它。实际上,这很好地证明了我不使用scanf()的原因;我使用了行阅读器(例如fgets())和sscanf()。它更容易控制。

您可以使用" %c"代替"%c"来格式化字符串来拯救它。空格会导致scanf()在读取字符之前跳过空格(包括换行符)。

但从长远来看,放弃scanf()fscanf()并使用fgets()或等效加sscanf()会更容易。除此之外,当您使用整个字符串时,错误报告会更容易,而不是scanf()失败后留下的小插图。

您还应始终检查是否获得了从scanf()转换的值。输入失败 - 经常和可怕。不要让它破坏你的程序,因为你没有检查。

答案 2 :(得分:6)

使用功能

void seek_to_next_line( void )
{
    int c;
    while( (c = fgetc( stdin )) != EOF && c != '\n' );
}

清除输入缓冲区。

答案 3 :(得分:5)

尝试在scanf中添加空格。

scanf(" %d", &var);
//     ^
//   there

这会导致scanf()在匹配整数之前丢弃所有空格。

答案 4 :(得分:2)

第一次调用'\n'后,scanf字符仍留在输入流中,因此第二次调用scanf()会将其读入。使用getchar()

答案 5 :(得分:1)

当您键入形状和ENTER时,第一个scanf会消耗该形状,但ENTER不会!第二个scanf需要一个数字,因为被认为是一个空格,所以跳过了ENTER,并且scanf等待一个有效的输入(一个数字),再次由ENTER终止。好吧,这个数字被消耗了,但是输入不是,所以while里面的第一个scanf使用它,你的形状提示被跳过...这个过程重复。您必须在scanfs中添加另一个%c来处理ENTER键。我希望这有帮助!

答案 6 :(得分:1)

您也可以使用 scanf("%c%*c", &c); 读取两个字符并忽略最后一个字符(在本例中为'\ n')