我们不得不使用 `scanf(" ")` 和 `scanf("%*c")`

问题描述 投票:0回答:2

在 C 中,当我们在

scanf("%s")
scanf("%c")
之前使用
scanf("%s")
scanf("%[^\n]")
时,在输入时,在第一个输入的末尾会有一个额外的
'\n'
,这将是传递到第二个输入并弄乱输入流。据我所知,我已经在两个不同的系统中使用相同的 gcc 编译器尝试了这些代码。但它每次都做了不同的事情。在第一个系统中,我不得不使用
scanf("\n")
来丢弃换行符。但是在第二个系统中没有这样的需要。它自动丢弃换行符。

然后我试了三个密码,

代码1:

printf("Enter the name of the student: ");
scanf("%s", name);

printf("Enter the email of the student: ");
scanf("%s", email);

在这里我不必忽略换行符,编译器没有问题。

代码2:

printf("Enter the name of the student: ");
scanf("%s", name);
scanf("%*c");

printf("Enter the email of the student: ");
scanf("%s", email);

这里我只是添加了

scanf("%*c")
来丢弃换行符,这与
code 1
的结果相同。但是,当我将
scanf("%*c")
替换为
scanf("\n")
时,输入再次混乱,我现在必须提供 3 个输入,因为它没有正确丢弃第一个换行符。

代码3:

char chr, s[100], sen[100];

scanf("%c", &chr);
scanf("\n");
scanf("%s", s);
scanf("\n");
scanf("%[^\n]%*c", sen);

如果没有

scanf("\n")
s,代码将无法工作。

我真的不明白这里发生了什么。为什么有时我必须转义换行符而其他时候不需要。

c
2个回答
1
投票

在C中,当我们在

scanf("%s")
scanf("%c")
之前使用
scanf("%s")
scanf("%[^\n]")
时,在输入时,会有一个额外的' ' 在第一个输入的末尾,它将被传递到第二个输入并弄乱输入流。

我不会那样说。我会说:

每当我们将

scanf
any 格式说明符一起使用时,指示用户键入的行结尾的
\n
将保留在输入流中,这可能会导致以后出现问题。分三种情况:

  1. 如果下一个输入是
    scanf
    使用除 %c
    %[…]
    之外的任何格式说明符
    ,挥之不去的 
    \n
    将与任何其他前导空格一起自动被跳过。
  2. 如果下一个输入是
    scanf
    使用
    %c
    %[…]
    \n
    将由该格式说明符读取(尽管通常不需要)。
  3. 如果下一个输入不是
    scanf
    ,例如
    fgets
    getchar
    \n
    将被该函数读取(尽管通常不需要)。

情况 #2 很容易通过在格式说明符中添加一个额外的前导空格来修复,明确指示

scanf
跳过前导空格(因为它隐式地对所有其他格式说明符执行此操作)。

通常不建议单独调用

scanf("\n")
,因为它并不像看起来那样做。


0
投票

scanf()
只消耗匹配转换格式字符串的字符。因此,它将其余输入保留在
stdin
中,例如:当
stdin
是行缓冲时用户输入的换行符,这是从终端读取时的默认设置。

大多数转换都会跳过这样的空白,但对于

%c
%[xxx]
则不会。对于这些格式,您可以通过在格式前插入一个空格来明确跳过挂起的换行符和其他空格:

#include <stdio.h>

int main() {
    char name[100];
    char email[100];
    char grade;
    
    printf("Enter the name of the student: ");
    if (scanf("%99[^\n]", name) != 1)
        return 1;
    
    printf("Enter the grade letter: ");
    if (scanf(" %c", grade) != 1)
        return 1;
    
    printf("Enter the email of the student: ");
    if (scanf("%99s", email) != 1)
        return 1;

    printf("name: %s\n", name);
    printf("email: %s\n", email);
    printf("grade: %c\n", grade);
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.