fwrite не записывает весь буфер

В настоящее время я делаю небольшую тестовую программу для простой проверки файлов. Программа записывает в файлы две маленькие матрицы (А и В), закрывает и снова открывает их, считывает матрицы из файлов, перемножает их и записывает полученную матрицу (С) в новый файл. Затем он закрывает и снова открывает этот файл, содержащий ответ, и распечатывает его, чтобы я мог проверить, правильно ли прошла операция ввода-вывода.

Моя проблема в том, что матрица результатов читается не так, как ожидалось.

Я считаю себя новичком в C и операциях ввода/вывода файлов, и это код, который вызывает у меня проблемы. Я использую WinXP, Codeblocks и Mingw.

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

#define bufferA(i,k) (bufferA[i*cols+k])
#define bufferB(k,j) (bufferB[k*cols+j])
#define bufferC(i,j) (bufferC[i*cols+j])

void printMatrix(int *nMatrixToPrint, int nNumberOfElements, int nDimension) {
// This function prints out the element of an Array. This array represents a matrix in memory.

int nIndex;
printf("\n");

for (nIndex = 0; nIndex < nNumberOfElements; nIndex++) {
    if (nIndex % nDimension == 0)
        printf("\n");
    printf("%d,",nMatrixToPrint[nIndex]);
    }

return;
}

int main(int argc, char *argv[]) {
int nElements = 16, nDim = 4;
int A[4][4] = {{1,2,3,1},{2,2,1,2},{4,2,3,1},{5,1,1,3}};
int B[4][4] = {{3,2,1,4},{2,2,3,3},{4,1,3,2},{2,2,5,1}};

// Create files of A and B, delete old ones if present
FILE *fpA = fopen("A.dat", "w+");
FILE *fpB = fopen("B.dat", "w+");

// Write data to them
fwrite((int*)A, sizeof(*A), nElements, fpA);
fwrite((int*)B, sizeof(*B), nElements, fpB);

// and close them
fclose(fpA);
fclose(fpB);

// Reopen files
fpA = fopen("A.dat", "r");
fpB = fopen("B.dat", "r");

// Allocate memory
int *bufferA = (int*)malloc(nElements * sizeof(*bufferA));
int *bufferB = (int*)malloc(nElements * sizeof(*bufferB));
int *bufferC = (int*)calloc(nElements, sizeof(*bufferC));

// Read files
fread(bufferA, sizeof(int), nElements, fpA);
fread(bufferB, sizeof(int), nElements, fpB);

printf("\nA");
printMatrix(bufferA, nElements, nDim);
printf("\n\nB");
printMatrix(bufferB, nElements, nDim);

// Matrix multiplication
// Calculate and write to C
int i,j,k = 0; // Loop indices
int n = nDim,l = nDim, m = nDim, cols = nDim;

// multiply
for (i = 0; i < n; i++) {           // Columns
    for (j = 0; j < m; j++) {       // Rows
        //C(i,j) = 0;
        for (k = 0; k < l; k++) {
            bufferC(i,j) += bufferA(i,k) * bufferB(k,j);
        }
    }
}
printf("\n\nC_buffer");
printMatrix(bufferC, nElements, nDim);

// Create C and write to it
FILE* Cfile = fopen("C.dat", "w");
fwrite(bufferC, sizeof(*bufferC), nElements, Cfile);

// Close files
fclose(fpA);
fclose(fpB);
fclose(Cfile);

// reopen C for reading
Cfile = fopen("C.dat", "r");

// Obtain file size
fseek(Cfile , 0 , SEEK_END);
long lSize = ftell(Cfile);
rewind(Cfile);
printf("\nC file length is: %ld", lSize);

// read data into bufferA
fread(bufferA, sizeof(int), lSize, Cfile);
fclose(Cfile);

printf("\n\nC_file");
printMatrix(bufferA, nElements, nDim);

// Free allocated memory and remove dangling pointers
free(bufferA); bufferA = NULL;
free(bufferB); bufferB = NULL;
free(bufferC); bufferC = NULL;

exit(0);
}

Что дает мне следующий вывод:

A

1,2,3,1,
2,2,1,2,
4,2,3,1,
5,1,1,3,

B

3,2,1,4,
2,2,3,3,
4,1,3,2,
2,2,5,1,

C_buffer

21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,26,28,
Длина файла C: 64

C_файл

21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,1,3,

Как видите, последние два элемента в C_file неверны, вместо этого вывод показывает последние два элемента в A, когда я записываю содержимое файла в буферA. Переключение на bufferB поменяет местами последние два символа с последними элементами в B, что все еще ошибочно. Копирование файла в другой проект даст два последних целых числа, которые были в оперативной памяти по этому адресу malloc.

У меня такой вопрос: Почему fwrite не записывает в файл нужные данные. Почему он управляет первыми 14 элементами, но не двумя последними? И чем это отличается от моего предыдущего правильного использования fwrite и fread, когда я писал и извлекал элементы A и B?


person Steinin    schedule 23.04.2011    source источник
comment
Ваш призыв к fread не совсем правильный; вы попытаетесь прочитать 64 значения, а не 16, потому что файл имеет длину 64 байта. Вероятно, вы захотите переключить соответствующий параметр на lSize / sizeof(int). Это не должно вызывать проблемы — вы пробовали регистрировать результат, возвращаемый fread? Он должен сообщить вам количество прочитанных «элементов» (в данном случае целых, поскольку вы указали sizeof (int)).   -  person Tommy    schedule 24.04.2011
comment
Спасибо, Томми. Я исправил вызов fread и зарегистрировал его возвращаемый размер_T, который оказался равным 14, что странно, поскольку файл на диске имеет размер 64 байта, что составляет 16 32-битных целых чисел.   -  person Steinin    schedule 24.04.2011
comment
Извини, братан, твой код отлично работает на моем компьютере с Ubuntu.   -  person karlphillip    schedule 24.04.2011


Ответы (2)


Вы пишете двоичные данные, и поэтому вам нужно открыть файл в двоичном режиме, по умолчанию это текстовый режим. Это имеет значение для Windows, но не для * nix, что объясняет, почему это работает для других людей здесь.

для всех вызовов fopen включите буква «b» в аргументе режима, например. замените «w+» на «w+b», замените «r» на «rb» и так далее.

person nos    schedule 23.04.2011
comment
Это была действительно проблема. Спасибо. - person Steinin; 24.04.2011
comment
Я сталкивался с этим раньше, но теперь у меня такое же проблемное событие с опцией rb. Я сказал fwrite записать 239616 целых чисел, но он написал только 3072, иногда только 1024, иногда 2048, они меняются. В чем может быть проблема? - person Chan Kim; 14.11.2017
comment
О, я обнаружил, что когда указатель буфера неверен, это может произойти. Я должен был указать fwrite(&buff[0], sizeof(int), count, fp); но я дал fwrite(&buff, sizeof(int),count,fp); по ошибке. - person Chan Kim; 14.11.2017

Ваша программа отлично работает на моем Mac.

Результаты будут выглядеть лучше, если printMatrix() выведет последнюю новую строку. Возможно, незавершенная строка вызывает некоторую путаницу в вашей системе?

person DigitalRoss    schedule 23.04.2011