2015-12-19 62 views
0

我需要你的幫助,從二進制文件中讀取結構, 「Grocery read_from_file()...」函數無法使這個工作!從二進制文件讀取結構(C)

這裏是我的代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <windows.h> 
#include <ctype.h> 
#include <conio.h> 

struct grocerylist 
{ 
    int iD; 
    char grocery[30]; 
    float amount; 
    char unit[10]; 
}; 



Grocery set_size_of(Grocery* list, int index); 

Grocery input(int index); 

void print_grocerylist(Grocery* list, int* index); 

void write_to_file(FILE* file_pointer, Grocery* list, int index); 

Grocery read_from_file(FILE* file_pointer, Grocery* list, int* index); 

void change_item(Grocery* list, int index); 

void remove_item(Grocery* list, int* index); 

int main() 
{ 

    Grocery* list = (Grocery*)malloc(sizeof(Grocery)*1);   //Grocery-array allocated memory for 1 struct 
    int index = 0, choice = 0; 
    FILE* file_pointer = NULL; 

    printf("Hey there user!\n"); 

    while(choice != 7){ 
     system("cls"); 
     printf("Menu\n"); 
     printf("1 - Add an item to the list.\n2 - Print the contents of your current list.\n3 - Print the contents to file.\n4 - Read from file.\n5 - Change an item on the list.\n6 - Remove item from the list.\n7 - close the program.\nChoose: "); 
     scanf("%d", &choice); 
     printf("\n"); 

     switch(choice){ 
      case 1: 
       list[index] = input(index); 
       index++; 
       *list = set_size_of(list, index);       //Reallocating memory for the array of grocery-structs. 
       fflush(stdin); 
       break;            //Add item 
      case 2: 
       print_grocerylist(list, &index);     //Print list 
       fflush(stdin); 
       break; 
      case 3: 
       write_to_file(file_pointer, list, index);   //print to file 
       fflush(stdin); 
       break; 
      case 4: 
       *list = read_from_file(file_pointer, list, &index);   //read from file 
       fflush(stdin); 
       break; 
      case 5: 
       change_item(list, index);       //change item 
       fflush(stdin); 
       break; 
      case 6: 
       remove_item(list, &index);       //remove item 
       index--; 
       fflush(stdin); 
       break; 
      case 7: 
       free(list); 
       exit(EXIT_SUCCESS);         //End program 
       break; 
      default: 
       printf("Wrong input, please try again!"); 
       fflush(stdin); 
       getch(); 
       break; 
     } 
    } 
    return 0; 
} 

Grocery set_size_of(Grocery* list, int index){    //reallocates memory. 

    list = realloc(list, (index+1)*sizeof(Grocery)); 

    return *list; 
} 

Grocery input(index){ 

    Grocery tmp; 
    int x = 0; 

    tmp.iD = index +1; 

    fflush(stdin); 
    printf("Grocery: "); 
    gets(tmp.grocery); 

    while(x == 0){ 
     fflush(stdin); 
     printf("Amount: "); 
     x = scanf("%f", &tmp.amount); 
     if(x == 0){ 
      puts("Error, please try again!"); 
     } 
    } 

    fflush(stdin); 
    x = 0; 
    while(x == 0){ 
     printf("Unit: "); 
     gets(tmp.unit); 
      if(isalpha(*tmp.unit)){ 
       x = 1; 
      }else{ 
       x = 0; 
       puts("Error: please try again!\n"); 
      } 
    } 
    printf("\n"); 

    return tmp; 
} 

void print_grocerylist(Grocery* list, int* index){ 

    int i; 

    system("cls"); 
    printf("The grocery list contains:\n"); 
    printf("Item   Amount  Unit"); 
     for(i=0;i<*index;i++) 
     { 
      printf("\n%d: %-10s %5.1f %6s", list[i].iD, list[i].grocery, list[i].amount, list[i].unit); 
     } 
     printf("\n"); 
    getch(); 
    printf("Press any key to continue.\n"); 
} 

void write_to_file(FILE* file_pointer, Grocery* list, int index){    //works just fine afaik.. Prints the index at the start, fills it up with all the rest. 

    char filename[30]; 
    memset(filename, '\0', sizeof(filename)); 

    printf("What is the name of the file you wish to write to?: "); 
    scanf("%s", filename); 
    strcat(filename, ".txt"); 

    file_pointer = fopen(filename, "wb"); 
    if(file_pointer == NULL){ 
     printf("Error!"); 
     return; 
    }else{ 
     fflush(stdin); 
     printf("File opened successfully!\n"); 
     fwrite(&index, sizeof(int), 1, file_pointer); 
     fwrite(list, sizeof(Grocery), index, file_pointer); 
     printf("File written."); 
     getch(); 
    } 

    fclose(file_pointer); 

    return; 
} 

