You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

scanf硬编码格式字符串与命令行传入格式字符串的输出差异原因

两段C语言代码输入缓冲区处理差异的原因分析

第一段代码(硬编码格式字符串)

#include <stdio.h>
int main()
{
    int i;
    char c;
    char *format_string = "%d\n";
    scanf(format_string, &i);
    printf("read: %d\n", i);

    printf("Let's check what is in the input buffer:\n");
    while (scanf("%c", &c) == 1)
    {
        printf("read from input buf: %d\n", c);
    }
}

执行命令:echo "5" | ./specific.out
输出结果:

read: 5
Let's check what is in the input buffer:

第二段代码(命令行传入格式字符串)

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        exit(EXIT_SUCCESS);
    }

    int i;
    char c;

    char *format_string = argv[1];

    scanf(format_string, &i);
    printf("read: %d\n", i);

    printf("Let's check what is in the input buffer:\n");
    while (scanf("%c", &c) == 1)
    {
        printf("read from input buf: %d\n", c);
    }
}

执行命令:echo "5" | ./general.out '%d\n'
输出结果:

read: 5
Let's check what is in the input buffer:
read from input buf: 10

差异原因解析

核心问题出在格式字符串中\n的实际解析结果不同:

  • 第一段代码里,硬编码的"%d\n"是C语言字面量字符串,编译器会把其中的\n解析为单个换行符(ASCII 10)。scanf处理这个格式时,%d读取整数5后,会继续匹配后续的换行符——scanf对空白符的处理逻辑是跳过所有连续空白(包括换行、空格、制表符等),直到遇到非空白字符才停止。因此第一个scanf执行完毕后,输入缓冲区里由echo "5"产生的换行符已经被完全消耗,后续的scanf("%c")没有内容可读,也就不会输出任何结果。
  • 第二段代码里,通过命令行传入的'%d\n'会被shell原样传递给程序,此时格式字符串中的\n是两个独立的字符:反斜杠\和字母n,而非换行符。scanf处理时,%d读取整数5后,会尝试匹配下一个字符\,但输入缓冲区里剩下的是换行符(ASCII 10),两者不匹配,scanf直接终止,不会消耗这个换行符。后续的scanf("%c")就会读取到这个残留的换行符,输出其ASCII值10。

内容的提问来源于stack exchange,提问作者Wakan Tanka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:52:49