如何将这些结构保存到二进制文件中?

How can I save these struct to a binary file?

我有两个结构要保存到二进制文件中。

typedef struct {
    int height;
    int width;
    int resistance_count;
    Resistance** resistances; //contains a list of resistance*.
} Breadboard;

typedef struct {
    int start_cell_col;
    int end_cell_col;
    int cell_row;
    float resistance_value;
} Resistance;

我有点不确定我应该如何拯救它们。由于我需要跟踪“resistance_count”变量以了解我将节省多少电阻,因此我必须先保存面包板。为此,我的尝试如下:

bool save_breadboard(char* filename, Breadboard* bb_pointer) {
    errno_t error_code;
    FILE* fp_board;
    
    /* Opens board.bin to save the board struct on. */
    error_code = fopen_s(&fp_board, filename, "wb");
    if (error_code != 0) {
        return false;
    }
    size_t elements_written = fwrite(bb_pointer, sizeof(Breadboard), 1, fp_board);
    if (elements_written == 0) {
        return false;
    }
    fclose(fp_board);
    return true;
}

在我目前的尝试中,我发现了一个问题,即我还保存了所有可能不必要的“阻力**”。我不知道是否有一种方法可以跳过保存电阻指针指针。但我不认为当我最终阅读它时它会导致问题。

为了避免阻力,我 运行 遇到了问题。这是我的工作:

bool save_resistances(char* filename, Breadboard* bb_pointer) {
    errno_t error_code;
    FILE* fp_resistances;
    /* Opens resistances.bin to save the array of resistance pointers on. */
    error_code = fopen_s(&fp_resistances, filename, "wb");
    if (error_code != 0) {
        return false;
    }
    size_t elements_written = fwrite(bb_pointer->resistances, sizeof(Resistance),
                                      bb_pointer->resistance_count, fp_resistances);
    if (elements_written == 0) {
        return false;
    }
    fclose(fp_resistances);

    return true;
}

我很确定我会以这种方式保存阻力指针。我无法检查二进制文件,但如果我取消引用阻力指针帮助?

size_t elements_written = fwrite(*bb_pointer->resistances, sizeof(Resistance),
                                 ^         bb_pointer->resistance_count, fp_resistances);

如果能帮助我理解 reading/writing 二进制文件,我们将不胜感激。

您离解决方案越来越近了。只是缺少一些东西...

With my current attempt I see a problem that I am also saving all the "Resistance**" which is perhaps unnecessary. I don't know if there is a way I could skip saving the resistance pointer pointers [...]

是啊,没必要。实际上,在回读时,您将不得不丢弃它并用有效值覆盖它。我不会费心去寻找跳过指针的奇怪方法。我建议写出一个 NULL 指针,以避免在通过执行以下操作重新读取数据时出错:

void *tmp = bb_pointer->resistances;
bb_pointer->resistances = NULL;
size_t elements_written = fwrite(bb_pointer, sizeof(Breadboard), 1, fp_board);
bb_pointer->resistances = tmp;

现在,来到您实际保存所有结构的部分,这是错误的:

size_t elements_written = fwrite(bb_pointer->resistances, sizeof(Resistance),
                                      bb_pointer->resistance_count, fp_resistances);

而做*bb_pointer->resistances也是错误的。你想保存每个 Resistance 结构,但你的 ->resistances 是一个指针数组,所以(1)保存指针(bb_pointer->resistances)显然是错误的,(2)试图保存就好像它们在内存中是连续的一样(*bb_pointer->resistances)也是错误的。您唯一可以做的就是遍历数组并取消引用每个指针,单独保存:

for (int i = 0; i < bb_pointer->resistance_count; i++) {
    if (fwrite(bb_pointer->resistances[i], sizeof(Resistance), 1, fp_resistances) != 1) {
        // handle error
        return false;
    }
}

最后,请记住 fwrite returns 写入的元素数量应始终等于请求的数量,因此通常您需要使用 res != count 检查错误,不与 res == 0:

size_t elements_written = fwrite(bb_pointer, sizeof(Breadboard), 1, fp_board);
if (elements_written != 1) {
    return false;
}