将数据从文件读取到链表时出现意外行为

Unexpected behavior while reading data into linked list from file

提问人:BlueBerryPie 提问时间:3/6/2023 更新时间:3/6/2023 访问量:63

问:

我正在尝试将链表中的数据读取和写入文件,但在这样做时遇到了无限循环。

法典:

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

struct Program { //structure to hold information of program
    char p_name[50];    //name of program
    char p_code[10];    //code of program
    char responsible[50];   //person responsible for program
    char r_email[50];   //email of responsible
    struct Program* next;
};

struct Program* inputProgram() {
    struct Program *temp = (struct Program*)malloc(sizeof(struct Program));
    printf("Enter the name of program: \n");
    scanf("%s", temp->p_name);
    printf("Enter the code of program: \n");
    scanf("%s", temp->p_code);
    printf("Enter the responsible of program: \n");
    scanf("%s", temp->responsible);
    printf("Enter the email of responsible: \n");
    scanf("%s", temp->r_email);
    return temp;
}

struct Program* addProgram(struct Program* head) {
    struct Program *temp = (struct Program*)malloc(sizeof(struct Program));
    temp = inputProgram();
    temp->next = NULL;
    if (head == NULL) {
        head = temp;
    }
    else {
        temp->next = head;
        head = temp;
    }
    return temp;
}

void write_to_file(struct Program* p) {
    FILE *of;
    of= fopen ("program.txt", "w");
    struct Program* temp = p;
    while(temp!=NULL) {
        fwrite (temp, sizeof(struct Program), 1, of);
        temp = temp->next;
    }
    fclose(of);
}

struct Program* read_from_file() {
    FILE *in;
    struct Program* head;
    struct Program* temp = (struct Program*)malloc(sizeof(struct Program));
    in = fopen ("program.txt", "r");
    while(fread((temp), sizeof(struct Program), 1, in)) {
        if (head == NULL) {
            head = temp;
            head->next = NULL;
        }
        else {
            temp->next = head;
            head = temp;
        }
    }
    fclose (in);
    return head;
}

int main() {
    struct Program *head = NULL;
    head = addProgram(head);
    head = addProgram(head);
    write_to_file(head);
    struct Program *temp = read_from_file();
    while(temp!=NULL){
        printf("%s", temp->p_name);
        temp = temp->next;   
    }

}

当我尝试从文件读取到链表中的数据时,我不断得到一个无限循环。据我了解,数据正在被正确读取,但一旦我尝试打印它。它不断进入无限循环。

我试图改变read_from_file功能。使用 malloc 为 head 变量分配空间。尝试将头的下一个分配给 NULL 并尝试使用临时进行相同的操作,但仍然不起作用。

知道问题出在哪里吗?

c 链接列表 malloc 无限循环 文件处理

评论

0赞 Weather Vane 3/6/2023
您可以通过检查 的返回值并限制它读取的数据长度来使数据读取更加可靠,例如。如果任何数据包含空格,它无论如何都会失败,并且字符串会变得不正常,可能会溢出大小的数组。在这种情况下,请使用包括前导空格。scanfif(scanf("%49s", temp->p_name) != 1) { /* handle error */ }[10]if(scanf(" %49[^\n]", temp->p_name) != 1)
2赞 Weather Vane 3/6/2023
请启用编译器警告。在它给出.这很可能导致不良行为。read_from_file()uninitialized local variable 'head' used
0赞 user3386109 3/6/2023
这篇文章是相关的,因为编译器检测到在 中使用之前未初始化。headread_from_file
0赞 user3386109 3/6/2023
@WeatherVane My IDE 检测到这一点,但在命令行上编译时没有检测到问题。您使用什么方法来查看警告?-Wall -Wextra
0赞 Weather Vane 3/6/2023
@user3386109 MSVC 默认级别。

答:

1赞 John Bollinger 3/6/2023 #1

您的程序存在几个问题,但是在遍历列表时导致无限循环的问题是只分配一个 .它将文件中的每个条目读取到同一结构中,如果它读取至少两个条目,则在第二次和每次后续读取时,该结构的指针设置为指向结构本身。read_from_file()struct Programnext

您需要为文件中的每个条目分配一个单独的结构对象。如果要避免动态分配然后释放一个额外的内容,则可以使用自动分配的结构进行初始读取,然后在读取成功后创建动态分配的副本。例:

struct Program *read_from_file(void) {
    struct Program *head = NULL;
    FILE *in = fopen("program.txt", "r");

    if (in) {
        struct Program prog;

        while(fread(&prog, sizeof(prog), 1, in)) {
            struct Program *temp = malloc(sizeof *temp);
            if (!temp) {
                break;
            }

            *temp = prog;
            temp->next = head;
            head = temp;
        }

        fclose(in);
    }

    return head;
}

另请注意,如上所述,第一个节点不需要特殊情况。但是,您应该检查函数调用是否成功,如上面所示,请使用 和 进行操作,以便正常处理失败。fopen()malloc()