user7823016
user7823016

Reputation: 167

How can I utilize struct arrays to output a given struct based on user-input

ISSUE: I'm trying to fill my beerData struct with data found in beer.dat, except I don't understand how structs work well enough to implement without crashing my code. I believe I need an array of structs.

The beer.dat file contents:

7 // total number of beers 
Coors //beer name
1234567 // beer id
72 // beer quantity
7.40 //beer price 
Miller
7777777
44
9.70
Bud
7654321
345
9.90
Wachusett
7799435
4
14.70
Corona
9999999
112
9.99
Zima
0000000
1
0.01
Mikes
0890398
12
10.99

CODE:

/*
    User interface, alloc, malloc 13 points
    Correct structure and array built 7 points
    Recursive sort
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct beerData {
    char *beer[7]; // number of brands

    char *beer_name; //names
    int beer_id[7]; //ID number given to beer
    int beer_quantity; //stock
    float beer_price; // pricing
} beer_data;


void printStr(char *line) {

    char *look = "";
    printf("What would you like to search for? \n");
    scanf("%s", look);

    //printf("Line: %s\n", line);


    exit(0);
}

void search() {
    //look through beer.dat for a specific beer by ID number.
    char str[32];

    FILE *fp = fopen("beer.dat", "r");

    if (fp == NULL) {
        printf("Error: can't open file to read\n");
    } else {
        while (!feof(fp)) {
            fscanf(fp, "%s ", str);
            //printf("%s\n",str);
            printStr(str);
        }

    }

    fclose(fp);
}


int main() {

    int user_choice;
    printf("Enter 1 to search for a beer, 2 to view the entire catalogue,"
           " and 3 to place an order, press 4 to exit.\n");


    while (user_choice != 4) {
        scanf("%d", &user_choice);
        switch (user_choice) {

            case 1:
                printf("Searching for a beer\n");
                user_choice = 0;
                search();
                break;
            case 2:
                printf("Viewing Inventory\n");
                //viewInv();
                break;
            case 3:

                printf("Placing an order...\n");
                //placeOrder();
                break;
            case 4:
                printf("Goodbye!\n");
                exit(0);
            default:
                printf("Incorrect entry, try again.\n");
                continue;
        }
    }


}

I'm trying create a function that searches through the file, and finds a specific beer based on an ID given, that ID is inside a set that should be its struct... so once the ID is input, the program searches for the beer, and prints out the name, ID, quantity, and price.

For full clarity, I'll post the assignment questions in case I'm not conveying my needs properly. The assignment is to:

  1. Searching for a beer should prompt the user for an ID number and the result should display its quantity and price, if it is in your inventory.
  2. A view of the entire inventory will display all the beers with their ID number, price and quantity in ascending order by price. This sorting should be done using either Recursive Bubble or Recursive Selection sort.
  3. When placing an order an invoice of the order should be printed to the screen.

Upvotes: 3

Views: 557

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31609

First you need to declare a meaningful structure. The structure contains relevant information for each item. Example:

typedef struct beer_data 
{
    char name[20]; //names
    int id; //ID number given to beer
    int quantity; //stock
    float price; // pricing
} beer_data;

Next, you need an array of this structure. Use malloc to allocate enough memory for total number of items. Example:

beer_data *beers = malloc(total * sizeof(beer_data));

Now you have beers[0], beers[1], beers[2]..., read each item in the file and put that in the structure.

To read the file, you can use fscanf or fgets.

The first line in your file is

7 // total number of beers 

You can read the number 7 using fscanf:

int maximum = 0;
fscanf(fp, "%d", &maximum);

This should work fine, but there are characters after that which you are not interested in. Use fgets to read to the end of the line and discard those characters.

Start a loop and read each line, add to the structure.

With this method, if you are adding a new item, then you have to increase the memory size. See add_item which uses realloc. This might be too advanced. Alternatively, you can save the new item to the file, call free(beers), and read the file again.

typedef struct beer_data 
{
    char name[20]; //names
    int id; //ID number given to beer
    int quantity; //stock
    float price; // pricing
} beer_data;

void search_by_name(beer_data *beers, int total)
{
    char buf[20];
    printf("Enter name to search: ");
    scanf("%19s", buf);
    //note, we put %19s because beers[count].name is only 20 bytes long

    for(int i = 0; i < total; i++)
    {
        if(strcmp(beers[i].name, buf) == 0)
        {
            printf("Found: %s, %d, %d, %.2f\n",
                beers[i].name, beers[i].id, beers[i].quantity, beers[i].price);
            return;
        }
    }
    printf("%s not found\n", buf);
}

void print_list(beer_data *beers, int total)
{
    for(int i = 0; i < total; i++)
    {
        printf("%s %d %d %.2f\n",
            beers[i].name, beers[i].id, beers[i].quantity, beers[i].price);
    }
}

void add_item(beer_data *beers, int *total)
{
    //note, total has to be passed as pointer 
    //because we are changing it

    //allocate more memory:
    beers = realloc(beers, sizeof(beer_data) * (*total + 1));

    printf("enter name: "); 
    scanf("%19s", beers[*total].name);

    printf("enter id:");
    scanf("%d", &beers[*total].id);

    printf("enter quantity:");
    scanf("%d", &beers[*total].quantity);

    printf("enter price:");
    scanf("%f", &beers[*total].price);

    //increase the total
    *total += 1;
}

int main() 
{
    FILE *fp = fopen("beer.dat", "r");
    if(!fp)
    {
        printf("Error: can't open file to read\n");
        return 0;
    }

    char buf[500];

    int maximum = 0;
    fscanf(fp, "%d", &maximum);

    //read the rest of the line and discard it 
    fgets(buf, sizeof(buf), fp);

    //allocate memory
    beer_data *beers = malloc(maximum * sizeof(beer_data));

    int total = 0;
    while(1)
    {
        fgets(buf, sizeof(buf), fp);
        sscanf(buf, "%19s", beers[total].name);

        if(fscanf(fp, "%d", &beers[total].id) != 1) break;
        fgets(buf, sizeof(buf), fp);

        if(fscanf(fp, "%d", &beers[total].quantity) != 1) break;
        fgets(buf, sizeof(buf), fp);

        if(fscanf(fp, "%f", &beers[total].price) != 1) break;
        fgets(buf, sizeof(buf), fp);

        total++;
        if(total == maximum)
            break;
    }

    fclose(fp);

    int stop = 0;
    while (!stop)
    {
        printf("\
    Enter 0 to exit\n\
    Enter 1 print list\n\
    Enter 2 for search\n\
    Enter 3 add new item\n");

        int choice;
        scanf("%d", &choice);
        switch(choice)
        {
        case 0: 
            stop = 1;
            break;

        case 1:
            print_list(beers, total);
            break;

        case 2:
            search_by_name(beers, total);
            break;

        case 3:
            add_item(beers, &total);
            break;
        }
        printf("\n");
    }

    //cleanup:
    free(beers);

    return 0;
}

Upvotes: 2

Related Questions