C fgets在非空文件上返回null

C fgets在非空文件上返回null,c,file-io,null,fgets,C,File Io,Null,Fgets,我试图从文件中读取非特定数量的成对整数。我还想跳过以#开头的行。我的问题是什么也没印出来。当我尝试打印fgets返回的值时,它打印为null。我真的很感激你能给我一点帮助,因为我对C不是很有经验,如果你不关注feof,我会非常感激,因为我已经读过为什么feof是坏的 该文件如下所示: #This must #be #skipped 1233 14432 4943928 944949 11233 345432 代码是: #include<stdio.h> #include<

我试图从文件中读取非特定数量的成对整数。我还想跳过以#开头的行。我的问题是什么也没印出来。当我尝试打印fgets返回的值时,它打印为null。我真的很感激你能给我一点帮助,因为我对C不是很有经验,如果你不关注feof,我会非常感激,因为我已经读过为什么feof是坏的

该文件如下所示:

#This must
#be
#skipped
1233 14432
4943928  944949
11233   345432
代码是:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct{
int start;
int end;
}path;
int main()
{
    path* array;
    array=malloc(5*sizeof(path));
    if(array==NULL){
    printf("Error allocating memory\n");
    abort();
    }


    FILE* fd=fopen("File.txt","r");
    if(fd==NULL){
    printf("Error opening file\n");
    abort();
    }
    char buff[200];
    int counter=0;
    if(fopen==NULL){
       printf("Error opening file\n");
        abort();
    }
    char c;
    while(!feof(fd)||counter==6){
        fgets(buff,200,fd);
        c=buff[0];
        if(strcmp(buff[0],"#")){
            continue;
        }
        sscanf(&buff,"%d %d",array[counter].start,array[counter].end);
        printf("%d\t%d\n",array[counter].start,array[counter].end);
        counter++;
    }


    fclose(fd);
    free(array);
    return 0;
}

