我在c中编写程序来读取文件的内容。 代码如下:
#include<stdio.h>
void main()
{
char line[90];
while(scanf("%79[^\n]\n",line)==1)
printf("%s",line);
}
以上代码读取文件内容并将其显示在屏幕上。
但是
while(scanf("%79[^\n]",line)==1) and while(scanf("%79[^\n]s",line)==1) or while(scanf("%79[^\n]s\n",line)==1)
不起作用。(它们只显示第一行)
任何人都可以解释一下吗?
答案 0 :(得分:5)
格式"%79[^\n]"
表示最多不超过79个字符且不是'\n'
的所有字符。
使用时,
scanf("%79[^\n]s",line)
返回值不应为1,因为格式说明符中的s
在读完所有不是s
的字符后需要文字'\n'
。换句话说,scanf
报告失败。
使用时,
scanf("%79[^\n]\n",line)
它成功了,因为它最后找到了一个文字'\n'
。
之间的区别
scanf("%79[^\n]",line)
和
scanf("%79[^\n]\n",line)
是在第一种情况下'\n'
留在输入流中,而在第二种情况下消耗'\n'
。在第二种情况下,不仅消耗了'\n'
,而且消耗了从scanf
开始的任何空格序列(感谢@MattMcNabb进行了额外的澄清)。
如果您希望'\n'
仅使用scanf("%79[^\n]%*c",line)
,请使用:
{{1}}
答案 1 :(得分:1)
由于格式本身是相同的,解决这个问题的关键是,正如你可以肯定的那样,格式字符串之后的尾随字符(或者没有那个字符)
'\n'
放在最后时,告诉scanf
读取并忽略读取字符串后的行尾字符。这很好用,因为'\n'
是根据您的格式终止字符串的内容(即%79[^\n]
)。's'
时,您告诉scanf
您希望在s
结尾的字符串后面有文字'\n'
。这是一个错误,因为scanf
会将字符串读取到'\n'
字符*并排除。'\n'
放在最后时,第一次阅读将会成功,但所有后续阅读都会偶然发现'\n'
,并立即停止阅读。请注意,有效的代码可能会对超过79个字符的输入字符串产生意外结果。这些字符串将被剪切为79个字符的标记,其余字符将显示为下一个字符串的开头。
*这种读取成功的情况不太可能发生 - 也就是说,当读取由于达到79的限制而终止时,和然后在80-发现字母s
太空了。
答案 2 :(得分:1)
很多微妙的差异:
1)"%79[^\n]"
告诉scanf()
扫描并保存1到79 char
,'\n'
除外。如果尝试扫描的第一个char
为\n
,则无将保存,扫描将停止。在OP的例子中,返回0。否则,'\0'
会附加到目标line
。如果没有其他内容,则返回1。
2)"%79[^\n]\n"
执行1)并且如果成功继续寻找任何连续的空白区域,而不仅仅是'\n'
。这通常包括'\n'
和,然后是 next 行的所有前导空格。无论是否找到空格,它都会返回1。
3)"%79[^\n]s"
执行1,如果成功则继续查看单个s
。无论是否找到s
,它都会返回1。可能这不是OP的愿望 - 放弃's'
。
4)"%79[^\n]s\n"
执行3)并且如果成功,则表现得像2)继续寻找任何连续的空白空间,而不仅仅是'\n'
。无论是否找到空格,它都会返回1。
5)3 while()
语句相当复杂,作为一个整体。尝试将'\n'
读入3 scanf()
中的1的开头时会遇到问题。
如果代码需要使用scanf()
来读取一行,那么更好的方法是
while (scanf(" %79[^\n]%*c", line) ==1)
。这将折腾前导空格,然后读取最后一行'\n'
,通过'\n'
抛出"%*c"
。
最好的方法是使用fgets(line, sizeof line, stdin)
。
答案 3 :(得分:0)
可能的问题是对逻辑值的短路问题。 即。当编译器阻止他有足够的信息来评估整个表达式时,它不需要测试其他逻辑值(并且不会对它们进行评估)。
即。 false和call_foo()总是计算为false,因此永远不会调用call_foo()。
它也可以连接到那个,当你在scanf中读取一行(3个逻辑表达式中的第一个)时,其他scanf将读取下一行,而不是相同的行,因为第一个scanf已经从缓冲区获取了数据