scanf("%s") 在使用 scanf("%d") 后仍然存储字符串。

3

所以我写了这个代码(忽略缓冲区溢出问题,因为这只是一个简单的例子):

#include<stdio.h>
int main(void){
    int n;
    char s[10];
    printf("Enter a number: ");
    scanf("%d",&n);
    scanf("%s",s);
    printf("%s",s);
    return 0;
}

这个字符串不应该被存储在数组中,因为输入缓冲区中应该有一个"\n",所以scanf("%s",s)应该被终止,但实际情况并非如此。输出打印了该字符串。


@xing 非常感谢。我不知道那个。 - Rishabh Kapri
通常情况下,它只会对后续的 "%c" 格式说明符造成问题,除非明确指示使用 " %c" 来跳过前导空格。 - Weather Vane
“...因为输入缓冲区中应该有一个“\n”…” - 你是从哪里得到这个想法的?scanf根本不关心\n。对于scanf来说,\n只是另一个空格字符。 - AnT stands with Russia
1
@AnT scanf在%c、%n和%[时确实会考虑空格。 - Rishabh Kapri
1个回答

3

格式说明符%s跳过前导空格,即任何'\n'' ''\t'等都将被忽略,s[0]将包含输入的第一个非空格字符。

为了演示一下scanf中发生的情况,看看下面利用scanf"%n"特性的示例,它返回已处理的字符数;我使用sscanf使结果不依赖于用户输入。请注意,读取字符串时,scanf处理的字符比结果中存储的多:

#include<stdio.h>
int main(void){
    int n;
    int pos;
    char s[10];
    const char* simulatedInput = "123\n     abcde";
    const char* inputPtr = simulatedInput;

    sscanf(inputPtr,"%d%n",&n,&pos);
    printf("sscanf on %s processed %d charaters; result n: %d\n", inputPtr, pos, n);

    inputPtr += pos;  // inputPtr will point at the position of '\n'
    sscanf(inputPtr,"%s%n",s,&pos);
    printf("sscanf on %s processed %d charaters; yet s as '%s' contains only %lu characters\n", inputPtr, pos, s, strlen(s));

    return 0;
}

输出:

sscanf on 123
     abcde processed 3 charaters; result n: 123
sscanf on 
     abcde processed 11 charaters; yet s as 'abcde' contains only 5 characters

2
只是一个小问题:scanf()的POSIX规范,在一个没有标记为POSIX扩展的部分中,指出'white space'包括换页符'\f'和垂直制表符'\v',以及空格、制表符和换行符。这不是一个重大问题;你很少遇到这两个字符。(有趣的是,C标准在默认(C)区域设置中将回车符'\r'添加到isspace()识别的字符列表中。C标准说'white space'而没有列出具体字符,这意味着" isspace()认为是空白字符"。) - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接