C语言中%79[^ ]与%79[^ ] 格式串差异及代码疑问解答
嘿,这个问题戳中了C语言输入函数里一个很容易踩坑的细节——格式符对空白字符的处理逻辑,我来给你一步步拆解清楚:
一、两段代码的核心差异
其实本质不是scanf和fscanf的区别(这俩的格式串处理逻辑是完全一致的),而是:
- 第一段代码的格式串开头是
%f,%f,这两个数值格式符会自动跳过前导空白; - 第二段代码的格式串只有
%79[^\n](或带\n的版本),而%[系列格式符不会跳过前导空白。
正是这个差异导致了读取行为的不同。
二、关键格式串的区别
我们逐个分析你提到的几个格式串:
1. %79[^\n]的行为
这个格式符的意思是:
- 最多读取79个字符;
- 遇到
\n(换行符)就停止读取; - 不会消耗掉输入流中的换行符——也就是说,读完一行内容后,换行符会留在缓冲区/文件流里,成为下一次读取的第一个字符。
另外要记住:%[系列格式符是不跳过前导空白的,只要流的当前位置是空白字符(比如换行符),它就会直接匹配失败,什么都读不到。
2. %f,%f,%79[^\n]为什么能读所有行?
前面的%f是数值格式符,这类格式符的特性是:自动跳过所有前导空白字符(包括换行符、空格、制表符等)。
所以当你第一次读完一行后,流里剩下的换行符,会被下一次调用scanf时的第一个%f自动跳过,然后继续读取下一行的数值和字符串,循环下去就能读完所有行。
3. %79[^\n]\n为什么能解决第二段的问题?
格式串里的\n不是指“匹配一个换行符”,而是匹配任意数量的空白字符(包括换行符、空格、制表符,甚至多个连续空白)。
当你用这个格式串时:
- 先通过
%79[^\n]读取一行的内容(直到换行符); - 后面的
\n会把流里剩下的换行符(以及可能的其他空白)全部消耗掉,让流的指针直接指向下一行的开头。
这样下一次调用fscanf时,就能正常读取下一行的内容,自然就能遍历所有行了。
4. 为什么第二段用%79[^\n]只能读一行?
第一次调用fscanf时,它会读取第一行的所有字符(直到换行符),但换行符留在了流里。
第二次调用时,%79[^\n]尝试读取字符,但第一个遇到的就是换行符,而[^\n]要求读取的字符不能是换行符,所以匹配失败,fscanf直接返回0(表示没有读取到任何内容),看起来就像只读了一行。
额外提醒
如果你想让%79[^\n]也能正常读取多行,还有一个办法:在每次读取后手动消耗掉换行符,比如用getc(fp)或者fscanf(fp, " %*c")(注意前面的空格,用来跳过可能的空白)。
内容的提问来源于stack exchange,提问作者Дмитрий Б

