【问题标题】:Why am I getting undefined values from reading a binary file in c?为什么我从 c 中读取二进制文件得到未定义的值?
【发布时间】:2019-05-13 02:31:43
【问题描述】:

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

有两个程序,第一个创建一个二进制文件“inventory.txt”并连续将三个变量part number、数量和价格放入一个动态分配的数组中,这个数组随着每个条目而增加,并在用户输入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;}

【问题讨论】:

  • 应该fread(&amp;pn,sizeof(int),k,fp);fread(&amp;pn,sizeof(int),1,fp); 吗?其他问题也存在。
  • 检查您在阅读程序中的阅读顺序。如果你写成pn, q, p,你也应该按这个顺序阅读。
  • fwrite(&amp;pn,sizeof(int),k,fp) 不应包含与号 (&amp;)。对应的fread() 调用也是如此。其他动态分配的内存也是如此。保存指向文件的指针(与指针指向的不同)然后读入通常会产生未定义的行为。

标签: c arrays


【解决方案1】:

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

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

调试文件写入/读取问题的第一步是检查程序写入的文件。在对输出文件进行 hexdump 时,我看到该文件仅包含垃圾值,因此您的写入程序本身已损坏。有了这些信息,如果我们查看您的代码,您的程序写出垃圾值的原因是因为在 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 中删除 &amp;,然后您的程序将写入正确的值,因此您的读取程序也可以读取正确的值。

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

【讨论】:

    【解决方案2】:

    您没有初始化int holdr。所以while(holdr!=0) 是未定义的行为。不知道该变量包含什么,因此您的循环可能会开始也可能不会开始。

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

    您说您的结果不会改变...这是因为您的数组不断重新分配并且值被存储到其中而无需您将结果写入文件。它只是无限循环,要求用户输入,直到 pn[0] 恰好变为 0。

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

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

    【讨论】:

      猜你喜欢
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-07
      相关资源
      最近更新 更多