Memory allocation

Hello,
I am writing a project that will read from an assortment of text files that create a menu and can read from it. I am getting the main menu to show but when I go to the next text file it just prints out the allocation to memory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  // A starting list of libaries. More could be added if needed.
#include <string>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <algorithm>

using namespace std;

// Global variable declarations

string mainMenu;
const double salesTax = 0.1; // This restaurant has a 10% sales tax

// Parallel arrays to store menu items and prices
string drinks[4], appetizers[4], entrees[5], desserts[3];
double drinkPrices[4], appetizerPrices[4], entreePrices[5], dessertPrices[3];

// Make more parallel arrays below this comment to store a customers order

enum menuType { MAIN, DRINK, APPETIZER, ENTREE, DESSERT };


string chooseDrinks[4], chooseAppetizers[4], chooseEntrees[5], chooseDesserts[3];
double chDrinkPrices[4], chAppPrices[4], chEntreePrices[5], chDessertsPrices[3];


//gets rid of whitespace
const string WHITESPACE = " \n\r\t\f\v|";

string ltrim(const string& s) {
    size_t start = s.find_first_not_of(WHITESPACE);
    return (start == string::npos) ? "" : s.substr(start);
}

string rtrim(const string& s) {
    size_t end = s.find_last_not_of(WHITESPACE);
    return (end == string::npos) ? "" : s.substr(0, end + 1);
}

string trim(const string& s) {
    return rtrim(ltrim(s));
}


void readMenu(string[]); // Expects an array of strings that are the names of the menu files

void makeOrder();

// Should walk the user through making a payment for their order
void makePayment();

int main() {
    // Each file name for the menus
    string fNames[] = { "Main.txt", "Drinks.txt", "Appetizers.txt", "Entrees.txt", "Desserts.txt" };

    readMenu(fNames); // Read from the files and store info into appropriate arrays
    makeOrder();  // Have the user make an order
    makePayment(); // Have the user pay for their meal

    return 0;
}


void readMenu(string fileNames[]) {
    bool done = false;
    int counter = 0;
    int selection = -1;
    menuType curMenu = MAIN;

    ifstream iFile;

    for (int curMenu = 0; curMenu < 5; ++curMenu) {
        iFile.open(fileNames[curMenu]); // Open the file
    }

    while (!done) {

        if (curMenu == MAIN) {
            // Read entire Main.txt file and store contents in the mainMenu string
            mainMenu.assign(istreambuf_iterator<char>(iFile), istreambuf_iterator<char>());

            cout << mainMenu << endl;
            cout << "Please enter one of the options above: ";
            cin >> selection;
            switch (selection) {
            case 0:
                done = true;
                break;
            case 1:
                curMenu = DRINK;
                break;
            case 2:
                curMenu = APPETIZER;
                break;
            case 3:
                curMenu = ENTREE;
                break;
            }
        }
        else if (curMenu == DRINK) {

            // Assign values to drinks
            if (iFile.is_open()) {
                getline(iFile, drinks[selection], '$');
                drinks[selection] = trim(drinks[selection]);
                iFile >> drinkPrices[selection];
            }
            cout << drinks << endl;
            cout << "Please enter one of the options above: ";
            cin >> selection;
            switch (selection) {
            case 0:
                curMenu = MAIN;
                break;
            case 1:

                break;
            case 2:
                break;
            case 3:
                break;
            }
        }
        else if (curMenu == APPETIZER) {
            if (iFile.is_open()) {
                getline(iFile, appetizers[selection], '$');
                appetizers[selection] = trim(appetizers[selection]);
                iFile >> appetizerPrices[selection];
            }
            cout << appetizers << endl;
            cout << "Please enter one of the options above: ";
            cin >> selection;
            switch (selection) {
            case 0:
                curMenu = MAIN;
                break;
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            }
        }
        else if (curMenu == ENTREE) {
            if (iFile.is_open()) {
                getline(iFile, entrees[selection], '$');
                entrees[selection] = trim(entrees[selection]);
                iFile >> entreePrices[selection];
            }
            cout << entrees << endl;
            cout << "Please enter one of the options above: ";
            cin >> selection;
            switch (selection) {
            case 0:
                curMenu = MAIN;
                break;
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            }
        }
        else if (curMenu == DESSERT) {
            if (iFile.is_open()) {
                getline(iFile, desserts[selection], '$');
                desserts[selection] = trim(desserts[selection]);
                iFile >> dessertPrices[selection];
            }
            cout << desserts << endl;
            cout << "Please enter one of the options above: ";
            cin >> selection;
            switch (selection) {
            case 0:
                curMenu = MAIN;
                break;
            case 1:
                break;
            case 2:
                break;
            case 3:
                break;
            }

        }
        system("cls");
    }

}

