为什么从c中读取二进制文件会得到未定义的值?

时间:2018-12-12 02:47:38

标签: c arrays

我正在编写一个程序,该程序使用动态分配的数组存储库存(三个数字数组),并将这些数组存储在名为“ inventory.txt”的二进制文件中。我遇到的问题是,当我打印出数组时,我的数组中确实出现了奇怪的数字。程序错误地读取了二进制文件,数组的大小被读取到程序中,因为显示了正确数量的元素,并且数字在多次迭代中没有变化。如何正确读取数字,以便程序显示正确的数字?

有两个程序,第一个创建一个二进制文件“ inventory.txt”,并将三个变量的零件号,数量和价格连续放入动态分配的数组中,该数组随每个条目的增加而增加,并在用户输入0时结束数字(只需输入一个0)。第二个程序仅读取存储在二进制文件“ inventory.txt”中的数组和数组大小,并打印“ i”行数量以及其中存储的数字。这是两个程序。

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




//THIS IS FIRST PROGRAM THAT STORES THE ARRAY BASED ON USER INPUT
int main(){
 printf("This program stores an invetory: ");//declarations
 int i=0, holdr, k=0;
 int *pn, *q;
 float *p;


 q=malloc(sizeof(int));
 pn=malloc(sizeof(int));      //allocate space
 p=malloc(sizeof(float));





 FILE *fp;
 fp=fopen("inventory.txt","w+b");    //open file




 while(holdr!=0){
 pn=realloc(pn, (i+1) * sizeof(int));    //read data into the three arrays
 q=realloc(q, (i+1) * sizeof(int));
 p=realloc(p, (i+1) * sizeof(float));
 printf("Please enter item data (part number, quantity, price): ");
 scanf("%d,%d,%f",&pn[i],&q[i],&p[i]);
 holdr=pn[i];
 i++;
 k++;
 }




 fwrite(&i,sizeof(int),1,fp);               //write arrays to inventory.txt(binary)
 fwrite(&pn,sizeof(int),k,fp);
 fwrite(&q,sizeof(int),k,fp);
 fwrite(&p,sizeof(float),k,fp);
 printf("Thank you. Inventory stored in inventory.txt. \n"); 


 fp=fopen("inventory.txt","r+b");        //Check to see if file is correct by printing from the file inside the same program.


 if (fp == NULL){
 printf("nah");
 exit(EXIT_FAILURE);
 }

 for(i=0;i<k;i++){
 fread(&pn,sizeof(int),k,fp);     //THIS DISPLAYS THE ARRAYS CORRECTLY AS ENTERED
 printf("%d\t" , pn[i]);
 fread(&q,sizeof(int),k,fp);
 printf("%d\t", q[i]);
 fread(&p,sizeof(int),k,fp);
 printf("%f\n", p[i]);}

 fclose(fp);
 return 0;
}

然后...

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

//THE SECOND FILE THAT PRINTS OUT THE ARRAYS FROM THE FIRST PROGRAM
int main(){


FILE *fp = fopen("inventory.txt","r+b");  //declarations

if (fp == NULL){      //check file
printf("nah");
exit(EXIT_FAILURE);
}
int i;
fread(&i,sizeof(int),1,fp); //get size of arrays from "i" in the other program, THIS PART WORKS 


int l,k;
int *pn, *q;
float *p;


q  = (int *)malloc(i * sizeof(int));  // TODO - check malloc() OK
pn = (int *)malloc(i * sizeof(int));  // TODO - check malloc() OK
p  = (float *)malloc(i * sizeof(float));  // TODO - check malloc() OK


fread( q, sizeof( int ), i, fp );   //read arrays in file into program
fread( p, sizeof( float ), i, fp );
fread( pn, sizeof( int ), i, fp );


printf("Below are the items in your inventory.\nPart#\tQuantity\tPrice\n");   
for(l=0;l<i;l++){                   //THIS DISPLAYS WEIRD ASS NUMBERS

printf("%d\t" , pn[l]);

printf("%d\t", q[l]);

printf("%f\n", p[l]);}
rewind(fp);
fclose(fp);
return 0;}

2 个答案:

答案 0 :(得分:2)

您的程序存在多个问题。首先,要使程序完全运行,您需要将holdr定义为非零值。

int i=0, holdr=1, k=0;

调试文件写入/读取问题的第一步是检查程序写入的文件。在对输出文件进行十六进制转储时,我看到该文件仅包含垃圾值,因此您的写入程序本身已损坏。有了这些信息,如果我们看一下您的代码,您的程序之所以会写出垃圾值的原因是因为在fwrite

中的指针类型上使用了地址运算符
fwrite(&i,sizeof(int),1,fp);      //this is okay, i is an int, &i is int*
fwrite(&pn,sizeof(int),k,fp);     //this is not okay, pn is int*, &pn is int**

基本上,您是在将阵列的地址而不是阵列的内容写入文件。因此,在回读时,您将获得数组的地址-这似乎是垃圾。

除了解决程序中的许多其他问题外,从数组的fwrite中删除&,然后程序将写入正确的值,因此您的读取程序也可以读取正确的值。

fwrite(pn,sizeof(int),k,fp);     //this is the right usage, pn is int*

答案 1 :(得分:0)

您没有初始化int holdr。因此while(holdr!=0)是未定义的行为。无法确定该变量的含义,因此您的循环可能开始也可能不会开始。

使用realloc分配内存后,将立即出现对malloc的调用,但是没有测试来确定是否需要额外的空间。通常,人们会写类似if (not_enough_space) realloc(something)的文字。您的代码(假设它甚至超过了前面提到的未定义行为),将只为pn和q分配单个整数的空间,为p分配单个浮点的空间,因此首先不需要malloc。

您说您的结果不会改变...这是由于以下事实:不断地重新分配数组并将值存储到它们,而无需将结果写入文件。它只是无限循环,要求用户输入,直到pn[0]恰好变为0。

在第二个源文件中,int i必须在使用前初始化。

没有理由强制转换malloc的结果。指向void的指针基本上是无类型的内存地址。