scanf()函数中%[^ ]s与%[^ ]两种扫描集的区别是什么?
嘿,这个问题问得挺细致的,我来给你把这俩写法的区别说透——其实核心是一个是标准正确用法,另一个纯属误用,咱们拆开唠:
scanf("%[^\n]") vs scanf("%[^\n]s")的本质区别 1. 正经好用的扫描集:%[^\n]
这是scanf扫描集的标准写法,格式就是%[ + 匹配规则 + ]。这里的^\n翻译过来就是「匹配所有**不是换行符\n**的字符」,程序会一直读输入,直到碰到换行符才停下,而且不会把换行符读进目标数组里。
举个实际代码例子:
char input_buf[100]; // 读取直到换行的所有字符 scanf("%[^\n]", input_buf);
比如你输入Stack Overflow is awesome然后回车,这段代码会把前面的整串内容全塞进input_buf里,回车的换行符会留在输入缓冲区里。
小提醒:一定要加长度限制!比如写成
%99[^\n](对应100长度的数组),防止输入太长导致缓冲区溢出,这是新手常踩的坑。
2. 完全错误的写法:%[^\n]s
这里的s根本不是扫描集的一部分!scanf会先执行%[^\n]这个扫描集,读完所有非换行字符后,接下来会傻愣愣地去输入里找一个普通的s字符——注意,是要在输入流里真的有个s才会继续,否则scanf直接匹配失败,还会把换行符留在缓冲区里,给后续的输入操作埋坑。
举个反面例子:
char input_buf[100]; // 错误写法! scanf("%[^\n]s", input_buf);
如果你输入hello然后回车,scanf读完hello后,转头要找s,但接下来的字符是换行符,匹配失败。这时候scanf会返回1(因为已经成功读了hello到数组里),但换行符还留在缓冲区,下次你用scanf或者getchar的时候,会直接读到这个换行,导致程序看起来“没反应”或者跳过输入,特别头疼。
就算你输入的内容末尾刚好有s,比如hellos回车,%[^\n]会把hellos全读进去,然后还是要找下一个s,但输入已经到换行符了,照样匹配失败,问题完全没解决。
一句话总结
%[^\n]:是你想要的、能正确读取整行非换行内容的扫描集用法;%[^\n]s:属于语法误用,完全没用还会搞乱输入缓冲区,千万别这么写!
内容的提问来源于stack exchange,提问作者Zahra19977

