fgets 无法读取换行符

fgets cannot read newline character

char c[500];
fgets(c, 500, fp);

if (c == "\n") {
    customer.checkoutTime = 0;
    customer.payment = 0;
}

如果 fgets 读取一个空行,我想在这两个 var 中存储两个零。但是它失败了,从不执行 if-block 代码。 fgets 应该如何读取空行?

c 不是单个字符;它是指向字符序列的指针。您的 if 是在询问这是否与您预先填充换行符的位置相同,如果这样描述,显然永远不会成功。

如果要查看c指向的第一个字符是否为换行符,请使用if ( *c == '\n' )

好的,有几件事:

1。函数行为

来自 description of fgets 函数:

The C library function char *fgets(char *str, int n, FILE *stream) reads a line from the specified stream and stores it into the string pointed to by str. It stops when either (n-1) characters are read, the newline character is read, or the end-of-file is reached, whichever comes first.

man fgets:

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('[=48=]') is stored after the last character in the buffer.

这是什么意思:

fgets 在遇到 \n(换行)字符后停止 阅读。但是让我们看看我们可以用结果字符串做什么:

鉴于 fgets 在最多读取 N-1 个字符后停止,您知道,如果 strlen(c) 是 499,则很可能没有遇到 EOF/EOL 个字符。
如果 fgets 遇到 EOL,它会 return 一个 NULL 指针,所以你可以使用它。除此之外,以下是查找新行的方法:

鉴于 c 是一个数组,我还会避免在声明和 fgets 调用中对缓冲区的大小进行硬编码。相反,我会使用:

char c[500], // perhaps a macro here?
    *check;
//more code
check = fgets(c, sizeof c, fp); // fgets returns relevant stuff
if (check == NULL || *check == '[=10=]')
    //Nothing was read (EOL), or an error occurred,
    //or fgets read a nul-character at the start of the line
if (strlen(c) == (sizeof c) -1)
    //likely no EOL
else
    c[strlen(c) - 1] most likely to be EOL

我添加了 *check == '[=26=]' 检查以响应 chux 的评论之一,以防 fgets 实际上是从文件中读取空字符。由于您只对以 \n 开头的行感兴趣,您只需跳过像这些

这样的行

2。代码问题

除此之外,您发布的代码:

if (c == "\n") {

在几个层面上是错误的。 "\n" 生成一个指向只读字符串 (char *) 的指针,它永远不会等于 c。使用 strcmp 比较字符串。对于字符,使用单引号,并比较 c 中的值,您必须取消引用它:

if (c[i] == '\n') // or *c == '\n'

在对 Scott Hunter 的回答的评论中,您提到您 正在 使用 *c == '\n' 检查,这很好,但是 c 在该表达式中衰减为指向数组中第一个元素的指针(即 fgets 读取的第一个字符)。该字符不太可能是新行。

本质上,您正在写 c[0] == '\n' 而您应该查看最后一个字符 (c[strlen(c) - 1] == '\n') 以查看您读取的字符串是否以新行结尾

3。 Windows 行尾:

大多数系统使用 \n 作为新行。 Windows 使用 \r\nfgets 实际上会选择 \n 字符,但缓冲区不会为空。 c 的值实际上是:

c[500] = {'\r', '\n', 0};

因此字符串中的第一个字符将不匹配 \n。您没有指定编码和您使用的系统(也没有指定编译器),但请确保您 trim 任何前导回车符 return 如果需要的话。

这里有更多详细信息 here

可能 意味着从代码的角度来看,您看到的空行将不会以 \n 开头,而是以 \r 开头.尝试检查一下:

if (*c == '\r' && c[1] == '\n')
    //empty windows line
else if (*c == '\n')
    //empty *nix line
else
    //line was not empty