void makeOrder() {

}

void makePayment() {

}
Why don't you use binary files? Granted, they are a bit more complicated, but you can use just one to store all of that stuff in a data structure or something like that.

But ok. In your for loop there on line 74, why do you open all the files at once through one ifstream object?

Actually, your whole function there looks weird. Why do you initialize curMenu as MAIN, then redeclare it as int, and use the for loop to increment it. That just won't work.

I haven't done enumerations in years, so I won't try to give you advice on that. But it looks like you're not doing it quite right, based on my (limited) experience with classes and data structures. Maybe someone else can explain it better than I can.

I am also not 100% sure what this program is supposed to do exactly, but I will do my best (and hope I don't embarrass myself).

But, what I would try is: Maybe have the user input curMenu and pass it to the function. Then put your file opening stuff inside each if/else if statement– so open the Main.txt file in the if (curMenu == MAIN), etc.
line 110: Mean you cout << "drinks" << endl; instead of cout << drinks << endl;? Same for other, similar instructions.

I couldn'tt test your code because it lacks of of the text files. But at a first glance, your file handling code looks okay.
Clever approach reading your menus from files.
However, there are several problems with your code.

Lines 72-76: Your trying to open all the files using the same ifstream object. This won't work.
http://www.cplusplus.com/reference/fstream/ifstream/open/?kw=ifstream%3A%3Aopen

If the stream is already associated with a file (i.e., it is already open), calling this function fails.

Only the first file get's opened. The others fail. You need to subscript iFile.
72
73
74
75
76
77
78
79
ifstream iFile[5];
for (int curMenu = 0; curMenu < 5; ++curMenu) 
{  iFile[curMenu].open(fileNames[curMenu]); // Open the file
    if (!i File[curMenu])
    {   cout << "Could not open: " << fileNames[curMenu] << endl;
        return;
    }
}


Lines 70,78: You're using the same variable name as a local variable and as your loop variable. This is a poor practice as it is confusing to the reader.

Line 82: This is unsafe and wrong. This form of string.assign takes input_iterators to first and last. 1) This is unsafe because it assumes your menu files fits in the size of an ifstream buffer. You should not make that assumption. If you increase the size of your main menu, this may no longer be true and your program may no longer work.. 2) You're passing an iterator to first for both first and last.

General comment: You have hard coded the number of menus and the number of items in each menu. This is also a poor practice. If you want to change the number of menus or change the number of items in a menu, you have to change your program in many places. You program should work regardless of the number of items in a menu. You should use std::vector to stores your items.

Lines 104-125, 127-146, 169-189: These lines are identical except for the arrays they're using. These lines are perfect candidates to be replaced by a single function when the appropriate iFile, menu and price arrays (or vectors) are passed in as arguments.
The 'issue' with L82 is that by default an iterator on a char stream ignores white space. Hence before L82:

 
iFile >> noskipws;


https://en.cppreference.com/w/cpp/io/manip/skipws
Stream buffer iterators do not skip whitespace.
Thanks for the info! I've being using noskipws with buffer iterators since I don't know when! Probably because you do with an istream iterator and I wrongly assumed both the same. Doh!!
Topic archived. No new replies allowed.