for循环中使用字符集格式的scanf为何无法正常读取输入?
问题原因
你的判断完全正确,故障的核心诱因就是scanf("%d",&n)读取整数后,残留在输入缓冲区中的尾部换行符。
执行scanf("%d",&n)时,函数只会读取连续的数字字符转换为整型存入变量n,你输入完数字按下的回车对应的\n字符不会被%d格式符匹配消费,会一直留在输入缓冲区中。
进入for循环后,你使用的%27[^\n]格式符匹配规则是「读取最多27个非换行符的字符」,第一次循环时缓冲区首字符就是残留的\n,会直接导致匹配失败:
- 匹配失败时
scanf不会对in数组执行任何写入操作,而in是栈上未初始化的局部数组,存储的是内存中的随机垃圾值,直接printf输出就会出现乱码,你看到的笑脸字符就是随机字节恰好命中了ASCII扩展字符集的对应编码。 - 由于
%27[^\n]匹配失败,scanf会直接提前返回,后面跟着的%*c(用来消费读取字符串后剩下的换行符)根本不会执行,缓冲区里的\n会一直留存,后续每一轮循环都会重复「匹配失败→输出垃圾值」的流程,全程不会等待用户输入。
修复方案
- 读取完整数
n后,立刻清空输入缓冲区中残留的所有字符直到换行,不要用C标准未定义的fflush(stdin),用循环读字符的方式兼容性最好:while(getchar() != '\n'); - 修正不规范的代码写法:
- 数组名本身就是首元素地址,
scanf读字符串时不需要对数组名取&; - 不要用非标准的
void main写法,C标准规定main函数返回值为int; - 字符数组读入前先初始化为全0,避免匹配失败时输出未初始化的内存乱码;
- 每轮读取完字符串后,统一用循环清空当前行剩余的所有字符(包括换行),兼容用户直接敲回车输入空行、输入内容超过27个字符的场景,避免残留字符影响下一轮输入。
- 数组名本身就是首元素地址,
修复后的完整可运行代码:
#include <stdio.h> int main() { int n; printf("Loop:\n"); scanf("%d", &n); // 清空读整数后残留的缓冲区内容 while (getchar() != '\n'); for (int i = 0; i < n; ++i) { char in[28] = {0}; scanf("%27[^\n]", in); // 清空当前行剩余所有字符,包括换行 while (getchar() != '\n'); printf("%s\n", in); } return 0; }
内容的提问来源于stack exchange,提问作者brittle_spirit
相关产品推荐
相关产品推荐

