【问题标题】:Loop exit condition on fgets doesn't work [duplicate]fgets上的循环退出条件不起作用[重复]
【发布时间】:2018-01-23 19:34:25
【问题描述】:

我有一个这样的文本文件

"input"
height : 227
width : 227
depth : 3

"conv"
num_output : 96
pad : 0
kernel_size : 11
stride : 4
group : 1

"relu"

"pool"
kernel_size : 3
stride : 2

我正在循环阅读(这是部分代码)

char line[100];

while ((fgets(line, sizeof(line), filePtr))) {
    if (line[0] != "\n") {
        sscanf(line, "%15s : %15s", tmpstr1, tmpstr2);
        printf("%s\n",  tmpstr2);
        printf("line = %s", line);
    } else
        break;
}

但我观察到if 条件始终成立,输出如下

"input"
227
line = height : 227
227
line = width : 227
3
line = depth : 3
3
line = 
3
line = "conv"
96
line = num_output : 96
0
line = pad : 0
11
line = kernel_size : 11
4
line = stride : 4
1
line = group : 1
1
line = 
1
line = "relu"
1
line = 
1
line = "pool"
3
line = kernel_size : 3
2
line = stride : 2

我也尝试与\0 进行比较,但结果没有改变。请指出我哪里出错了。

附: : 我正在使用 Ubuntu 16.04 64 位机器和 gcc 5.2.1。

【问题讨论】:

  • line[0] != "\n" --> line[0] != '\n'
  • 您将char 与字符串文字进行比较,您应该打开编译器警告。 gcc -pedantic -Werror
  • @BLUEPIXY 感谢您指出。完全忽略了那个错字。
  • 我把它作为'字符串比较'的副本关闭了,但它也可以看作是字符比较。条件if (line[0] != "\n") {charchar * 进行比较。它可以通过使用if (strcmp(line, "\n") != 0)if (line[0] != '\n') 来修复——两者都在这种情况下工作。对于一般字符串比较(较长的字符串),请使用strcmp()

标签: c string loops fgets


【解决方案1】:

换行符是一个字符,而不是一个字符串,所以改变这个:

line[0] != "\n"

到这里:

line[0] != '\n'

启用编译器警告(GCC 中的-Wall 标志),您应该会看到如下内容:

warning: comparison between pointer and integer
warning: comparison with string literal results in unspecified behavior [-Waddress]

【讨论】:

    【解决方案2】:

    您正在尝试将字符串文字与char 进行比较。

    与:

    if(line[0] != '\n')
    

    效果很好。

    如果您正在读取以文本模式打开的文件(包括stdin),那么底层系统用于标记行尾的任何表示都将被转换为单个“\n”字符。

    您应该打开编译器警告。对于gcc,它是-pedantic -Werror

    【讨论】:

    • 很好的答案,但是请检查我的答案是否有标志(我只使用一个标志就收到了警告)。
    • 是的,你会的,我会留下它,所以 OP 会看到gcc 有更多机会 :-)
    • 你的速度更快,答案也很好,所以你应得的。
    【解决方案3】:

    this site 上,我们可以看到 fgets 不会更改 str 的值(在您的情况下为行)。因为值没有改变,你的 if 测试不断被评估为真。

    如果要检查 fgets 是否找到文件末尾,则必须检查 fgets 是否返回 NULL。

    【讨论】:

      【解决方案4】:

      您正在将一个字符与一个字符串进行比较:line[0] != "\n" 应该会产生一个警告。要检测空行,请改用:

      line[0] != '\n'
      

      注意你还应该验证sscanf()的返回值:

      char line[100];
      
      while (fgets(line, sizeof(line), filePtr) && *line != '\n') {
          if (sscanf(line, "%15s : %15s", tmpstr1, tmpstr2) == 2) {
              printf("%s\n",  tmpstr2);
              printf("line = %s", line);
          } else {
              printf("invalid format: %s", line);
          }
      }
      

      【讨论】: