0

Im a student and I got this problem while trying to make a dynamic allocation for arrays and arrays of structs.
With the same input, it always give me different outputs, and sometime it shows errors.

I have been fixing this bug for 3 days but still cant.
Im sorry for that my code is so long. I really dont know how should I shorten it for you.
Thank you very much.

main.cpp:

#include <iostream>
#include <iomanip>
#include <string>
#include "MyFunctions.h"

using namespace std;

struct Dish {
    string name;
    int price;
};

struct Serving {
    int n;
    char name;
    Dish *dish;
};

int main() {
    Menu();
    Infomation();
  
    int n = 0;
    Serving *serving = new Serving[n];

    char type;
    cout << endl << "Please input a serving type (A/B/C/D) "; cin >> type;
    while (type != 'A' && type != 'B' && type != 'C' && type != 'D') {
        cout << "Wrong input, please input again! (A/B/C/D) "; cin >> type;
    }
    Choosing(serving, n, type);

    DeleteDishArray(serving, n);
    DeleteServingArray(serving);

    return 0;
}

MyFunctions.cpp:

#include <iostream>
#include <iomanip>
#include <string>
#include "MyFunctions.h"

using namespace std;

struct Dish {
    string name;
    int price;
};

struct Serving {
    int n;
    char name;
    Dish *dish;
};


Dish *CreateDishArray(int n) {
    Dish *dish = new Dish[n - 1];
    if (dish == NULL) {
        return NULL;
    }
    return dish;
}

void DeleteDishArray(Serving *& serving, int n) {
    for (int i = 0; i < n; i++) {
        if (serving[i].dish != NULL) {
            delete[] serving[i].dish;
            serving[i].dish = NULL;
        }
        else {
            serving[i].dish = NULL;
        }
    }
}

void DeleteServingArray(Serving *&serving) {
    if (serving != NULL) {
        delete[] serving;
        serving = NULL;
    }
    else {
        serving = NULL;
    }
}

void Increase(Serving*& serving, int& n) {
    n++;
    Serving* newserving = new Serving[n];
    for (int i = 0; i < n - 1; i++) {
        newserving[i] = serving[i];
    }
    DeleteServingArray(serving);
    serving = newserving;
}

void Choosing(Serving *&serving, int& n, char type) {
    char answer;

    switch (type) {
        case 'A':
            cout << "Imported serving type A! Do you want to order one more? (Y/N) "; cin >> answer;
            while (answer != 'Y' && answer != 'N') {
                cout << "Wrong input, please input again! (Y/N) "; cin >> answer;
            }

            Increase(serving, n);

            serving[n - 1].n = 3; serving[n - 1].dish = CreateDishArray(serving[n - 1].n);
            serving[n - 1].name = 'A';
            serving[n - 1].dish[0].name = "Burger"; serving[n - 1].dish[0].price = 130;
            serving[n - 1].dish[1].name = "Drink"; serving[n - 1].dish[1].price = 130;
            serving[n - 1].dish[2].name = "Potato"; serving[n - 1].dish[2].price = 120;

            if (answer == 'Y') {
                cout << endl << "Please input a serving type (A/B/C/D) "; cin >> type;
                while (type != 'A' && type != 'B' && type != 'C' && type != 'D') {
                    cout << "Wrong input, please input again! (A/B/C/D) "; cin >> type;
                }

                Choosing(serving, n, type);
            }

            else if (answer == 'N') {
                Choosing(serving, n, NULL);
            }

            break;

        case 'B':
            cout << "Imported serving type B! Do you want to order one more? (Y/N) "; cin >> answer;
            while (answer != 'Y' && answer != 'N') {
                cout << "Wrong input, please input again! (Y/N) "; cin >> answer;
            }

            Increase(serving, n);

            serving[n - 1].n = 3; serving[n - 1].dish = CreateDishArray(serving[n - 1].n);
            serving[n - 1].name = 'B';
            serving[n - 1].dish[0].name = "Cheese burger"; serving[n - 1].dish[0].price = 150;
            serving[n - 1].dish[1].name = "Drink"; serving[n - 1].dish[1].price = 130;
            serving[n - 1].dish[2].name = "Potato"; serving[n - 1].dish[2].price = 120;

            if (answer == 'Y') {
                cout << endl << "Please input a serving type (A/B/C/D) "; cin >> type;
                while (type != 'A' && type != 'B' && type != 'C' && type != 'D') {
                    cout << "Wrong input, please input again! (A/B/C/D) "; cin >> type;
                }

                Choosing(serving, n, type);
            }

            else if (answer == 'N') {
                Choosing(serving, n, NULL);
            }

            break;

        case 'C':
            cout << "Imported serving type C! Do you want to order one more? (Y/N) "; cin >> answer;
            while (answer != 'Y' && answer != 'N') {
                cout << "Wrong input, please input again! (Y/N) "; cin >> answer;
            }

            Increase(serving, n);

            serving[n - 1].n = 3; serving[n - 1].dish = CreateDishArray(serving[n - 1].n);
            serving[n - 1].name = 'C';
            serving[n - 1].dish[0].name = "Chicken burger"; serving[n - 1].dish[0].price = 200;
            serving[n - 1].dish[1].name = "Drink"; serving[n - 1].dish[1].price = 130;
            serving[n - 1].dish[2].name = "Potato"; serving[n - 1].dish[2].price = 120;

            if (answer == 'Y') {
                cout << endl << "Please input a serving type (A/B/C/D) "; cin >> type;
                while (type != 'A' && type != 'B' && type != 'C' && type != 'D') {
                    cout << "Wrong input, please input again! (A/B/C/D) "; cin >> type;
                }

                Choosing(serving, n, type);
            }

            else if (answer == 'N') {
                Choosing(serving, n, NULL);
            }

            break;

        case 'D':
            cout << "Imported serving type D! Do you want to order one more? (Y/N) "; cin >> answer;
            while (answer != 'Y' && answer != 'N') {
                cout << "Wrong input, please input again! (Y/N) "; cin >> answer;
            }

            Increase(serving, n);

            serving[n - 1].n = 4; serving[n - 1].dish = CreateDishArray(serving[n - 1].n);
            serving[n - 1].name = 'D';
            serving[n - 1].dish[0].name = "Chicken burger"; serving[n - 1].dish[0].price = 200;
            serving[n - 1].dish[1].name = "Drink"; serving[n - 1].dish[1].price = 130;
            serving[n - 1].dish[2].name = "Potato"; serving[n - 1].dish[2].price = 120;
            serving[n - 1].dish[3].name = "Ice cream"; serving[n - 1].dish[3].price = 160;


            if (answer == 'Y') {
                cout << endl << "Please input a serving type (A/B/C/D) "; cin >> type;
                while (type != 'A' && type != 'B' && type != 'C' && type != 'D') {
                    cout << "Wrong input, please input again! (A/B/C/D) "; cin >> type;
                }

                Choosing(serving, n, type);
            }

            else if (answer == 'N') {
                Choosing(serving, n, NULL);
            }

            break;

        default:
            Bill(serving, n);
        }
}

