为什么 scanf 要求输入两次,但只是在第一次循环迭代中?

Why does scanf ask for input twice, but just in the first loop iteration only?

首先,这似乎与 this 问题重复,但在我的例子中,为什么这只发生在第一次循环迭代(第一个数组元素的输入)中。为什么不是全部?

我的代码:

#include "stdio.h"

int main(int argc, char const *argv[])
{
    int a[5];
    int i;
    for (i = 0; i < 5; i++) {
        printf("Input a[%d]:\n", i);
        int x = scanf("%d ", &a[i]);    // notice the white-space after %d
    }
    for (i = 0; i < 5; ++i)
    {
        printf("a[%d]=%d\n", i, a[i]);
    }
}

输出示例:

Input a[0]:
1
2
Input a[1]:
3
Input a[2]:
4
Input a[3]:
5
Input a[4]:
6
a[0]=1
a[1]=2
a[2]=3
a[3]=4
a[4]=5

为什么只对a[0]要求输入两次,其余的不要求输入,还有为什么分配给a[1-5]的值是在它之前的一个循环迭代中输入的值?

我阅读了this的答案,但我仍然不明白为什么它在每个循环中不要求输入两次。有明确的解释吗?

在你的情况下,

 scanf("%d ", &a[i]);

扫描一个整数后,scanf()需要匹配白色space,任意数量的白色space直到需要一个非白色space字符来完成匹配。

因此,第一次,第二个输入是非白色space,它终止扫描,但留在缓冲区中(保持未读状态)下一个扫描.

下一次以后,最后一个输入(留在缓冲区中)被认为是扫描输入,当前输入作为终止符,只是留在缓冲区等等。

因此,最后一个输入 (6) 从未真正读入数组,它仍然只是一个 终止符 。考虑连续的前五个输入。 为了清楚起见,引用 C11§7.21.6.2 第 (5) 段, 强调我的

A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read.

很好地解释了 scanf()

为了阐明用户体验,棘手的附加部分是 stdin 通常是行 缓冲 ​​。这意味着 none 的用户输入被分配给 stdin,直到 Enter 或 EOF 发生。这就是为什么当键入 2 时第一个 scanf() 没有 return(scanf("%d ",... 中的指令 " " 寻找的非白色 space ).用户必须键入 2 输入 然后 stdin 得到两个 "2\n"然后 scanf() 看到 2,在 stdin 和 return 中未读。

以下代码:

1) 不引发编译器警告 I.E.完全符合

2) 使用 scanf()

正确处理任何错误情况

3) 使用 'return(0);'

正确处理程序退出

4) 包括用于 exit() 的 stdlib.h 和 EXIT_FAILURE

5) 在不使用可选参数 argc 和 argv 时正确声明 main() 函数。

6) 更正了 scanf() 中格式字符串的问题

#include "stdio.h"
#include <stdlib.h> // exit and EXIT_FAILURE

#define MAX_A_LEN (5)

int main( void )
{
    int a[ MAX_A_LEN ];
    int i; // loop index

    for (i = 0; i < MAX_A_LEN; i++)
    {
        printf("Input a[%d]:\n", i);
        if( 1 != scanf("%d", &a[i]) )    
        { // then scanf failed
            perror( "scanf failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, scanf successful
    }

    for (i = 0; i < MAX_A_LEN; ++i)
    {
        printf("a[%d]=%d\n", i, a[i]);
    }

    return(0);
} // end function: main