📜  在 C 中 scanf() 之后使用 fgets()/gets()/scanf() 的问题

📅  最后修改于: 2022-05-13 01:55:44.407000             🧑  作者: Mango

在 C 中 scanf() 之后使用 fgets()/gets()/scanf() 的问题

scanf()是 C 语言中的一个库函数。它从标准输入读取标准输入。 fgets()是 C 语言中的一个库函数。它从指定的流中读取一行并将其存储到字符串变量指向的字符串中。它仅在以下任一情况下终止:

  • 到达文件结尾
  • 读取 n-1 个字符
  • 读取字符

1)考虑下面一个简单的 C 程序。该程序使用 scanf() 读取一个整数,然后使用 fgets() 读取一个字符串,

输入

10
test
C
// C program to demonstrate the problem when
// fgets()/gets() is used after scanf()
#include 
  
int main()
{
    int x;
    char str[100];
    scanf("%d", &x);
    fgets(str, 100, stdin);
    printf("x = %d, str = %s", x, str);
    return 0;
}


C
// C program to demonstrate the problem when
// scanf() is used in a loop
#include 
  
int main()
{
    char c;
    printf("Press q to quit\n");
    do {
        printf("Enter a character\n");
        scanf("%c", &c);
        printf("%c\n", c);
    } while (c != 'q');
    return 0;
}


C
// C program to demonstrate the problem when
// fgets()/gets() is used after scanf()
#include 
  
int main()
{
    int x;
    char str[100];
    scanf("%d\n", &x);
    fgets(str, 100, stdin);
    printf("x = %d, str = %s", x, str);
    return 0;
}


C
// C program to demonstrate the problem when
// scanf() is used in a loop
#include 
  
// Driver Code
int main()
{
    char c;
    printf("Press q to quit\n");
    do {
        printf("Enter a character\n");
        scanf("%c\n", &c);
        printf("%c\n", c);
    } while (c != 'q');
    return 0;
}


输出

x = 10, str = 

解释:上述代码的问题是 scanf() 读取一个整数并在缓冲区中留下一个字符。所以 fgets() 只读取换行符,字符串“test”被程序忽略。

2)在循环中使用scanf()时也会出现类似的问题。

输入:

a
b
q 

C

// C program to demonstrate the problem when
// scanf() is used in a loop
#include 
  
int main()
{
    char c;
    printf("Press q to quit\n");
    do {
        printf("Enter a character\n");
        scanf("%c", &c);
        printf("%c\n", c);
    } while (c != 'q');
    return 0;
}

输出

Press q to quit
Enter a character
a
Enter a character


Enter a character
b
Enter a character


Enter a character
q

解释:我们可以注意到上面的程序打印了一个额外的“输入一个字符”,然后是一个额外的换行符。发生这种情况是因为每个 scanf() 都会在缓冲区中留下一个字符,由下一个 scanf 读取。

如何解决上述问题?

  • 我们可以通过使用额外的\n使scanf()读取新行,即scanf(“%d\n”, &x) 。事实上scanf("%d ", &x)也可以(注意多余的空格)。
  • 我们可以在scanf( ) 之后添加一个 getchar( ) 来读取额外的换行符。

以上几点的更正程序将是,

1) scanf() 后面有 fgets() 时:

输入:

10
test

C

// C program to demonstrate the problem when
// fgets()/gets() is used after scanf()
#include 
  
int main()
{
    int x;
    char str[100];
    scanf("%d\n", &x);
    fgets(str, 100, stdin);
    printf("x = %d, str = %s", x, str);
    return 0;
}

输出

x = 10, str = test

2) 当 scanf() 在循环中使用时:

输入:

a
b
q 

C

// C program to demonstrate the problem when
// scanf() is used in a loop
#include 
  
// Driver Code
int main()
{
    char c;
    printf("Press q to quit\n");
    do {
        printf("Enter a character\n");
        scanf("%c\n", &c);
        printf("%c\n", c);
    } while (c != 'q');
    return 0;
}

输出:按q退出

Enter a character
a
Enter a character
b
Enter a character
q

必读:当在 nextXXX() 之后使用 nextLine() 时, Java中的 Scanner 会出现问题