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
相关产品推荐
相关产品推荐