void Bill(Serving *&serving, int n) {
    int total = 0;
    cout << endl << "======= YOUR BILL =======" << endl << endl;
    for (int i = 0; i < n; i++) {
        cout << "---------TYPE " << serving[i].name << "---------" << endl;
        for (int j = 0; j < serving[i].n; j++) {
            cout << setw(15) << right << serving[i].dish[j].name << ": " << serving[i].dish[j].price << " JPY" << endl;
        }
    }
    cout << "------------------------" << endl;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < serving[i].n; j++) {
            total += serving[i].dish[j].price;
        }
    }
    cout << setw(17) << right << "TOTAL PRICE: " << total << " JPY" << endl;
    cout << setw(17) << right << "FINAL PRICE: " << total * 90 / 100 << " JPY" << endl;
}

void Menu() {
    cout << endl << "\t\t\t      DISHES' PRICES" << endl << endl;

    cout << setfill('-');
    cout << "\t\t\t" << setw(26) << "-" << endl;
    cout << setfill(' ');

    cout << "\t\t\t|" << setw(16) << right << " Dishes ";
    cout << setw(15) << left << "| Price |" << endl;

    cout << setfill('-');
    cout << "\t\t\t" << setw(26) << "-" << endl;
    cout << setfill(' ');

    cout << "\t\t\t|" << setw(16) << right << "Burger ";
    cout << setw(15) << left << "| 130   |" << endl;

    cout << "\t\t\t|" << setw(16) << right << "Cheese burger ";
    cout << setw(15) << left << "| 150   |" << endl;

    cout << "\t\t\t|" << setw(16) << right << "Chicken burger ";
    cout << setw(15) << left << "| 200   |" << endl;

    cout << "\t\t\t|" << setw(16) << right << "Drink ";
    cout << setw(15) << left << "| 130   |" << endl;

    cout << "\t\t\t|" << setw(16) << right << "Potato ";
    cout << setw(15) << left << "| 120   |" << endl;

    cout << "\t\t\t|" << setw(16) << right << "Ice cream ";
    cout << setw(15) << left << "| 160   |" << endl;

    cout << setfill('-');
    cout << "\t\t\t" << setw(26) << "-" << endl;
    cout << setfill(' ');
}

