【问题标题】:fread/fwrite not working as expectedfread/fwrite 没有按预期工作
【发布时间】:2016-03-14 13:46:16
【问题描述】:

所以我正在尝试编写具有学生记录数据库的 ac 文件,一旦文件运行,它应该从二进制文件中读取学生记录并将它们添加到链表中:学生结构如下所示:

typedef struct student {
    char lname[10], initial, fname[10];
    unsigned long SID;
    float GPA;

    struct student* next; /* pointer to the next student record */   
} studentList;

我对我的数据使用单链表,如果我使用 fscanf 读写数据,我的代码运行良好。但是,一旦我开始使用 fwrite 和 fread,每次我的程序加载它都不会正确加载文本文件中的数据,当我检查二进制文件时,它似乎有数据。这是我的加载和写入数据功能:

void printRecords() {
    FILE *fPointer = fopen("data.bin", "w");
    studentList *newStudent = head;
    while (newStudent != NULL) { /*Loop through linked list starting from head node*/
        fwrite(&newStudent, sizeof(newStudent), 1, fPointer);

        newStudent = newStudent->next;
    }
}

void loadRecords() {
    studentList *cStudent;
    FILE *fPointer = fopen("data.bin", "r");
    int counter = 0;
    int x = 0;
    int n = 0;
    while (n != 0) {
        printf("test\n");
        if (fPointer == NULL) {
            break;
        }
        cStudent = (studentList *)malloc(sizeof(studentList));
        n = fread(&cStudent, sizeof(cStudent), 1, fPointer);
        x = cStudent->GPA;
        printf("%d\n", x);
        if (feof(fPointer)) { break; }
        if (counter == 0) {
            head = cStudent;
            temp = (studentList *)malloc(sizeof(studentList));
            temp = cStudent;
            counter++;
        }

        temp->next = (studentList *)malloc(sizeof(studentList));
        temp->next = cStudent;
        temp = temp->next;
    }
    fclose(fPointer);
}

所以我做错了什么,因为现在它没有将任何内容读入我的列表,它似乎在写入但不确定它是否甚至写入了正确的数据,我花了很长时间试图弄清楚这一点并拥有卡了一段时间了,先谢谢了。

【问题讨论】:

  • 你还没有关闭printRecords()中的文件

标签: c fwrite fread


【解决方案1】:

read write to binary files in c

FILE   *fPointer=fopen("data.bin","wb");  //to write file
FILE *fPointer=fopen("data.bin","rb");    //to read file

【讨论】:

  • 在 Linux 系统上,b 标志无效。因此,在提供此作为答案之前,最好澄清一下 OP 是否在 Linux 上运行。如果是 Linux,那么这可能不是答案。
  • 二进制模式在某些平台(例如 Windows)上是可取和必要的,但这并不是代码的唯一问题。
  • 是的,我在 linux 上运行,我已经实施了 chqrlie 的修复,但现在我遇到了 seg 错误并试图解决它。我的结构和头节点被声明为全局变量,希望这也能有用。
【解决方案2】:

您的代码存在多个问题。

printRecords有问题:

  • 您应该使用二进制模式。
  • 您写的是指针的内容和一些不确定的内容,而不是指针指向的内容。这实际上是未定义的行为。
  • 您忘记关闭文件。
  • next 成员写入文件的值没有意义。写入相同的记录可能会为不同的运行产生不同的文件内容。

这是一个更正的版本,如果文件无法打开,则返回写入的记录数或 -1:

int printRecords(void) {
    FILE *fPointer = fopen("data.bin", "wb");
    studentList *sp;
    int n = 0;

    if (fPointer == NULL)
        return -1;

    /* Loop through linked list starting from head node */
    for (sp = head; sp != NULL; sp = sp->next) {
        n += fwrite(sp, sizeof(newStudent), 1, fPointer);
    }
    fclose(fPointer);
    return n;
}

loadRecords还有更多问题:

  • 也应该使用二进制模式。
  • 您测试文件结尾的方式不正确。
  • 链接记录的方式也不起作用。

这是loadRecords 的更正版本,它返回读取的记录数,如果文件无法打开,则返回-1:

int loadRecords(void) {
    studentList student, *newsp, *sp;
    FILE *fPointer = fopen("data.bin", "rb");
    int n = 0;

    if (fPointer == NULL)
        return -1;

    while (fread(&student, sizeof(student), 1, fPointer) == 1) {
        n++;
        student.next = NULL;  // value read from file is meaningless
        newsp = malloc(sizeof(studentList));
        *newsp = student;
        if (head == NULL) {
            head = newsp;
        } else {
            /* append the new record to the list */
            for (sp = head; sp->next; sp = sp->next)
                continue;
            sp->next = newsp;
        }
    }
    fclose(fPointer);
    return n;
}

请注意,以这种方式将二进制数据存储到文件系统是不可移植的。整数和浮点数的表示可能因平台而异,以及结构成员的对齐方式,尤其是在文件中无论如何都无用的next 指针。该文件只能在同一平台上使用编写该文件的同一程序读取,这使其成为备份或持久存储的糟糕选择。

【讨论】:

  • 非常感谢您的回答,但是我忘记指出我在 linux 上运行,因此这可能是个问题。在我实施了你的修复后,我目前遇到了段错误,我不知道究竟是为什么。
  • @MohammedAl-Huneidi:将您更正的程序发布到 pastebin,一定还有其他错误。
【解决方案3】:

文件写入函数有问题,主要是数据指针和大小:

void printRecords(){
    FILE *fPointer = fopen("data.bin","wb");    // add "b" mode (MSVC)
    if (fPointer == NULL)                       // check file opened
        exit(1);                                // or report "Cannot open file"
    studentList *newStudent = head;
    while(newStudent !=NULL)
    {
        fwrite(newStudent, sizeof(*newStudent), 1, fPointer);   // remove the & and add a *
        newStudent = newStudent->next;
    }
    if (fclose(fPointer))                       // close the file
        exit(1);                                // or report "Failed to close file"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2020-03-18
    • 2012-06-14
    • 2014-11-15
    • 1970-01-01
    • 2012-07-02
    • 2011-09-07
    相关资源
    最近更新 更多