Grocery read_from_file(FILE* file_pointer, Grocery* list, int* index){  //Can't get this to work... 

    char filename[30]; 
    memset(filename, '\0', sizeof(filename)); 

    printf("What is the name of the file you wish to read from?: "); 
    scanf("%s", filename); 
    strcat(filename, ".txt"); 

    file_pointer = fopen(filename, "rb"); 
    if(file_pointer == NULL){ 
     printf("Error!"); 
     return *list; 
    }else{ 
     fflush(stdin); 
     free(list); 
     printf("File opened successfully!\n"); 
     fread(index, sizeof(int), 1, file_pointer); 
     printf("Index %d read.\n", *index); 
     list = (Grocery*)calloc(*index, sizeof(Grocery)); 
     fread(list, sizeof(Grocery), (*index), file_pointer); 
     printf("File read."); 
     getch(); 
     fflush(stdin); 
    } 

    fclose(file_pointer); 

    return *list; 
} 

void change_item(Grocery* list, int index){  //Basically it's a more complex version of "Grocery input()" were we look to the ID/index and alter the information. 

    int x = 0, id, item, choice; 

    print_grocerylist(list, &index); 

    printf("Which item would you like to change?\nID number: "); 
    scanf("%d", &id); 
    printf("\nWhat do you want to change?\n1 - Grocery.\n2 - Amount.\n3 - Unit.\nChoose: "); 
    scanf("%d", &choice); 

    switch(choice){ 
     case 1: 
      fflush(stdin); 
      printf("Grocery: "); 
      for(item = 0; item <= index; item++){ 
       if(list[item].iD == id){ 
        gets(list[item].grocery); 
       } 
      } 
      break; 
     case 2: 
      while(x == 0){ 
       fflush(stdin); 
       printf("Amount: "); 
       for(item = 0; item <= index; item++){ 
        if(list[item].iD == id){ 
         x = scanf("%f", &list[item].amount); 
        } 
       } 
       if(x == 0){ 
        puts("Error, please try again!"); 
       } 
      } 
      break; 
     case 3: 
      fflush(stdin); 
      x = 0; 
      printf("Unit: "); 
      for(item = 0; item <= index; item++){ 
       if(list[item].iD == id){ 
        gets(list[item].unit); 
         if(isalpha(*list[item-1].unit)){ 
          x = 1; 
         }else{ 
          x = 0; 
          puts("Error: please try again!\n"); 
         } 
       } 
      } 
      break; 
     default: 
      printf("\nError! Please try again.\n"); 
      break; 
    } 

    return; 
} 

void remove_item(Grocery* list, int* index){ //Takes the last struct and copies it to the slot which will be "removed" and then reallocates the memory for the array -1, keeping the old ID, to make things simple. 

    int item; 

    printf("Which item would you like to remove?\nID number: "); 
    scanf("%d", &item); 

    strcpy(list[item].grocery, list[*index].grocery); 
    list[item].amount = list[*index].amount; 
    strcpy(list[item].unit, list[*index].unit); 

    list = realloc(list, (*index-1)*sizeof(Grocery)); 

    return ; 
} 
+0

兩個詞:字節對齊(我的所有其他'話'將集中在你的問題結構有多嚴重......)。歡迎您,請進行堆棧溢出遊覽' – Grantly

+0

「無法讓這個工作。」經典的差勁問題。 *什麼*不起作用?編譯,崩潰的可執行文件或錯誤的輸出?請詳細說明您遇到的具體問題。 –

+0

對不起,我的英語不好。 –

回答

0

在大多數情況下,在「雜貨店read_from_file()」函數的工作原理,但它返回,而不是它正確讀取只列出的第一項。

  1. 要返回並分配(指針)整個列表,改變呼叫

       *list = read_from_file(file_pointer, list, &index); 
    

       list = read_from_file(file_pointer, list, &index); 
    

    和定義

    Grocery read_from_file(FILE* file_pointer, Grocery* list, int* index){  
    … 
         return *list; 
    … 
        return *list; 
    } 
    

    Grocery *read_from_file(FILE *file_pointer, Grocery *list, int *index) 
    {  
    … 
         return list; 
    … 
        return list; 
    } 
    
  2. 爲了不漏的老list的內存時,它讀取一個從文件,list = (Grocery*)calloc(*index, sizeof(Grocery));前插入free(list)或更改到

     list = realloc(list, *index * sizeof(Grocery));