scanf("%79 [^ \ n]",line)之间的差异; vs scanf("%79 [^ \ n] \ n",line)vs scanf("%79 [^ \ n] s",line)

时间:2014-06-25 20:55:46

标签: c scanf

我在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) 

不起作用。(它们只显示第一行)

任何人都可以解释一下吗?

4 个答案:

答案 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已经从缓冲区获取了数据