Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何循环遍历文件的每一行?_C_File - Fatal编程技术网

C 如何循环遍历文件的每一行?

C 如何循环遍历文件的每一行?,c,file,C,File,我试图为文件中的每一行分配一个新结构的内存,但当文件为空时,我的循环仍会分配一次内存。问题在于使用while(!feof(file)),但我无法找到while循环的替代检查方法 循环如下所示: while(!feof(f)) { p = (struct PlayerTime*)malloc(sizeof(struct PlayerTime)); head = p; fscanf(f, "%f %s", &p->seconds, p->name);

我试图为文件中的每一行分配一个新结构的内存,但当文件为空时,我的循环仍会分配一次内存。问题在于使用while(!feof(file)),但我无法找到while循环的替代检查方法

循环如下所示:

while(!feof(f))
{
    p = (struct PlayerTime*)malloc(sizeof(struct PlayerTime));
    head = p;
    fscanf(f, "%f %s", &p->seconds, p->name);
    p = p->next;
}
// Allocate the space for the first element
struct PlayerTime *head=malloc(sizeof(*head));
// p will always point to a pointer to the element to be filled;
// let's start with the head
struct PlayerTime **p=&head;
// Try to read
while(fscanf(f, "%f %s", &((*p)->seconds), (*p)->name)==2)
{
    // If we are here, the last read was successful
    // Move p to the pointer to the next element
    p = &((*p)->next);
    // ... and allocate the space for such element
    *p = malloc(sizeof(**p));
}
// After exit, there's an extra element that we allocated but we couldn't read
// Free it
free(*p);
// And put the relevant pointer to NULL
// (it will terminate the list, or set head to NULL if no element has been read)
*p=NULL;
指针和结构都是在循环之前定义的,如果文件中没有任何内容,我就不知道如何让它不循环

  • feof(f)
    表示
    EOF
    尚未命中
  • fscanf
    点击
    EOF
    并失败
  • feof(f)
    停止循环,因为已命中
    EOF
  • 正确的方法:

    while (fscanf(f, "%f %s", &p->seconds, p->name) == 2) {
        ...
    }
    
    提示:还要花更多的时间思考何时以及如何分配内存,可能会发生什么情况,以及应该如何处理这些情况。

    这一点已经讨论得非常透彻
    feof
    不会告诉您文件是否将在下一次读取时完成,但会告诉您是否已尝试读取但由于文件结束而失败

    在您的情况下,解决方案是检查读取是否失败(通过检查
    fscanf
    的返回值),在这种情况下,取消分配结构;这也使您的代码更加健壮,因为它还检查EOF以外的错误(例如IO错误、无效数据格式等)

    顺便说一句,
    p=p->next
    不会实现您的期望。如果您正在“动态”构建链接列表,您可以执行以下操作:

    while(!feof(f))
    {
        p = (struct PlayerTime*)malloc(sizeof(struct PlayerTime));
        head = p;
        fscanf(f, "%f %s", &p->seconds, p->name);
        p = p->next;
    }
    
    // Allocate the space for the first element
    struct PlayerTime *head=malloc(sizeof(*head));
    // p will always point to a pointer to the element to be filled;
    // let's start with the head
    struct PlayerTime **p=&head;
    // Try to read
    while(fscanf(f, "%f %s", &((*p)->seconds), (*p)->name)==2)
    {
        // If we are here, the last read was successful
        // Move p to the pointer to the next element
        p = &((*p)->next);
        // ... and allocate the space for such element
        *p = malloc(sizeof(**p));
    }
    // After exit, there's an extra element that we allocated but we couldn't read
    // Free it
    free(*p);
    // And put the relevant pointer to NULL
    // (it will terminate the list, or set head to NULL if no element has been read)
    *p=NULL;
    

    除了上面的链接,请参见对已接受答案的评论。