Writing/reading C 中的二维字符数组到二进制文件

Writing/reading 2D char array in C to binary file

我有一个数组,其中包含 6 个单词和一个秘密单词

char boardInputs[7][6];

每次用户输入单词时,我都需要将这个数组自动保存到二进制文件中。重启程序后,我需要从二进制文件中读取保存的words数组,并将其安装到板子的输入数据数组中

void readArray(int rows, int cols, char array[rows][cols]) {
    FILE *data;
    data = fopen("autosave.bin", "rb");
    fread(array, sizeof(char[rows][cols]), 1, data);
}


void autoSave() {
    int result = EXIT_SUCCESS;
    char file_name[] = "autosave.bin";
    FILE *fp = fopen(file_name, "wb");
   
    if (fp == NULL) {
        result = EXIT_FAILURE;
        fprintf(stderr, "fopen() failed for '%s'\n", file_name);
    } else {
        size_t element_size = sizeof *boardInputs;
        size_t elements_to_write = sizeof boardInputs;
        size_t elements_written = fwrite(boardInputs, element_size, elements_to_write, fp); 
        if (elements_written != elements_to_write) {
            result = EXIT_FAILURE;
            fprintf(stderr, "fwrite() failed: wrote only %zu out of %zu elements.\n", 
                    elements_written, elements_to_write);
        }

        fclose(fp);
    }
}

int main() {
    int cols = 7;
    int rows = 6;
    char (*myArray)[cols] = allocArray(rows, cols);

    readArray(rows, cols, myArray);
    strcpy(boardInputs, myArray);
    free(myArray);
}

我创建了这段代码,但是二进制文件中的单词设置不正确。如何解决?

  1. autoSave() 使用不正确的参数调用 fwrite()sizeof boardInputs 是二维数组的总大小,因此元素数为 1。这是关键问题。
  2. autoSave() 不会 return 消除任何东西 result.
  3. autoSave()readArray() hard-code 相同的路径,因此将其设为定义而不是重复。
  4. readArray() 依赖于全局变量,因此将行和列提升为宏常量并简化了参数数量。
  5. readArray() 应该关闭 data 文件句柄。
  6. main() 应该 return 一个整数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ROWS 7
#define COLS 6
#define PATH "autosave.bin"
char boardInputs[ROWS][COLS];

void autoSave() {
    FILE *fp = fopen(PATH, "wb");
    if(!fp) {
        fprintf(stderr, "fopen() failed for '%s'\n", PATH);
        return;
    }
    size_t elements_to_write = sizeof boardInputs;
    size_t elements_written = fwrite(boardInputs, 1, elements_to_write, fp);
    if (elements_written != elements_to_write) {
        fprintf(stderr, "fwrite() failed: wrote only %zu out of %zu elements.\n",
            elements_written, elements_to_write);
    }
    fclose(fp);
}

void printArray(char array[ROWS][COLS]) {
    for(int i = 0; i < ROWS; i++) {
        printf("%d: %s\n", i, array[i]);
    }
}

void readArray(char array[ROWS][COLS]) {
    FILE *data = fopen(PATH, "rb");
    fread(array, sizeof(char[ROWS][COLS]), 1, data);
    fclose(data);
}


int main() {
    for(unsigned i = 0; i < 7; i++) {
        char s[7];
        sprintf(s, "%u", i);
        strcpy(boardInputs[i], s);
    }
    printArray(boardInputs);
    autoSave();
    char myArray[ROWS][COLS];
    readArray(myArray);
    printArray(myArray);
    return 0;
}

输出表明读写具有相同的值:

0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6

您的代码中存在多个问题:

  • 您没有在 readArray 中测试 fopen() 失败;
  • 您没有关闭 read_array 中的文件;
  • resultautoSave 中未使用;
  • strcpy复制整板不正确。您应该测试 readArray 是否成功并使用 memcpy;
  • autoSave中的大小不正确:size_t element_size = sizeof *boardInputs计算出一个字的大小,即6个字节,size_t elements_to_write = sizeof boardInputs是整个数组的字节大小。 fwrite 将尝试写入 6 * 42 字节,当它访问超出其边界的 boardInputs 时导致未定义的行为。数组的长度是它的大小除以元素大小。在这种情况下,最好以字节为单位,而不是以字为单位;
  • 为了保证boardInputsmyArray的一致性,需要在构造中定义相同的大小

这是修改后的版本:

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

#define WORD_COUNT 7
#define WORD_LEN   6
char boardInputs[WORD_COUNT][WORD_LEN];
const char *autoSaveFilename = "autosave.bin";

int readArray(int rows, int cols, char array[rows][cols]) {
    FILE *fp = fopen(autoSaveFilename, "rb");
    if (fp == NULL)
        return -1;
    int n = fread(array, sizeof(char[rows][cols]), 1, fp);
    fclose(fp);
    return n == 1 ? 0 : -1;
}

int autoSave(void) {
    int result = EXIT_SUCCESS;
    FILE *fp = fopen(autoSaveFilename, "wb");
   
    if (fp == NULL) {
        result = EXIT_FAILURE;
        fprintf(stderr, "fopen() failed for '%s': %s\n",
                autoSaveFilename, strerror(errno));
    } else {
        size_t element_size = 1;
        size_t elements_to_write = sizeof(boardInputs);
        size_t elements_written = fwrite(boardInputs, 1, elements_to_write, fp); 
        if (elements_written != elements_to_write) {
            result = EXIT_FAILURE;
            fprintf(stderr, "fwrite() failed: wrote only %zu bytes out of %zu.\n", 
                    elements_written, elements_to_write);
        }
        fclose(fp);
    }
    return result;
}

int main() {
    char myArray[WORD_COUNT][WORD_LEN];

    if (!readArray(WORD_COUNT, WORD_LEN, myArray))
        memcpy(boardInputs, myArray, sizeof boardInputs);

    return 0;
}