2016-06-28 15 views
0

次のコードは、バイナリファイルへのバイナリデータの書き込み/読み出しを行います。書き込みが成功した場合は、戻り値がfread戻り値として成功した場合でも成功します。しかし、最後の2つまたは3つの値は常に迷惑になるので、配列のサイズを小さくすることでこれを検証しました。バイナリファイルから構造体ポインタの配列にデータを読み込めません

書き込み直後にファイルを読み込んだ場合、値はすべて問題ありません。しかし、プログラムを書いた後で一度閉じてから最初のアクションでプログラムを再実行すると、最後のいくつかの値が迷惑メールとして出力されます。なぜそうなのか ?示されるようにコードを書く/読むこと

#include<stdio.h> 
#include<stdlib.h> 
#define MAX 7 

void write(FILE *); 
void read(FILE *); 

int flag=0; 

struct emp 
{ 
char name[20]; 
int id; 
float salary; 
}*e[MAX]; 

void write(FILE *f) 
{ 
int i=0,check=0; 

flag=1; 
for(i=0;i<MAX;i++) 
{ 
    e[i]=malloc(sizeof(struct emp)); 
    if(e[i]) 
    { 
     printf("\nEnter Name id salary\n"); 
     scanf("%s %d %f",e[i]->name,&e[i]->id,&e[i]->salary); 
     //printf("\n----------%s %d %f\n",e[i]->name,e[i]->id,e[i]->salary); 
     //fflush(stdin); 
    } 
    else 
    { 
     printf("\nError allocating Memory\n"); 
     exit(0); 
    } 
} 
check= fwrite(*e,sizeof(struct emp),MAX,f); 
if(check!=MAX) 
{ 
    printf("\nerror writing to file\n"); 
} 
else 
    { 
    printf("\nwritten successfully to file\n"); 
    } 
} 

void read(FILE *f) 
{ 
int i=0; 

if(flag==0) //reading file right after running program 
{ 
    for(i=0;i<MAX;i++) 
    { 
     e[i]=malloc(sizeof(struct emp)); 
     if(e[i]==NULL) 
     { 
      printf("\nError Allocating Memory for read\n"); 
      exit(0); 
     } 
    } 
} 

if(fread(*e,sizeof(struct emp),MAX,f)==MAX) 
{ 
    for(i=0;i<MAX;i++) 
    { 
     printf("\n%s %d %f\n",e[i]->name,e[i]->id,e[i]->salary); 
    } 
} 
else 
{ 
    printf("\nEither reading error or partial content read\n"); 
} 
} 

int main() 
{ 
FILE *fp=NULL; 
char a='a'; 

do 
{ 
    printf("\nEnter w to write, r to read and e to exit\n"); 
    //scanf("%c",&a); 
    a=getche(); 

    switch(a) 
    { 
     case 'w': 
       fp=fopen("binary_ptr.exe","wb"); 
       if(fp==NULL) 
       { 
        printf("\nError opening file to write\n"); 
        exit(0); 
       } 
       write(fp); 
       fclose(fp); 
       break; 
     case 'r': 
       fp=fopen("binary_ptr.exe","rb"); 
       if(fp==NULL) 
       { 
        printf("\nError opening file to read\n"); 
        exit(0); 
       } 
       read(fp); 
       fclose(fp); 
       break; 
     case 'e': 
       exit(0); 
       break; 
     default: 
       printf("\nInvalid input\n"); 
       break; 
    } 
} 
while(1); 

return 0; 
} 

答えて

2

は、すべての構造体が*e始まるメモリの連続領域に配置されている前提としています。これはそうではありません。

このコードでは、structという配列は定義されていませんが、後者へのポインタが含まれています。動的に割り当てられたstruct自体は、メモリ上に散在しています。

このコードでは、MAX>1の未定義の動作が、*e[0]の境界を超えて書き込み/読み出しによって呼び出されます。 1 structfread()/fwrite()MAX回の周りにこのループを解決するために

(例えば、明示的Valgrindメモリチェッカーを使用してコンパイルされたコードを実行し、この問題を指摘することにします。)あなたの問題に関係のない側の注意点として


read()write()がに悪い名前ですPOSIX C標準で既に使用されている関数を所有しています。読み取り機能で

0

、あなたが

if(fread(*e,sizeof(struct emp),MAX,f)==MAX) 

を持っているこれは、配列eにMAXの要素を読み込みます。ただし、は連続した配列ではありません。あなたは正確に述べたように、あなたがemp構造体へのポインタの配列ではなく、配列を持っている、あなたは非連続的にあなたのemp構造体にメモリを割り当てられましたので、あなたは(fread(*e, sizeof(struct emp), MAX, f)を行うことはできません

e[i]=malloc(sizeof(struct emp)); 
0

とは別にeを割り当てていますemp構造体のファイルへのempデータを書き込む際に

for (int i = 0; i < MAX; ++i){ 
    if (fread(e[i], sizeof(struct emp), 1, f) == sizeof(struct emp)){ 
     printf("\n%s %d %f\n", e[i]->name, e[i]->id, e[i]->salary); 
    } else { 
     ... 
    } 
} 

同様に、あなたは別々にすぎ

for (int i = 0; i < MAX; ++i){ 
    check = fwrite(e[i], sizeof(struct emp), 1, f); 
    if (check != sizeof(struct emp)){ 
     ... 
    } else { 
    ... 
    } 
} 
それを実行する必要があります。あなたは、別途各 empを読む必要があります
関連する問題