scanf使用%[^ ]无法实现3次输入的问题排查
为什么
%[^\n]没法实现三次输入? 我来给你拆解下问题所在,顺便说下解决办法:
首先看你的代码,用%s能正常读三次,换成%[^\n]就不行,核心原因是两者对输入缓冲区里的空白字符处理逻辑完全不同:
- 当你用
%s的时候,它会自动跳过输入开头的所有空白字符(包括换行、空格、制表符)。所以每次你输入完按回车,那个换行符会被%s直接忽略,下一次scanf能正常读取新的输入内容。 - 但
%[^\n]的规则是只读取所有不是换行符的字符,它不会自动跳过前置的空白,而且当它遇到换行符停止读取后,那个换行符会留在输入缓冲区里,不会被消耗掉。
举个实际的执行流程例子:
- 第一次输入
hello然后回车,scanf("%[^\n]", str[0])把hello读到了str[0]里,但输入缓冲区里还剩一个\n。 - 第二次循环的时候,
scanf一检查输入缓冲区,第一个字符就是\n,而%[^\n]不匹配换行符,所以直接读取失败,str[1]根本没被赋值。 - 第三次循环也是同样的情况,直接跳过读取步骤。
最后打印的时候,只有str[0]有内容,后面的要么是空要么是乱码。
解决办法
有两种简单可靠的方式修复这个问题:
方式一:在格式串前加空格
在%[^\n]前面加一个空格,让scanf自动跳过所有前置空白字符(包括上次留下的换行):
scanf(" %[^\n]", str[i]);
这里的空格是关键,它会告诉scanf先忽略所有空白,直到遇到第一个非空白字符再开始读取内容。
方式二:手动吃掉换行符
每次用%[^\n]读取后,调用getchar()把缓冲区里的换行符读掉:
scanf("%[^\n]", str[i]); getchar(); // 清除缓冲区里的换行符
不过要注意,为了避免输入过长导致缓冲区溢出,最好限制读取的字符数(比如你的数组是100长度,就最多读99个字符,留一个位置存字符串结束符\0):
scanf("%99[^\n]", str[i]); getchar();
内容的提问来源于stack exchange,提问作者Gourango Modak




