从二进制文件读取结构(C)

时间:2015-12-19 18:44:41

标签: c struct binary

我需要你帮助从二进制文件中读取struct, " Grocery read_from_file()..."功能无法使其正常工作!

这是我的代码:

#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 ;
}

1 个答案:

答案 0 :(得分:0)

在大多数情况下,&#34; Grocery read_from_file()&#34;函数有效,但它只返回第一个项而不是正确读取的列表。

  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时不泄漏旧free(list)的内存,请在list = (Grocery*)calloc(*index, sizeof(Grocery));之前插入 list = realloc(list, *index * sizeof(Grocery)); 或将其更改为

    $(document).ready(function(){
        $("button").click(function(){
            $.get("demo_test.asp", function(data, status){
                alert("Data: " + data + "\nStatus: " + status);
            });
        });
    });