char c[500];
fgets(c, 500, fp);
if (c == "\n") {
customer.checkoutTime = 0;
customer.payment = 0;
}
如果fgets读取一个空行,我想在这两个var中存储两个零。但它失败了,从不执行if-block代码。 fgets应该如何读取空行?
答案 0 :(得分:3)
好的,有几件事:
来自description of fgets
功能:
C库函数
char *fgets(char *str, int n, FILE *stream)
从指定的流中读取一行并将其存储到str指向的字符串中。当读取(n-1)个字符,读取换行符或达到文件结尾时(以先到者为准),它会停止。
与man fgets
相同:
fgets()从流中读取最多一个小于大小的字符,并将它们存储到s指向的缓冲区中。读数在EOF或换行符后停止。如果读取换行符,则将其存储到缓冲区中。终止空字节('\ 0')存储在缓冲区中的最后一个字符之后。
fgets
在遇到\n
(新行)字符后停止阅读。但是让我们看看我们可以用结果字符串做什么:
鉴于fgets
在读取最多N-1个字符后停止,您知道,如果strlen(c)
为499,则可能没有遇到EOF / EOL字符。
如果fgets
遇到EOL,它将返回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 == '\0')
//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 == '\0'
检查以响应chux的一条评论,以防fgets
实际上是从文件中读取一个空字符。由于您只对以\n
开头的行感兴趣,因此您只需跳过这些行
除此之外,您发布的代码:
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'
)以查看你读取的字符串是否以新行结尾
大多数系统使用\n
表示新行。 Windows使用\r\n
。 fgets
实际上会接收\n
字符,但缓冲区不会为空。 c
的值实际上是:
c[500] = {'\r', '\n', 0};
因此字符串中的第一个字符与\n
不匹配。您没有指定编码和您使用的系统(也没有编译器),但如果需要,请确保修剪任何前导回车字符。
有关此here
的更多详情此 可能表示从代码角度看,您看到为空的行不是以\n
开头,而是以\r
开头。请尝试检查:
if (*c == '\r' && c[1] == '\n')
//empty windows line
else if (*c == '\n')
//empty *nix line
else
//line was not empty
答案 1 :(得分:2)
c
不是单个字符;它是指向一系列字符的指针。你的if
正在询问这是否与你预先填充换行符的位置相同,当用这种方式描述时,显然不会成功。
如果您想查看c
指向的第一个字符是换行符,请使用if ( *c == '\n' )
。