2014-03-24 113 views
1

林在C. 初學者閱讀的二進制文件,我想寫入和讀取二進制文件,我達到了這個至今:分段故障而用C

我可以我的結構以二進制文件,並且可以閱讀。

問題一:我只能讀取整數,不知何故字符串被打印爲垃圾或隨機字符。

問題二:如果我跑我的計劃,我的一些條目添加到我的二進制文件,然後我打印所有它工作正常(除問題一)項,但在我結束我的程序,並再次運行我嘗試讀取文件時出現分段錯誤。

請幫助我,我只是不能前進。

/* Our structure */ 
struct rec 
{ 
    int max,cost; 
    char *name; 
}; 


struct rec addNewEntry() 
{ 

    //init 
    char name[256]; 
    int max; 
    int cost; 

    //input 
    printf("Type name: \n"); 
    scanf("%s" , &name) ; 

    printf("Type guests limit: \n"); 
    scanf("%d", &max); 

    printf("Type price: \n"); 
    scanf("%d", &cost); 

    //create record 
    struct rec record; 

    record.name = name; 
    record.max = max; 
    record.cost = cost; 

    return record; 

} 

int main() 
{ 

    FILE *ptr_myfile; 


    //////////////////////////MENU//////////////////////////////// 

    int option=-1; 


    while(option!=3) 
    { 

     printf("\n=== MENU === \n"); 
     printf("\n1. Print all entries"); 
     printf("\n2. Add new entry"); 
     printf("\n3. Exit"); 
     printf("\n"); 

     printf("\nType menu option:"); 

     scanf("%d", &option); 


     if(option == 1) 
     { 
      printf("\n...Printing all entries\n"); 



      int f=open("stadionok.db",O_RDONLY); 
      if (f<0){ perror("Error at opening the file\n");exit(1);} 

      struct rec my_record; 

      while (read(f,&my_record,sizeof(my_record))){ //use write for writing 
       printf("name: %s \n",my_record.name); 
       printf("max: %d \n",my_record.max); 
       printf("cost: %d \n",my_record.cost); 
      } 


      close(f); 


     } 
     else if(option ==2) 
     { 

      printf("\n...Type a new entry\n"); 


      //OPEN AND CHECK 
      ptr_myfile=fopen("stadionok.db","a"); 
      if (!ptr_myfile) 
      { 
       printf("Unable to open file!"); 
       return 1; 
      } 

      //TYPE A NEW ENTRY 
      struct rec new_stad = addNewEntry(); 

      //WRITE TO FILE 
      fwrite(&new_stad, sizeof(struct rec), 1, ptr_myfile); 


      //CLOSE 
      fclose(ptr_myfile); 

      printf("Done.\n"); 
     } 


    } 




    return 0; 
} 

編輯:

我修改的只是如你所說,現在我得到: 錯誤:不兼容的類型分配

在:

char name[256]; 


//input 
printf("Type name: \n"); 
scanf("%s" , &name) ; 


struct rec record; 

record.name = name; //HERE 
+1

name已經是地址,因此不需要在&前面加上前綴。你不能像這樣分配一個數組到另一個數組。使用memcpy或strncpy來複制數組的內容。 –

+0

謝謝你的工作很好。 –

回答

2

原因你得到的垃圾字符串是你正在寫一個char 指針進入文件。 做你想做的事的簡單方法是在你的結構中使用一個固定長度的char數組。像這樣:

struct rec 
{ 
    int max,cost; 
    char name[1024]; 
}; 

這也是墜機的原因。當您讀取數據並嘗試打印字符串時,printf()可能會嘗試從無效的內存塊中讀取,因爲內存地址已更改。

如果您想將動態大小的字符串寫入文件,它會變得更復雜一些。
然後,你不應該寫結構本身,但它的值和字符串的大小。
僞代碼示例:

write(max); 
write(cost); 
write(strlen(name)); // strlen + 1 if you want to include \0 
write(name); 

max = readInt(); 
cost = readInt(); 
nameLen = readInt(); 
allocatememory(nameLen); 
name = read_n_bytes(namelen); 


您的編輯: 如果rec.name仍然是一個指針(字符*),你必須指定一個指向它,而不是一個數組。

rec.name = &name; 

如果您rec.name是現在有一個固定大小的數組:

strncpy(rec.name, name, sizeof(rec.name)); // copy the string to rec.name 
rec.name[strlen(name)] = '\0'; // add a binary 0 to the end of the string 

注意:如果你正在閱讀超過1層結構(在一個循環中),你不應該使用char name[256];,因爲每次rec.name都會指向每次讀取新值時被覆蓋的名稱。對於每個條目使用以下構造:

char* name; //define name as a pointer 
name = malloc(256); // allocate a new memory block and assign a pointer to it to name 
scanf("%s" , name); // No & needed because name is already a pointer 
rec.name = name; // No & needed because name is already a pointer 
+0

請參閱我的編輯 –

+0

請參閱我的編輯。我也糾正了我的錯誤。 printf因爲想要訪問一個無效的內存地址而崩潰 –