2011-04-23 39 views
1

我目前正在做一个简单的文件检查的小测试程序。该程序将两个小矩阵(A和B)写入文件,关闭并重新打开它们,从文件中读入矩阵,将它们相乘并将结果矩阵(C)写入新文件。然后它关闭并重新打开包含答案的文件并将其打印出来以检查IO操作是否正确进行。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); 
} 

这给了我下面的输出:

一个

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

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_FILE

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

正如你可以看到,最后两个元素在C_file中是错误的,而输出显示A中的最后两个元素,因为我正在将文件内容写入bufferA。切换到bufferB将交换最后两个字符与B中的最后一个仍然错误的元素。将文件复制到另一个项目中将产生最后两个整数,因为无论在该malloc地址处的内存中。

我的问题如下:为什么不写入适当的数据到文件中。它为什么要管理前14个元素,而不是后两个?当我写和检索A和B的元素时,这与我之前正确使用fwrite和fread的方式有何不同?

+0

您对fread的电话不太正确;您将尝试读取64个值而不是16个值,因为该文件的长度为64个字节。您可能想要将相关参数切换到lSize/sizeof(int)。这应该不会导致问题,但 - 您是否尝试过记录fread的返回结果?它应该告诉你'项目'的数量(在这种情况下,整数,因为你指定了sizeof(int))读取。 – Tommy 2011-04-23 20:12:12

+0

谢谢汤米。我修复了fread调用并记录了它的返回size_T,结果是14,这很奇怪,因为磁盘上的文件是64字节,它是16个32位整数。 – Steinin 2011-04-23 20:30:37

+0

对不起兄弟,你的代码在我的Ubuntu盒子上工作正常。 – karlphillip 2011-04-23 20:56:47

回答

4

您正在编写二进制数据,因此您必须以二进制模式打开文件,默认为文本模式。这在窗口上有所不同,但不在* nix上,这就解释了为什么它适用于这里的其他人。

对于您所有的fopen调用,在模式参数中包括字母'b',例如,用“w + b”替换“w +”,用“rb”替换“r”等等。

+0

这确实是个问题。谢谢。 – Steinin 2011-04-23 21:31:24

+0

我以前经历过这种情况,但现在我遇到了与“rb”选项相同的问题事件。我告诉fwrite写239616整数,但它只写了3072,有时只写1024,有时写2048,它改变了。问题是什么? – 2017-11-14 04:46:20

+0

哦,我发现当缓冲区指针错误时,可能会发生这种情况。我应该给fwrite(&buff [0],sizeof(int),count,fp);但我给了fwrite(&buff,sizeof(int),count,fp);因为失误。 – 2017-11-14 04:54:20

0

你的程序在我的Mac上运行得很好。

如果printMatrix()输出最终换行符,结果会更好。也许未终结的行会在你的系统上造成某种混乱?