【问题标题】:C: For loop acting REALLY strangely with scanfC:for 循环在 scanf 中的作用真的很奇怪
【发布时间】:2012-04-07 00:38:57
【问题描述】:

所以我得到了以下代码:

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 完全陌生。

根据您的 cmets 编辑代码至此(对奇怪的格式表示歉意):

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

那里发生了什么?第一行上方还有其他输出代码,来自程序的另一部分。会不会是这个原因?

【问题讨论】:

  • 获取输入应始终通过 fgets+sscanf 完成,以避免此类和其他常见错误和漏洞。
  • 这是一个 uni 作业,不幸的是我们不得不使用 scanf。
  • While-loop ignores scanf the second time 的可能重复项。在提问之前尝试搜索此网站。

标签: c loops for-loop scanf


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    %s%d%f 和大多数其他转换说明符不同,%c 转换说明符不会跳过任何前导空格,因此它会从上一个条目中选择换行符。

    键入a 1 1 &lt;Enter&gt; 后,输入流的内容为{'a', '1', '1', '\n'}。第一个scanf 使用a11,将尾随\n 留在输入流中。 scanf 返回 3,然后打印 q 的值。

    第二次循环,scanf 拾取剩余的\n 并将其分配给l,但由于输入流中没有其他内容,因此它没有分配xy,所以它返回一个值 1 并且你的分支没有被占用。然后循环重新开始。

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

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

    格式中的前导空格将导致scanf 跳过输入流中的任何前导空格,因此您不会意外地从上一个条目中拾取尾随换行符。当然,如果您想要选择任何空白字符,则必须做一些不同的事情。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        你有未消费的“\n”,getchar() 会消费它:

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

        【讨论】:

        • 或者只是:if (3 == scanf("%c %d %d\n", &l, &x, &y)) printf("%d\n", q);跨度>
        • 或者只是: if(3 == scanf("%c %d %d ", &l, &x, &y)) 删除任何空白内容。
        • 我用过这个方法,但是第一次迭代还是报错。我已经向 OP cos 添加了细节,因为我无法在 cmets 中格式化。想法?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-23
        相关资源
        最近更新 更多