C:对于使用scanf,循环操作非常奇怪

时间:2012-03-22 12:41:10

标签: c loops for-loop scanf

所以我有以下代码:

int q, x, y;
char l;
for (q = 0; q<10; q+=1) {
    printf("%d\n", q);
    if (3 == scanf("%c %d %d", &l, &x, &y)) {
        printf("%d\n", q);
    }
}

我希望这会运行“scanf”10次。每次在我输入任何东西之前打印'q',然后再打印。所以预期的输出应该是这个(如果我错了,请纠正我):

0
> a 1 1
0
1
> b 2 2
1
2
> c 3 3
2
...and so on.

但我真的明白了。

0
> a 1 1
1
1
2
> a 2 2
3
3
4
> a 3 3
5
5
6
> a 4 4
7
7
8
> a 5 5
9
9

如果我取出scanf功能,它会按照预期从0到9进行计数。 scanf函数发生了什么让for循环行为如此奇怪?我在Java / Python方面有一些经验,但我对C完全不熟悉。

根据您对此的评论编辑代码(为奇怪的格式化道歉):

for (q = 0; q<10; q+=1) {
        printf("%d: ", q);
        if (3 == scanf("%c %d %d ", &c, &x, &y)) printf("%d\n", q);
        else { printf("WTF %d\n", q); }
    }
一半解决了这个问题。它适用于第一个迭代的所有迭代。如此:

0: a 0 0
WTF 0
1: b 1 1
1
2: c 2 2
2

那里发生了什么?从程序的另一部分开始,在第一行之上还有其他输出代码。这会导致这种情况吗?

4 个答案:

答案 0 :(得分:4)

你没有消耗“\ n”,getchar()会消耗它:

if (3 == scanf("%c %d %d", &l, &x, &y)) {
    getchar();
    printf("%d\n", q);
}

答案 1 :(得分:4)

%s%d%f以及大多数其他转换说明符不同,%c转换说明符不会跳过任何前导空格,因此它会接收来自上一个条目的换行符。

输入a 1 1 <Enter>后,输入流的内容为{'a', '1', '1', '\n'}。第一个scanf使用a11,在输入流中保留尾随\nscanf返回3并打印q的值。

第二次循环,scanf选择剩余的\n并将其分配给l,但由于输入流中没有其他内容,因此不会分配x 1}}或y,因此它返回值1并且不执行分支。然后循环重新开始。

解决此问题的最简单方法是在%c转换说明符之前的格式字符串中放置一个前导空格:

if (3 == scanf(" %c %d %d", &l, &x, &y))
  printf("%d\n", q);

格式中的前导空格将导致scanf跳过输入流中的任何前导空格,因此您不会意外地从上一个条目中获取尾随换行符。当然,如果你希望拿起任何空格字符,你就必须做些不同的事情。

答案 2 :(得分:2)

为什么不尝试在你的vars中添加else语句和printf来调试它? 似乎每次(3 == ..)都是真的,还有一次它是假的。 当您按Enter键时,scanf可能会为换行符运行两次...

答案 3 :(得分:0)

scanf函数返回不同的值而不是3(三个输入)。我不知道确切的原因,但我觉得因为scanf中的空格(“%c space%d”,&amp; c,&amp; i);函数它返回不同的值。