簡體   English   中英

C 文件 Fwrite 和 fread 結構指針

[英]C file Fwrite and fread struct pointers

該程序僅適用於第一次。 第二次應該發生的是將相同的數據添加到二進制文件,但沒有發生。

第一次運行:運行正常,顯示寫入文件。

第二次運行:它寫入文件但不讀取。

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

typedef struct {
    char *name, *role, *course;
    int year, id;
} StudentFile;

void saveBin(StudentFile *studentsFile, int lines){
    FILE *file = fopen("studentsx.bin","ab");
    if (!file) {
        printf("\n\n\tImposible to open file. \n\n");
        exit(1);
    }

    for (int i = 0; i < lines; i++){
        fwrite(&studentsFile[i], sizeof(StudentFile), 1, file);
    }
    fclose(file);
}

void readBin(){
    StudentFile *studentsFile = malloc(sizeof(StudentFile)*5000);
    FILE *file = fopen("studentsx.bin","rb");
    if (!file) {
        printf("\n\n\tImposible to open file. \n\n");
        exit(1);
    }

    int j = 0;

    while (fread(&studentsFile[j], sizeof(StudentFile), 1, file)){
        printf("\nLine read %d: %s\t%s\t%d\t%d\t%s", j+1, studentsFile[j].name, studentsFile[j].role, studentsFile[j].year, studentsFile[j].id, studentsFile[j].course);
        j++;
    }

    fclose(file);
}

void main(){
    StudentFile *studentsFile = malloc(sizeof(StudentFile)*2);
    int lines = 0;

    studentsFile[0].name = "John";
    studentsFile[0].role = "Gamer";
    studentsFile[0].year = 1999;
    studentsFile[0].id = 1;
    studentsFile[0].course = "IOT";
    studentsFile[1].name = "Piter";
    studentsFile[1].role = "GamerXL";
    studentsFile[1].year = 1991;
    studentsFile[1].id = 2;
    studentsFile[1].course = "IOTXL";
    lines = 2;

    saveBin(studentsFile, lines);
    readBin();
}

您正在編寫指針,而不是字符串。 fwrite寫入 memory 的單個連續數組。在您的情況下, StudentFiles和實際字符串分散在 static memory 和堆 memory 中。

考慮你的結構:

typedef struct {
  char *name, *role, *course;
  int year, id;
} StudentFile;

在 memory 中看起來像這樣:

[<pointer to name><pointer to role><pointer to course><year><id>]

memory 不同區塊的其他地方:

[John\0Gamer\0\OIT\o.......]

你寫了上面的第一個塊而遺漏了第二個塊。

這個問題有多種方法,我們通常將它們命名為“序列化”——將復雜的數據結構序列化為一個線性文件。

其中一種方法是在您的結構StudentFile中分配固定大小的塊:

#define MAX_NAME 100
#define MAX_ROLE 100
#define MAX_COURSE 100
typedef struct {
  char name[MAX_NAME];
  char role[MAX_ROLE];
  char course[MAX_COURSE];
  int year, id;
} StudentFile;

然后字符串namerolecourse將在StudentFile

[<100 bytes for name><100 bytes for role><100 bytes for course><year><id>]

這是 memory 的連續塊,如果可以像您一樣使用單次調用 fwrite 來編寫。

但是您將無法像以前那樣分配字符串

studentsFile[i].name = "John";

C 為此有 strncpy:

strcpy(studentsFile[0].name, "John", MAX_NAME);

另一種方法是多次調用 fwrite。 對於每個字符串,首先寫入長度,然后是字符串本身。 對於像int這樣的基本類型,您只需編寫 int 即可。

首先,您從指針指向的不同位置收集字符串:

size_t nameLen = strlen(studentsFile[i].name) + 1;/* +1 for the final zero*/
fwrite(&nameLen, sizeof(size_t), 1, file);
fwrite(studentsFile[i].name, nameLen, 1, file);
size_t roleLen = strlen(studentsFile[i].role) + 1;
fwrite(&roleLen, sizeof(size_t), 1, file);
fwrite(studentsFile[i].role, roleLen, 1, file);
size_t courseLen = strlen(studentsFile[i].course) + 1;
fwrite(&courseLen, sizeof(size_t), 1, file);
fwrite(studentsFile[i].course, courseLen, 1, file);

然后你寫原始類型:

fwrite(&studentsFile[i].year, sizeof(int), 1, file);
fwrite(&studentsFile[i].id, sizeof(int), 1, file);

下次讀取文件時,您將依賴寫入順序並以相同順序讀回字段:

size_t nameLen;
fread(&nameLen, sizeof(size_t), 1, file);
char *name = malloc(nameLen);
fread(name, nameLen, 1, file);
size_t roleLen;
fread(&roleLen, sizeof(size_t), 1, file);
char *role = malloc(roleLen);
fread(role, roleLen, 1, file);
size_t courseLen;
fread(&courseLen, sizeof(size_t), 1, file);
char *course = malloc(courseLen);
fread(course, courseLen, 1, file);
int year;
fread(&year, sizeof(int), 1, file);
int id;
fread(&id, sizeof(int), 1, file);

printf("\nLine read %d: %s\t%s\t%d\t%d\t%s", j+1, name, role, year, id, course);

問題出在其他地方:仔細想想,你的代碼在這里用fwrite()做什么?

typedef struct {
    char *name, *role, *course;
    int year, id;
} StudentFile;

fwrite(&studentsFile[i], sizeof(StudentFile), 1, file);

studentFile寫入單個元素后,文件內容是什么樣的?

  1. 三個字符串和兩個整數(二進制形式)
  2. 三個指向某處的指針和兩個整數(都是二進制形式)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM