fgets无法读取换行符

时间:2016-10-03 15:43:46

标签: c file fgets scanf

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

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

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

2 个答案:

答案 0 :(得分:3)

好的,有几件事:

1。功能行为

来自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开头的行感兴趣,因此您只需跳过这些行

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不匹配。您没有指定编码和您使用的系统(也没有编译器),但如果需要,请确保修剪任何前导回车字符。

有关此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' )