void Infomation() {
    cout << endl << "\t\t  CHOOSE ONE OF THE SERVING TYPES BELOW:" << endl << endl;

    cout << setfill('-');
    cout << "  " << setw(65) << "-" << endl;
    cout << setfill(' ');

    cout << "  |" << setw(5) << left << " No.";
    cout << setw(15) << left << "| Serving Type";
    cout << setw(43) << left << "| ADish" << left << "|" << endl;

    cout << setfill('-');
    cout << "  " << setw(65) << "-" << endl;
    cout << setfill(' ');

    cout << "  |" << setw(5) << right << "1 ";
    cout << setw(15) << left << "|    Type A";
    cout << setw(16) << left << "| Burger" << setw(27) << ", Drink, Potato";
    cout << "|" << endl;

    cout << "  |" << setw(5) << right << "2 ";
    cout << setw(15) << left << "|    Type B";
    cout << setw(16) << left << "| Cheese burger" << setw(27) << ", Drink, Potato";
    cout << "|" << endl;

    cout << "  |" << setw(5) << right << "3 ";
    cout << setw(15) << left << "|    Type C";
    cout << setw(43) << left << "| Chicken burger, Drink, Potato";
    cout << "|" << endl;

    cout << "  |" << setw(5) << right << "4 ";
    cout << setw(15) << left << "|    Type D";
    cout << setw(43) << left << "| Chicken burger, Drink, Potato, Ice cream";
    cout << "|" << endl;

    cout << setfill('-');
    cout << "  " << setw(65) << "-" << endl;
    cout << setfill(' ');
}

MyFunctions.h:

#ifndef MyFunctions_h
#define MyFunctions_h

#include <iostream>
#include <iomanip>
#include <string>
#include "MyFunctions.h"

using namespace std;

struct Dish; 

struct Serving;


Dish* CreateDishArray(int n);

void DeleteDishArray(Serving*& serving, int n);

void DeleteServingArray(Serving*& serving);

void Increase(Serving*& serving, int& n);

void Choosing(Serving*& serving, int& n, char type);

void Bill(Serving*& serving, int n);

void Menu();

void Infomation();

#endif /* MyFunctions_h */
Nimantha
  • 6,405
  • 6
  • 28
  • 69
SnowyField
  • 47
  • 1
  • 9
  • `Serving *serving = new Serving[n];` when `n` is equal to zero will probably do that. You've allocated a zero-sized array... whatever that means. – paddy Mar 30 '22 at 12:00
  • @paddy Im sorry sir, but I still get error when I change `Serving *serving = new Serving[1];` – SnowyField Mar 30 '22 at 12:03
  • Why does `CreateDishArray` allocate an array with `n-1` elements when you ask for `n` elements? – molbdnilo Mar 30 '22 at 12:08
  • @molbdnilo OMG thank you so much sir, it works perfectly now!! I did `ctrl H` to change all `[n]` to `[n - 1]`, that's why this so stupid question appeared, thank you!!!!! – SnowyField Mar 30 '22 at 12:15
  • Also, it looks like you're making the classic student mistake of spending a lot of effort on polishing the layout of output. This usually feels like you're doing something, but is largely a waste of time. (And gets in the way of rethinking the structuring of data.) – molbdnilo Mar 30 '22 at 12:16
  • @molbdnilo thank you so much to give me this precious advice, that will be engraved in my heart. – SnowyField Mar 30 '22 at 12:19
  • After fixing the allocation size it seems to work, but there are still some warnings you should fix: https://godbolt.org/z/PnKjz65fo – mch Mar 30 '22 at 12:22
  • 1
    You should try to write your program in small, testable parts. Only build on what is already working. You have written too much code all at once, and then do not have yet the debugging ability to deal with it. – paddy Mar 30 '22 at 12:23
  • @mch oh.. I just want to give a wrong type to take it to `default` of the `switch`, that's why I used `NULL`, I should find way to fix it now. thank you so much!! – SnowyField Mar 30 '22 at 12:26
  • @paddy thank you, the problem has been fixed, so I will reorganize my code like what you advice me now – SnowyField Mar 30 '22 at 12:27
  • @SnowyField -- *Im sorry for that my code is so long* -- A lot of that code (and your issues with memory allocation) will go away if you had used `std::vector` and `std::vector` instead of `Dish *` and `Serving *`. The `n` member variable would be unnecessary in `Serving`, the code to delete all of those entries wouldn't be necessary, etc. – PaulMcKenzie Mar 30 '22 at 13:18
  • @SnowyField Also, get rid of `using namespace std;` in the header file. [See this](https://stackoverflow.com/questions/4872373/why-is-including-using-namespace-into-a-header-file-a-bad-idea-in-c). – PaulMcKenzie Mar 30 '22 at 13:22
  • @PaulMcKenzie thank you so much sir, I understood, I will do as what you advice me! – SnowyField Mar 30 '22 at 13:48

0 Answers0