0

My class, my teacher and I all couldn't figure out what's wrong with the code. It's a canteen ordering system, so as a student you order something and it logs it into a system and the canteen workers can make food accordingly. The specific problem is that I'm trying to make a tally but it only prints the first food item that was ordered. The relevant code is below and images are attached.

Menu of available items, Orders Placed, Result of order tally //note the student's order is an ID of the food item

struct food
{

    int   foodID;

    char  foodName[namesize];//namesize is 30

    char  foodItems[size];//specials for the day//size is 3

    int   itemTally;//total of food that needs to be prepared - REPLACED

    float totalEarnt;//total amount earnt for selling the food

    float totalSpen;//cost of food to the employer

    float totalProfits;//total profts made

    float itemCost;//cost of the food item

};

struct student
{

    char  firstname[namesize];

    char  lastname[namesize];

    int   ID;//students ID

    float form;//student's form room

    int   order;//ID of the food they ordered

    int   quantity;//how much of the food item

    float paid;//how much they paid

    int   delivery;//This is a yes or no

    char  location[aSize];//where it will be delivered to; aSize is 20

};

void orderTally()//Tallies up all the orders based on their ID; Student 1 orders 3 fish, student 2 orders 4 fish, outputs 7 fish
{

    FILE*fp;
    FILE*fp1;

    struct food foodie={0,"","",0,0.0,0.0,0.0,0.0};
    struct student orderie={"","",0,0.0,0,0,0.0,0,""};
    int i;//This is the food ID.

    if((fp1 = fopen("student", "rb+"))==NULL)//order file
    {
        printf("Cannot open order file \n");
        exit(1);
    }
    if ((fp = fopen("food", "rb+"))==NULL)//menu file
    {
        printf("Cannot open food file \n");//UPDATE: update other statements
        exit(1);
    }
    int sum=0;

    for(i=1;i<=100;i++)
    {
        fread(&orderie,sizeof(struct student),1,fp1);

        while(!feof(fp1))
        {
            if(orderie.order==i)//If the order ID is equal to one of the 100 food IDs...
            {   
                sum=sum+orderie.quantity;
            }
            fread(&orderie,sizeof(struct student),1,fp1);
        }
        if(sum!=0)
        {
            fseek(fp,(i-1)*sizeof(struct food),SEEK_SET);
            fread(&foodie,sizeof(struct food),1,fp);

            printf("------------------------------------------------------------\n");
            printf("\t\t\tORDERS\n");
            printf("------------------------------------------------------------\n\n");
            printf("%s",foodie.foodName);
            printf(" - %d\n\n",sum);
            sum=0;
        }
    }
    fclose(fp1);
    fclose(fp);
}
Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
Kusuo
  • 13
  • 2
  • Read this: [**Why is “while ( !feof (file) )” always wrong?**](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) Your instructor missing that is disappointing. – Andrew Henle Mar 23 '20 at 19:11
  • STRONG SUGGESTIONS: 1) Save and check the return status of *EACH* I/O operation (fread(), fseek(), etc). 2) Consider changing `while(!feof(...))` to `while ((iret = fread(...))` (or equivalent). And, MOST IMPORTANT: 3) Step through the debugger. Please post back what you find, and/or update your post with any specific questions you encounter along the way. – FoggyDay Mar 23 '20 at 19:23
  • Even better, quit cramming too much code into your `if` statements. You can't single-step through `if ((fp = fopen("food", "rb+"))==NULL)` like you can `fp = fopen("food", "rb+");` followed by `if (fp == NULL)` **on a separate line**. That also makes your code a **LOT** easier to understand. You gain nothing by cramming the assignment into the `if`-statement - other than too much going on in each line for a beginner in C to understand. – Andrew Henle Mar 23 '20 at 19:29
  • You are doing `for (i=1;i<=100;i++)` and the first part of that loop is doing `fread` on the _entire_ contents of `fp1` [in the `while` loop]. So, when `i` is 2, the `fread` will get an immediate EOF. Do you need an `fseek` for `fp1` [to rewind it] on each iteration of the `for` loop? If not, the `while` for `fp1` would be better placed _above_ the `for` loop. As it is, it seems wasteful to reread the file 100 times. – Craig Estey Mar 23 '20 at 19:35
  • 1
    @AndrewHenle - technically the use of `while(!feof(fp1))` is okay here because it is called *After* the attempted read and *Before* the content of `orderie` are accessed -- looks wonky, but technically fine. – David C. Rankin Mar 24 '20 at 02:06

1 Answers1

0

This is prefaced by my top comment:

You are doing for (i=1;i<=100;i++) and the first part of that loop is doing fread on the entire contents of fp1 [in the while loop]. So, when i is 2, the fread will get an immediate EOF. Do you need an fseek for fp1 [to rewind it] on each iteration of the for loop? If not, the while for fp1 would be better placed above the for loop. As it is, it seems wasteful to reread the file 100 times.

I've restructured and simplified things a bit. It's a lot easier to read the student file once and record all sums in an array.

struct food {
    int foodID;
    char foodName[namesize];            // namesize is 30
    char foodItems[size];               // specials for the day//size is 3
    int itemTally;                      // total of food that needs to be prepared - REPLACED
    float totalEarnt;                   // total amount earnt for selling the food
    float totalSpen;                    // cost of food to the employer
    float totalProfits;                 // total profts made
    float itemCost;                     // cost of the food item
};

struct student {
    char firstname[namesize];
    char lastname[namesize];
    int ID;                             // students ID
    float form;                         // student's form room
    int order;                          // ID of the food they ordered
    int quantity;                       // how much of the food item
    float paid;                         // how much they paid
    int delivery;                       // This is a yes or no
    char location[aSize];               // where it will be delivered to; aSize is 20
};

// Tallies up all the orders based on their ID; Student 1 orders 3 fish,
// student 2 orders 4 fish, outputs 7 fish
void
orderTally()
{
    FILE *fp;
    FILE *fp1;

    struct food foodie;
    struct student orderie;
    int i;                              // This is the food ID.

    // order file
    if ((fp1 = fopen("student", "rb+")) == NULL)
    {
        printf("Cannot open order file \n");
        exit(1);
    }

    int sums[101] = { 0 };

    // read _entire_ student file in one pass
    while (1) {
        if (fread(&orderie,sizeof(struct student),1,fp1) != 1)
            break;
        sums[orderie.order] += orderie.quantity;
    }

    fclose(fp1);

    // menu file
    if ((fp = fopen("food", "rb+")) == NULL)
    {
        printf("Cannot open food file \n"); // UPDATE: update other statements
        exit(1);
    }

    for (i = 1; i <= 100; i++) {
        int sum = sums[i];
        if (sum == 0)
            continue;

        fseek(fp, (i - 1) * sizeof(struct food), SEEK_SET);
        fread(&foodie, sizeof(struct food), 1, fp);

        printf("------------------------------------------------------------\n");
        printf("\t\t\tORDERS\n");
        printf("------------------------------------------------------------\n\n");
        printf("%s", foodie.foodName);
        printf(" - %d\n\n", sum);
    }

    fclose(fp);
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48