#包括
#包括
#包括
类型定义结构{
int启动;
内端;
}路径;
int main()
{
路径*数组;
数组=malloc(5*sizeof(path));
if(数组==NULL){
printf(“分配内存时出错”);
中止();
}
FILE*fd=fopen(“FILE.txt”、“r”);
如果(fd==NULL){
printf(“打开文件时出错”);
中止();
}
字符buff[200];
int计数器=0;
如果(fopen==NULL){
printf(“打开文件时出错”);
中止();
}
字符c;
而(!feof(fd)|计数器==6){
fgets(buff,200,fd);
c=增益[0];
if(strcmp(buff[0],“#”)){
继续;
}
sscanf(&buff,“%d%d”,数组[计数器]。开始,数组[计数器]。结束);
printf(“%d\t%d\n”,数组[counter]。开始,数组[counter]。结束);
计数器++;
}
fclose(fd);
自由(数组);
返回0;
}

您不应在
while
条件下选中
feof()
。看

循环应为:

while (fcounter < 5 && fgets(buff, 200, fd))
while(fcounter<5&&fgets(buff,200,fd))

首先,回答问题的标题:
fgets()
在文件末尾返回
NULL
,而不是在文件为空时返回

无论如何,您在
while
循环中的测试不正确:

  • feof()
    仅当您已尝试读取并且已到达文件结尾且读取不成功时,才会给出真实结果。当
    read
    尝试为您提供尽可能多的字节时。。。如果文件结束,则获取文件结束条件的唯一方法是在读取某些内容失败后。最好检查
    fgets()
    result,因为它在现在无法读取任何内容时返回
    NULL
    。(并非最后一读)如此

    或者只是

    while(fgets(buff, sizeof buff, fd))
    
    那就更好了。另外,请参见如何使用
    sizeof
    运算符来使用已用缓冲区的大小,而不是重复(并且容易出错)两个位置的实际字节数。如果您决定更改缓冲区的大小,还需要更改
    fgets()
    调用中要读取的实际字节数,这样就有可能忘记其中一个字节,从而导致出现问题

  • 只有在
    期间,您才可以命令留在循环中!feof()
    或当
    计数器==6
    时(首先,这将使控件在计数器等于6时进入循环,尽管您是否已达到EOF,这不可能是正确的)认为只有在两个条件都为false时才能退出循环(这意味着
    feof()
    返回true并且也返回计数器!=6),您最好编写:

    while(fgets(buff, sizeof buff, fd) && counter < max_number_of_iterations)
    
    也是不正确的,因为
    buff[0]
    是一个字符(实际上,它是缓冲区中读取的第一个字符,
    “#”
    是一个字符串文字(不是字符),您可能至少从编译器得到了一个警告,从中可以说没有单词。您最好测试两个字符是否相等,如中所示

    if (buff[0] == '#')  /* this time '#' is a character literal, not a string literal */
    
  • 排队

    if (fopen == NULL)
    
    fopen
    本身就是指向库函数的指针
    fopen(3)
    ,这不是您想要的(
    fopen
    总是
    !=NULL
    ),但是

    (您以前是这样做的,因此最好删除所有此代码)

  • 您定义了一个
    char c;
    ,然后将其初始化为
    buff
    的第一个字符,然后您就根本不使用它了。这对您的代码没有影响,但它的样式不好,并且会让将来的维护人员感到困惑

  • sscanf(&buff),“%d%d”行中,…
    您不需要传递
    &buff
    ,而
    buff
    已经是一个字符指针。最好传递
    buff
    。n但是,您需要传递指向正在读取的变量的指针,因此需要将其更正为:

    sscanf(buff, "%d%d", &array[counter].start, &array[counter].end);
    
    不这样做将导致未定义的行为,这将很难实现,因为使用未初始化的变量(以及更多指向变量的指针)可能会使代码一开始工作,但在生产一段时间后失败……这是一个非常严重的错误

更正了所有这些错误后,您的代码应该如下所示:

普鲁士 使用您发布的
文件.txt

最后,一个提示:
尽管您只想知道循环下降的原因,而不想知道为什么
feof()
在这里没有用处(以及许多其他您没有要求的东西,这些东西在代码中是错误的),如果确实是这样,您最好发布一个示例,该示例只显示您应该阅读的页面所建议的失败行为,我建议您这样做。

如果(fopen==NULL){则此语句,如果(strcmp(buff[0],“#”)则此语句){没有意义。
counter==6
应该是
counter<5
你在哪里检查
fgets()的值?
?Azzarian“如果你不关注feof,我将非常感激,因为我已经阅读了为什么feof不好”,这与(!feof(fd)相反…<代码>是问题的一个重要部分。请考虑修复并查看编译器警告。
if (fopen == NULL)
if (fd == NULL){
sscanf(buff, "%d%d", &array[counter].start, &array[counter].end);
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N (5)  /* I have  defined this constant so you can 
                * change its value without having to go all 
                * the code for occurrences of it and 
                * changing those */

typedef struct{
    int start;
    int end;
} path;

int main()
{
    path* array = malloc(N*sizeof(path)); /* better declare and init */
    if(array==NULL){
        printf("Error allocating memory\n");
        abort();  /* have you tried exit(EXIT_FAILURE); ?? */
    }

    FILE* fd=fopen("File.txt","r");
    if(fd==NULL){
        printf("Error opening file\n");
        abort();
    }
    char buff[200];
    int counter=0;
    while(fgets(buff, sizeof buff, fd) && counter < N){
        if(buff[0] == '#'){
            continue;
        }
        sscanf(buff, "%d %d", &array[counter].start, &array[counter].end);
        printf("%d\t%d\n", array[counter].start, array[counter].end);
        counter++;
    }

    fclose(fd);
    free(array);

    return 0;
}
$ pru
1233    14432
4943928 944949
11233   345432