如何将2D数组写入文件并返回C语言

时间:2017-12-15 17:08:15

标签: c arrays file

我试图将一块电路板(这是一个已动态分配的2D阵列)保存到一个文件中,以便以后加载"用户可以再次使用该板。要保存电路板,用户必须输入s filename。为了获得用户输入,我有一个else命令的if语句:

else if (playerMove.command == 's') {
    char* fileName = NULL;
    scanf(" %s", fileName);
    implementSave(boardState, fileName);

由于我们只学习了如何在C中读取/打开/写入二进制文件,我试图在我的implementSave函数中为此做同样的事情:

void implementSave(BoardState* boardState, char* fileName) {
  FILE* file = fopen(fileName, "wb");
  fwrite(fileName, sizeof(char), sizeof(boardState->board.theBoard), file);
  fclose(file);
}

注意:我在程序中使用了一些结构; struct board包含char** theBoard, int numRows, int numCols, char blankSpace

但是,当我尝试运行save命令时,这会给我一个错误。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:1)

此代码

 fwrite(fileName, sizeof(char), sizeof(boardState->board.theBoard), file);

表示:

  

将数据写入文件file。数据位于内存位置fileName处,数据由sizeof(boardState->board.theBoard)个项目组成,每个项目的sizeof(char)字节大。

这听起来对你好吗?我不这么认为;它是错误的,可以在fileName位置找到数据,因为你想将电路板数据写入文件而没有文件名,对吗?

另外要小心sizeof(); sizeof()无法动态确定某些内存的内容,它只知道静态内存的大小。 E.g。

char test[20];
size_t s = sizeof(test);

s将是20.但现在考虑一下:

char test[20];
char * ptr = test;
size_t s = sizeof(ptr);

现在s将是4或8,因为指针通常是4个字节大小或8个字节大小。 sizeof()为您提供指针的大小,而不是指针指向的内存大小。在C中没有办法获得指针所指向的内存块的大小,这个大小必须始终是已知的。

你说你的电路板是char ** theBoard,所以theBoard是一个指向内存或字符指针数组的指针。

theBoard -> [0] -> ['a1', 'b1', 'c1', 'd1', ... ] 
            [1] -> ['a2', 'b2', 'c2', 'd2', ... ] 
            [2] -> ['a3', 'b3', 'c3', 'd3', ... ]
            :

在这种情况下,创建代码需要看起来像那样(假设[0],[1],...是行):

 theBoard = calloc(numberOfRows, sizeof(char *));
 for (size_t i = 0; i < numberOfRows; i++) {
     theBoard[i] = calloc(numberOfCols, sizeof(char));
 }

如果是这种情况,您需要逐行编写数据:

for (size_t row = 0; row < numberOfRows; row++) {
    fwrite(boardState->board.theBoard[row], sizeof(char), numberOfCols, file);
}

当然,假设所有行都有相同数量的cols。

如果我可以给你一个小费,不要让小组char **成为char *,因为它会使一切变得更加容易。如果您的电路板是20x30(20行,30列),那么您可以像这样定义您的电路板:

char * theBoard = calloc(numberOfRows * numberOfCols, sizeof(char))

现在你只有一个数组,如下所示:

theBoard -> ['a1', 'b1', 'c1', 'd1', ... ,
             'a2', 'b2', 'c2', 'd2', ... ,
             'a3', 'b3', 'c3', 'd3', ... ,
             :
             ]

您将如何访问特定字段?很简单:

 int row = 5;
 int col = 8;
 char field = theBoard[(row * numberOfCols) + col];

然后你可以通过一个电话编写整个电路板:

fwrite(theBoard, sizeof(char), numberOfRows * numberOfCols, file);

看,更容易。您也可以通过调用free(theBoard);释放整个电路板,而在使用char **方法时,则必须执行此操作:

 for (size_t i = 0; i < numberOfRows; i++) {
     free(theBoard[i]);
 }
 free(theBoard);

答案 1 :(得分:0)

您不能只将双指针写入文件。您必须索引第一个指针中的每个元素,并将数据写入行(或列)中,但我已经演示了行。为此,请使用for循环。请注意(假设电路板 all ,您将保存到二进制文件),生成的文件大小应为numRow * numCol字节。

int i;
for (i = 0; i < BoardState->board.numRow; ++i) {
         fwrite(BoardState->board.theBoard[i], sizeof(char), BoardState->board.numCol, file)
}

读取(“加载”)文件与上面的代码相反 - 请注意,仅将板保存到文件是不明智的 - 我建议在文件的开头保存行数和列数到在读取(加载)文件时,可以轻松分配内存。

因此,假设您将行/列的数量存储在上面的代码中,则变为

fwrite(&BoardState->board.numRow, sizeof(int), 1, file);
fwrite(&BoardState->board.numCol, sizeof(int), 1, file);
int i;
for (i = 0; i < BoardState->board.numRow; ++i) {
         fwrite(BoardState->board.theBoard, sizeof(char), BoardState->board.numCol, file)
}

注意这有可能引入字节序问题。如果您感兴趣,可以使用Google。

相关问题