I have an array, which holds 6 words and a secret word
char boardInputs[7][6];
I need to autosave to binary file this array every time when user entered the word. After restarting the program, I need to read the saved array of words from the binary file and install it into the input data array of the board
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);
}
I created this code, but the words from the binary file are set incorrectly. How to fix it?
CodePudding user response:
There are multiple problems in your code:
- you do not test for
fopen()
success inreadArray
- you do not close the file in
read_array
result
is unused inautoSave
.strcpy
is incorrect to copy the whole board. You should test ifreadArray
succeeded and usememcpy
.- the sizez in
autoSave
are incorrect:size_t element_size = sizeof *boardInputs
evaluates to the size of a word, ie 6 bytes, andsize_t elements_to_write = sizeof boardInputs
is the size in bytes of the whole array.fwrite
will attempt to write6 * 42
bytes, causing undefined behavior as it accessesboardInputs
beyond its boundaries. The length of an array is its size divided by the element size. In this case, it is probably best to use bytes, not words as the unit. - to ensure consistency between
boardInputs
andmyArray
, they should be defined with the same size by construction.
Here is a modified version:
#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;
}
CodePudding user response:
autoSave()
is callingfwrite()
with incorrect arguments,sizeof boardInputs
is the total size of the 2d array so number of elements is 1. This was the key issue.autoSave()
doesn't return anything so eliminateresult
.autoSave()
andreadArray()
hard-code the same path, so make it a define instead of duplication.readArray()
relies on a global variable, so elevated rows and cols to macro constants and simplified number of arguments.readArray()
should close thedata
file handle.main()
should return an int.
#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;
}
The output demonstrate the read and write have the same values:
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