【问题标题】:C Linked List from file not exiting after printingC 来自文件的链接列表在打印后未退出
【发布时间】:2016-05-24 02:08:58
【问题描述】:

所以,我必须从文件输入中打印一个链接列表,我已经设法开始工作了:

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

typedef struct Vehicle{
    int option;
    char make [30];
    char model[30]; 
    int car_manufacture_date;
    float maximum_velocity;
    float mass;
    int seats;
    struct Vehicle *next;//linked list node
} vehicle_t;


int main (){

    FILE* fp;
    fp = fopen("vehicles.crash.txt", "r");

    vehicle_t* first_car = malloc(sizeof(vehicle_t));
    if (first_car == NULL){
        printf("Error. Failed to allocate memory to first_car\n");
        exit(1);
    }
    vehicle_t* current_vehicle = malloc(sizeof(vehicle_t));
    if (current_vehicle == NULL){
        printf("Error. Failed to allocate memory to current_vehicle\n");
        exit(1);
    }
    vehicle_t* new_vehicle = malloc(sizeof(vehicle_t));
    if (new_vehicle == NULL){
        printf("Error. Failed to allocate memory to new_vehicle\n");
        exit(1);
    }
    printf("GOOD1\n");

    current_vehicle = first_car;
    new_vehicle = first_car;
    printf("GOOD2\n");

    //Loading vehicles from file to linked list
    if (fp != NULL)
    {
        printf("GOOD3\n");
        while (fscanf(fp,"%d %s %s %d %f %f %d", &new_vehicle->option, new_vehicle->make, new_vehicle->model, &new_vehicle->car_manufacture_date, 
        &new_vehicle->maximum_velocity, &new_vehicle->mass, &new_vehicle->seats) != EOF)
        {
            printf("GOOD4\n");
            current_vehicle->next = new_vehicle;
            current_vehicle = current_vehicle->next;
            new_vehicle = malloc(sizeof(vehicle_t));
            if (first_car == NULL){
                printf("Error. Failed to allocate memory\n");
                new_vehicle->next=NULL;
                exit(1);
            }

            printf("GOOD5\n");
        }
    close(fp);
    printf("Input completed\n");
    }
    else
        printf("Error! couldn't find file\n");

    current_vehicle = first_car;

    while (current_vehicle != NULL) 
    {
        printf("Option: %d\tMake: %s\tModel: %s\tManufactured: %d\tMax Velocity: %.2f\tMass: %.2f\tSeats: %d\n",
        current_vehicle->option, current_vehicle->make, current_vehicle->model, current_vehicle->car_manufacture_date, 
        current_vehicle->maximum_velocity, current_vehicle->mass, current_vehicle->seats);

        new_vehicle = current_vehicle->next;
        current_vehicle = current_vehicle->next;
    };
    printf("Printing completed");
return 0;
}

在打印出最后一个文件项之前一切正常,之后程序崩溃。从我在其他帖子中看到的情况来看,while 循环与它们都匹配。

打印出来的"GOOD" 语句只是检查点

文件中的文本格式为:1 Toyota Camry 2010 200.0 1100.0 5

【问题讨论】:

  • 您在调试器下运行程序了吗?
  • 输入循环后需要current_vehicle-&gt;next = NULL;。还有很多内存泄漏。
  • 为什么会有前 3 个 malloc?我原以为您只需要为拥有真实数据的事物分配内存。
  • fclose 应该被调用而不是 close,其参数是文件描述符而不是 FILE 指针。
  • 启用编译器警告,你的 close() 甚至没有在你的代码中声明。它调用未定义的行为,因为它将FILE * 视为int

标签: c file linked-list


【解决方案1】:

我认为您忘记将最后一个列表节点的-&gt;next 字段设置为NULL。您刚刚调用了malloc,因此该值可能是随机的,导致您的打印失败。

【讨论】:

    【解决方案2】:

    无限循环的主要原因是未能将最终的 next 设置为 NULL [正如其他人提到的那样]。

    但是,我认为使用简化为您的代码更容易看出这一点,虽然大部分是正确的,但比它需要的要复杂。

    无论如何,这可以编译但我没有测试它[请原谅无偿的风格清理]:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Vehicle {
        int option;
        char make[30];
        char model[30];
        int car_manufacture_date;
        float maximum_velocity;
        float mass;
        int seats;
        struct Vehicle *next;               // linked list node
    } vehicle_t;
    
    int
    main()
    {
        FILE *fp;
    
        fp = fopen("vehicles.crash.txt", "r");
        if (fp == NULL) {
            printf("Error! couldn't find file\n");
            exit(1);
        }
    
        vehicle_t *first_car = NULL;
        vehicle_t *previous_vehicle = NULL;
    
        // Loading vehicles from file to linked list
        while (1) {
            vehicle_t *new_vehicle = malloc(sizeof(vehicle_t));
    
            if (new_vehicle == NULL) {
                printf("Error. Failed to allocate memory to new_vehicle\n");
                exit(1);
            }
    
            // NOTE: the lack of this [in your equivalent code] was the reason
            // for the infinite loop
            new_vehicle->next = NULL;
    
            if (fscanf(fp, "%d %s %s %d %f %f %d",
                &new_vehicle->option, new_vehicle->make, new_vehicle->model,
                &new_vehicle->car_manufacture_date, &new_vehicle->maximum_velocity,
                &new_vehicle->mass, &new_vehicle->seats) == EOF) {
                    free(new_vehicle);
                    break;
            }
    
            if (first_car == NULL)
                first_car = new_vehicle;
            else
                previous_vehicle->next = new_vehicle;
    
            previous_vehicle = new_vehicle;
        }
    
        fclose(fp);
    
        vehicle_t *current_vehicle = first_car;
    
        while (current_vehicle != NULL) {
            printf("Option: %d\tMake: %s\tModel: %s\tManufactured: %d\tMax Velocity: %.2f\tMass: %.2f\tSeats: %d\n",
                current_vehicle->option, current_vehicle->make,
                current_vehicle->model, current_vehicle->car_manufacture_date,
                current_vehicle->maximum_velocity, current_vehicle->mass,
                current_vehicle->seats);
            current_vehicle = current_vehicle->next;
        };
    
        printf("Printing completed");
    
        return 0;
    }
    

    【讨论】:

    • @paulsm4 感谢您的提醒,我会调整答案。就个人而言,我很少使用*scanf,所以我只是假设[简单] 部分是正确的。但是,这里的手册页说可以返回EOF,所以我想我还是得测试一下。
    • @paulsm4 我刚刚测试了程序并在输入结束时得到-1(EOF)。所以,这与 linux 手册页相匹配。这里也以同样的方式记录:freebsd.org/cgi/man.cgi?query=scanf&sektion=3
    • @paulsm4,你有点困惑fscanf 返回EOF,如果在第一次成功转换或匹配失败发生之前到达输入结尾。请参阅RETURN VALUE 部分下的 man fscanf
    • 啊,谢谢你的代码。老实说,我在物理编码时很难实现链表。这个概念本身很容易理解。此外,我还没有找到任何涉及从文件中填充链接列表的教程,而且对于像我这样相对较新的人来说,所问的问题有点太具体了。
    • @CraigEstey 实际上,您介意解释一下为什么将while(1) 放在那里吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    相关资源
    最近更新 更多