write, save and read .dat files

Pages: 12
I need help writing, saving and then reading data from a .dat file.



The code below let the code I am able to edit but not to save, read the data.

Also when I edit any data the placeholder "0" doesn't go away. Please run the code and you will see what I'm talking about.

Note: When I terminate the program and run it again, I can't read the data anymore, even though there is a .dat file but I can't read it.
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


#include <iostream>
#include <string>
#include <fstream>


using namespace std;


#define MAX_RECORDS 10
#define NO_OF_CURRENT 7


struct Item{
char description[20];
double price;
int in_stock;
int sold;
};


Item items[MAX_RECORDS];


void createEmptyInventory();
void editInventory();
void displayInventory();
void makeAnOrder();
void createOrderReport();
void createRevenueReport();
void saveInventory();


void createEmptyInventory()
{
char ch;
cout<<"Warning! This will destroy all data."<<endl;
cout<<"Press 'y' to continue: ";
cin>>ch;
if(ch != 'y')
    return;
for(int i = 0; i < MAX_RECORDS; i++){
    for(int j = 0; j < 31; j++)
      items[i].description[j] = 0;
    items[i].price = 0.0;
    items[i].in_stock = 0;
    items[i].sold = 0;
}
saveInventory();
}


void displayInventory()
{
cout<<"ITEM# \t DESCRIPTION \t PRICE \t #INSTOCK \t #SOLD"<<endl;
for(int i = 0; i < NO_OF_CURRENT; i++)
    cout<<i+1<<"\t"<<items[i].description<<"\t"<<items[i].price
        <<"\t"<<items[i].in_stock<<"\t"<<items[i].sold<<endl;
}


void editInventory()
{
char ch;
int choice, itemNo;
do{
    displayInventory();
    cout<<"Which item # do you want to edit (-1 to quit): ";
    cin>>itemNo;
    if(itemNo == -1)
      return;
    if(itemNo <= 0 || itemNo > NO_OF_CURRENT){
      cout<<"Please enter valid item #"<<endl;
      ch = 'y';
      continue;
    }
    itemNo--;
    cout<<"1. Description"<<endl;
    cout<<"2. Price"<<endl;
    cout<<"3. Quantity In Stock"<<endl;
    cout<<"4. Quantity Sold"<<endl;
    cout<<"Enter choice: ";
    cin>>choice;
    switch(choice){
      case 1:
        cout<<"Enter new description: ";
        cin>>items[itemNo].description;
        break;
      case 2:
        cout<<"Enter new Price: ";
        cin>>items[itemNo].price;
        break;
      case 3:
        cout<<"Enter new quantity in stock: ";
        cin>>items[itemNo].in_stock;
        break;
      case 4:
        cout<<"Enter new quantity sold: ";
        cin>>items[itemNo].sold;
        break;
      default:
        cout<<"Invalid choice"<<endl;
        break;
    }
    cout<<"Do you want to edit another record (y/n)? ";
    cin>>ch;
}while(ch != 'n');
}


void makeAnOrder()
{
int choice, itemNo, qty;
while(true){
    displayInventory();
    cout<<"Which item # do you want to order (-1 to quit): ";
    cin>>itemNo;
    if(itemNo == -1)
      return;
    if(itemNo <= 0 || itemNo > NO_OF_CURRENT){
      cout<<"Please enter valid item #"<<endl;
      continue;
    }
    itemNo--;
    cout<<"Description: "<<items[itemNo].description<<endl;
    cout<<"Price: "<<items[itemNo].price<<endl;
    cout<<"Quantity In Stock: "<<items[itemNo].in_stock<<endl;
    cout<<"Quantity Sold: "<<items[itemNo].sold<<endl;
    cout<<"How many? ";
    cin>>qty;
    if(qty > items[itemNo].in_stock){
      cout<<"Sorry, your order exceeds number in stock."<<endl;
    }else{
      items[itemNo].in_stock -= qty;
      cout<<"Amount due: "<<items[itemNo].price*qty<<endl;
    }
}
}


void saveInventory()
{
ofstream outfile;
outfile.open("inventory.dat", ios::binary);
if(!outfile.is_open()){
    cout<<"File openning error."<<endl;
    return;
}
outfile.write((char*)&items, sizeof(items));
outfile.close();
}


int main()
{
int choice;
while(true){
    cout<<"\n    \n"<<endl;
    cout<<"\n   ORCHARD TO TABLE ORDERING SYSTEM \n"<<endl;
    cout<<"1. Create Empty Inventory"<<endl;
    cout<<"2. Display State of Inventory"<<endl;
    cout<<"3. Edit Inventory"<<endl;
    cout<<"4. Make an Order"<<endl;
    cout<<"5. Create Reorder Report"<<endl;
    cout<<"6. Create Revenue Report"<<endl;
    cout<<"7. Save Current Inventory"<<endl;
    cout<<"8. Quit \n"<<endl;
    cout<<"Enter your choice: "<<endl;
    cin>>choice;
    switch(choice){
      case 1:
        createEmptyInventory();
        break;
      case 2:
        displayInventory();
        break;
      case 3:
        editInventory();
        break;
      case 4:
        makeAnOrder();
        break;
      case 5:
        break;
      case 6:
        break;
      case 7:
        saveInventory();
        break;
      case 8:
        return 0;
      default:
        cout<<"Invalid choice"<<endl;
        break;
    }
}
return 0;
}
Last edited on
Didn't run your code, but just wanted to note that you're clearly going out of bounds at line 45.
1
2
    for(int j = 0; j < 31; j++)
      items[i].description[j] = 0;

Your description char array is only size 20, not 31.

even though there is a .dat file but I can't read it.
There isn't any place in your current code where you attempt to read a file.

Please prefer to use const int or constexpr int over ugly #define macros.
e.g. const int MAX_RECORDS = 10;
Last edited on
> I need help writing, saving and then reading data from a .dat file

Here is something to get you started:

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
#include <iostream>
#include <fstream>
#include <cstring> // std::strcmp
#include <cmath> // std::abs

struct Item {

    // aaded In-class member initializers
    // https://www.stroustrup.com/C++11FAQ.html#member-init
    char description[20] {};
    double price = 0.0 ;
    int in_stock = 0 ;
    int sold = 0 ;
};

// sanity check
bool valid( const Item& it ) {

    return it.description[0] && // description is not empty
           it.price >= 0.0 &&  // price is non-negative
           it.in_stock >= 0 &&  // qty in stock is non-negative
           it.sold >= 0 ;  // qty sold is non-negative
}

// write information about the item to an output stream
// a more idiomatic way is to overload the stream insertion operator
std::ostream& save( std::ostream& stm, const Item& it ) {

    // it is best to rely on plain text rather than binary goo
    // http://catb.org/esr/writings/taoup/html/ch05s01.html

    // we write one line of text for each member variable
    // and add an empty line at the end; it helps visually to separate the items in a file

    return stm << it.description << '\n'
               << it.price << '\n'
               << it.in_stock << '\n'
               << it.sold << '\n'
               << '\n' ;
}

// read information about the item (that was written earlier)  from an input stream
std::istream& load( std::istream& stm, Item& it ) {

    // read the first non-empty line into description
    do
        stm.getline( it.description, sizeof(it.description) ) ;
    while( it.description[0] == 0 ) ;

    // the the other fields
    stm >> it.price >> it.in_stock >> it.sold ;

    // if the read was successful and the data that was read is correct we are done
    if( stm && valid(it) ) return stm ;

    // read failed; indicate failure
    stm.clear( std::ios::failbit ) ; // put the stream into a failed state
    it = {} ; // clean out the item

    return stm ;
}

int main() {

    // create a dummy item for testing
    const Item it { "dummy test item XBT", 123.45, 678, 90 } ;

    // test our save function
    save( std::cout, it ) << "\n-----------\n" ;

    // write the info to a file
    const char file_name[] = "test_file.dat" ;

    {
        std::ofstream file(file_name) ;
        file << "\n\n\n" ; // put in a few empty lines (these should be skipped on input)
        if( save( file, it ) ) std::cout << "save ok\n" ;
    }

    // dump the contents of the file to se what was written
    std::cout << "\nthe file contains:\n-------\n" << std::ifstream(file_name).rdbuf() ;

    // read back what was saved
    {
        Item item_read_from_file ;
        std::ifstream file(file_name) ;
        if( load( file, item_read_from_file ) ) std::cout << "load ok\n" ;

        // visually verify that item_read_from_file contains the correct data
        std::cout << "\nitem read back is:\n-------\n" ;
        save( std::cout, item_read_from_file ) ;

        // verify it with program code
        if( std::strcmp( it.description, item_read_from_file.description ) == 0 &&
            std::abs( it.price - item_read_from_file.price ) < 0.00001 &&
            it.in_stock == item_read_from_file.in_stock &&
            it.sold == item_read_from_file.sold )
                std::cout << "ok. item_read_from_file is the same as the original item\n" ;
        else std::cout << "*** error *** : items do not match\n" ;
    }
}
sorry your code didn't help
When I select an item, I would like to enter all four fields associated with the item, successively. I do not want to have to bring up each item 4 times in order to enter the name of the item, the price of the item, the quantity in stock, and the number sold. That makes data entry too cumbersome. Finally, when I entered -1, in order to end the data entry, it went into an infinite loop, and the data never got stored.

To understrand better this program is about A large family farm is producing locally grown fruit and vegetables.Each week they deliver orders from the produce that they grow to local drop off points where customers pick up our weekly, freshly grown, produce.They are interested in creating an ordering mechanism by which people can select what they want to go into their weekly baskets.My job is to create software that will allow them to take custom orders that they will fill in boxes with their names on them.•The data, I will be using, is simply a fruit simulation of the data that they might actually use. Nonetheless, the principles will be the same.

I need help to FIX NUMBER 5. Create Reorder Report 6. Create Revenue Report 7. Save Current Inventory because they DON'T WORK. Finally, when I entered -1, in order to end the data entry, it went into an infinite loop, and the data never got stored.Therefore I still can't read
I've changed the code so that read/save now works OK and an extra option to create an inventory item. AFAIK, this all works OK now. What's left are options 5/6 (the reports). What should these look like?

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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

constexpr size_t MAX_RECORDS {10};
constexpr size_t SIZE_DESC {20};

struct Item {
	char description[SIZE_DESC] {};
	double price {};
	int in_stock {};
	int sold {};
};

Item items[MAX_RECORDS] {};

void createEmptyInventory();
void editInventory();
void displayInventory();
void makeAnOrder();
void createOrderReport();
void createRevenueReport();
void saveInventory();
void readInventory();
void createInventory();

void createEmptyInventory()
{
	char ch {};

	cout << "Warning! This will destroy all data." << endl;
	cout << "Press 'y' to continue: ";
	cin >> ch;

	if (ch == 'y') {
		for (size_t i = 0; i < MAX_RECORDS; ++i) {
			items[i].description[0] = 0;
			items[i].price = 0.0;
			items[i].in_stock = 0;
			items[i].sold = 0;
		}

		saveInventory();
	}
}

void createInventory()
{
	size_t itemNo {};

	for (; itemNo < MAX_RECORDS && items[itemNo].description[0]; ++itemNo);

	if (itemNo < MAX_RECORDS) {
		cout << "Enter description: ";
		cin >> items[itemNo].description;

		cout << "Enter Price: ";
		cin >> items[itemNo].price;

		cout << "Enter quantity in stock: ";
		cin >> items[itemNo].in_stock;

		cout << "Enter quantity sold: ";
		cin >> items[itemNo].sold;
	} else
		cout << "Inventory full\n";
}


void displayInventory()
{
	cout << "ITEM#\tDESCRIPTION\tPRICE\t#INSTOCK\t#SOLD\n";

	for (size_t i = 0; i < MAX_RECORDS; ++i)
		if (items[i].description[0])
			cout << i + 1 << "\t" << items[i].description << "\t\t" << items[i].price
				<< "\t" << items[i].in_stock << "\t\t" << items[i].sold << endl;
}


void editInventory()
{
	char again {'y'};

	do {
		displayInventory();
		int itemNo {};

		cout << "Which item # do you want to edit (-1 to quit): ";
		cin >> itemNo;

		if (itemNo == -1)
			return;

               --itemNo;

		if (itemNo < 0 || itemNo >= MAX_RECORDS || items[itemNo].description[0] == 0) {
			cout << "Please enter valid item #\n";
			continue;
		}

		int choice {};

		cout << "1. Description\n";
		cout << "2. Price\n";
		cout << "3. Quantity In Stock\n";
		cout << "4. Quantity Sold\n";
		cout << "Enter choice: ";
		cin >> choice;

		switch (choice) {
			case 1:
				cout << "Enter new description: ";
				cin >> items[itemNo].description;
				break;

			case 2:
				cout << "Enter new Price: ";
				cin >> items[itemNo].price;
				break;

			case 3:
				cout << "Enter new quantity in stock: ";
				cin >> items[itemNo].in_stock;
				break;

			case 4:
				cout << "Enter new quantity sold: ";
				cin >> items[itemNo].sold;
				break;

			default:
				cout << "Invalid choice\n";
				break;
		}

		cout << "Do you want to edit another record (y/n)? ";
		cin >> again;

	} while (again != 'n');
}

void makeAnOrder()
{
	while (true) {
		displayInventory();

		int itemNo {}, qty {};

		cout << "Which item # do you want to order (-1 to quit): ";
		cin >> itemNo;

		if (itemNo == -1)
			return;

               --itemNo;

		if (itemNo < 0 || itemNo >= MAX_RECORDS || items[itemNo].description[0] == 0) {
			cout << "Please enter valid item #" << endl;
			continue;
		}

		cout << "Description: " << items[itemNo].description << '\n';
		cout << "Price: " << items[itemNo].price << '\n';
		cout << "Quantity In Stock: " << items[itemNo].in_stock << '\n';
		cout << "Quantity Sold: " << items[itemNo].sold << '\n';

		cout << "How many? ";
		cin >> qty;

		if (qty > items[itemNo].in_stock)
			cout << "Sorry, your order exceeds number in stock.\n";
		else {
			items[itemNo].in_stock -= qty;
			items[itemNo].sold += qty;
			cout << "Amount due: " << items[itemNo].price * qty << '\n';
		}
	}
}

void saveInventory()
{
	ofstream outfile("inventory.dat", ios::binary);

	if (outfile.is_open())
		outfile.write((char*)&items, sizeof(items));
	else
		cout << "File opening error.\n";
}

void readInventory()
{
	ifstream infile("inventory.dat", ios::binary);

	if (infile.is_open()) {
		infile.read((char*)&items, sizeof(items));
		cout << "Read data file OK\n";
	} else
		cout << "Input file does not yet exist\n";
}

int main()
{
	readInventory();

	while (true) {
		int choice {};

		cout << "\n   ORCHARD TO TABLE ORDERING SYSTEM \n\n";
		cout << "1. Create Empty Inventory\n";
		cout << "2. Display State of Inventory\n";
		cout << "3. Edit Inventory\n";
		cout << "4. Make an Order\n";
		cout << "5. Create Reorder Report\n";
		cout << "6. Create Revenue Report\n";
		cout << "7. Save Current Inventory\n";
		cout << "8. Quit \n";
		cout << "9. Create an inventory item\n";

		cout << "Enter your choice: ";
		cin >> choice;

		switch (choice) {
			case 1:
				createEmptyInventory();
				break;

			case 2:
				displayInventory();
				break;

			case 3:
				editInventory();
				break;

			case 4:
				makeAnOrder();
				break;

			case 5:
				break;

			case 6:
				break;

			case 7:
				saveInventory();
				break;

			case 8:
				return 0;

			case 9:
				createInventory();
				break;

			default:
				cout << "Invalid choice\n";
				break;
		}
	}
	return 0;
}

Last edited on
Hello Leonardo797,

I am getting to this late because your original code gave me a headache last night trying to read it.

Now before I put any more time into it I have to ask if you want to stay with your original code, which is a good start, or ig you intend to rewrite based on the suggestions so far?

Andy
Hi Andy, yes I want to follow this structure..
Note see my revised code above.
Hello Leonardo797,

What I have been working on.

Made some changes to the header files:
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
#include <cctype>  // <--- For "std::tolower() and std::toupper()" + others.
#include <iostream>
#include <iomanip>  // <--- Output manipulators.
#include <limits>
#include <string>

#include <fstream>

using namespace std;  // <--- Should not be used.

constexpr int MAX_RECORDS{ 10 };
constexpr int NO_OF_CURRENT{ 7 };
constexpr int MAX_ARRAY_SIZE{ 21 };  // <--- To give an example. The variable name can be changed to anything you like.

//struct Item  // <--- For normal use.
//{
//    char description[MAX_ARRAY_SIZE]{};
//    double price{};
//    int in_stock{};
//    int sold{};
//};

struct Item  // <--- This 1 used for testing.
{
    char description[MAX_ARRAY_SIZE]{ "dummy test item XBTA" };
    double price{ 123.45 };
    int in_stock{ 678 };
    int sold{ 90 };
};

Item items[MAX_RECORDS];  // <--- Bad idea. Should not be a global variable. Should be defined in "main". 

Lines 11, 12 and 13 rep;lace the "#define"s that Ganado told you about.

As JLBorges pointed out you can initialize the variables in the struct when you define the struct. The second struct I did to have something to work with so I did not have to type everything each time the program runs. This 7 elements of the array to start with even though they are the same information.

Your prototypes are good, but will need to be changed in the futute.

Initializing the variables in the struct does tend to eliminate the need for the "createEmptyInventory" function, but if you have a need for it I would suggest:
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
void createEmptyInventory()
{
    char ch{ 'n' };

    //cout << "\n\n   Warning! This will destroy all data.\n";
    //cout << "   Press 'y' to continue: ";
    // <--- Alternative.
    cout << "\n\n   Warning! This will destroy all data.\n   Press 'y' to continue: ";  // <--- Can be combined into 1 line.
    cin >> ch;

    //if (ch != 'y')  // <--- Does not account for a capital 'Y'.
    if (std::tolower(ch) != 'y')  // <--- Alternative.
    //if (ch != 'y' && ch != 'Y')  // <--- Otherwise.
        return;

    for (int i = 0; i < MAX_RECORDS; i++)
    {
        for (int j = 0; j < MAX_ARRAY_SIZE; j++)
            items[i].description[j] = 0;

        items[i].price = 0.0;
        items[i].in_stock = 0;
        items[i].sold = 0;
    }

    saveInventory();
}

Some of the changes I made are not absolutely necessary, but something to consider. Like the first "cout" does not have to be 1 line, but I would keep the "\n"s and the indentation. It looks like this:




    ORCHARD TO TABLE ORDERING SYSTEM
 1. Create Empty Inventory
 2. Display State of Inventory
 3. Edit Inventory
 4. Make an Order
 5. Create Reorder Report
 6. Create Revenue Report
 7. Save Current Inventory
 8. Quit
  Enter your choice: 1


   Warning! This will destroy all data.
   Press 'y' to continue:


Indenting the warning message tends to catch the attention of whom ever is using it.

Next I worked on the "displayInventory" function. This is a good place to use "setw()" from the "<iomanip>" header file if you can. If you can not use "setw()" there are other ways, just not as easy to work with.

Using "setw()" the output I get is:

ITEM#    DESCRIPTION        PRICE   #INSTOCK   #SOLD
  1   dummy test item XBT  123.45     678        90
  2   dummy test item XBT  123.45     678        90
  3   dummy test item XBT  123.45     678        90
  4   dummy test item XBT  123.45     678        90
  5   dummy test item XBT  123.45     678        90
  6   dummy test item XBT  123.45     678        90
  7   dummy test item XBT  123.45     678        90


It is a start, but it is more to show how everything can line up better.

Your use of the "\t" is not always a good idea. As the first character in a string it works fine, but after that columns may not line up correctly.

You will have to let me know what you can do with your output and what you can use to format it.

I would work on this much for now, but mostly the display function. When your display function works it will make it easier to see and changes that are made in the edit function.

The write function works well and I did not change anything there except for adding some blank lines.

Your read function that you need would be the opposite of the write function. You could just copy the write function and make the necessary changes for reading.

In "main" I started off with this:
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
int main()
{
    bool save{};  // <--- For future use.
    int choice{};
    //Item items[MAX_RECORDS]{};  // <--- Should be here and passed to the functions that need it.

    std::cout << std::fixed << std::showpoint << std::setprecision(2);  // <--- Only needs done once.

    //ReadFile(items);

    while (true)
    {
        cout << 
            "\n\n\n"
            "    ORCHARD TO TABLE ORDERING SYSTEM\n"
            " 1. Create Empty Inventory\n"
            " 2. Display State of Inventory\n"
            " 3. Edit Inventory\n"
            " 4. Make an Order\n"
            " 5. Create Reorder Report\n"
            " 6. Create Revenue Report\n"
            " 7. Save Current Inventory\n"
            " 8. Quit \n"
            "  Enter your choice: ";
        cin >> choice;

Reading the file should be done before the menu so that you have something to work with. As long as the file exists and is not empty. Otherwise if there is nothing to read you can start with calling "createEmptyInventory" to set up a starting array to use.

Using the "cout" this way makes it easier to work with. You do not need all those "cout"s for each line.

And when it comes to "endl" prefer to use "\n" instead. Also in the above example the "cout" followed by the "cin". The "cin" will flush the output buffer before taking any input, so there is no need for "endl" or "flush".

For now the switch works. I have no need to change it yet.

What you do need to tell me is if the function "createEmptyInventory" is necessary or if it can be eliminated?

If I understand what you wanted for choice 3 the "edit" you can eliminate the menu and switch and do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cout << "\n New Description: ";
std::cin.getline(items[itemNo].description, MAX_ARRAY_SIZE);

cout << " New Price: ";
std::cin >> items[itemNo].price;

cout << " New Quantity In Stock: ";
std::cin >> items[itemNo].in_stock;

cout << " New Quantity Sold: ";
std::cin >> items[itemNo].sold;

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
                          // You may need this after the last formatted input and before the "cin.getline". 


For the main menu I am thinking something like this:
1
2
3
4
5
6
7
8
9
10
11
12
cout <<
    "\n\n\n"
    "    ORCHARD TO TABLE ORDERING SYSTEM\n"
    "  1. Display State of Inventory\n"
    "  2. Edit Inventory\n"
    "  3. Make an Order\n"
    "  4. Create Reorder Report\n"
    "  5. Create Revenue Report\n"
    "  6. Save Current Inventory\n"
    "  7. Quit \n"
    " 10. Create Empty Inventory\n"
    "  Enter your choice: ";

An idea to add a little difficultly to wipeing out your array which you may not want to do.

Andy
@seeplus,

I did, but please explain how cin >> items[itemNo].description; will accept input of "Green Beans"?

Andy
It won't. But neither did the OP original code. Also I didn't format the display much. Once the program is 'working' these are easy to change. There's also no checking for valid numeric input (enter a letter for a menu option.) et al.

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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cctype>

using namespace std;

constexpr size_t MAX_RECORDS {10};
constexpr size_t SIZE_DESC {20};

struct Item {
	char description[SIZE_DESC] {};
	double price {};
	int in_stock {};
	int sold {};
};

Item items[MAX_RECORDS] {};

void createEmptyInventory();
void editInventory();
void displayInventory();
void makeAnOrder();
void createOrderReport();
void createRevenueReport();
void saveInventory();
void readInventory();
void createInventory();
double getDouble(const std::string& prm = "");
int getInt(const std::string& prm = "");

double getDouble(const std::string& prm)
{
	double d {};

	while ((std::cout << prm) && !(cin >> d)) {
		std::cout << "Invalid number\n";
		if (prm.empty()) std::cout << "Please re-enter: ";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	return d;
}

int getInt(const std::string& prm)
{
	int i {};

	while ((std::cout << prm) && !(cin >> i)) {
		std::cout << "Invalid number\n";
		if (prm.empty()) std::cout << "Please re-enter: ";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	return i;
}

void createEmptyInventory()
{
	char ch {};

	cout << "Warning! This will destroy all data." << endl;
	cout << "Press 'y' to continue: ";
	cin >> ch;

	if (std::tolower(ch) == 'y') {
		for (size_t i = 0; i < MAX_RECORDS; ++i) {
			items[i].description[0] = 0;
			items[i].price = 0.0;
			items[i].in_stock = 0;
			items[i].sold = 0;
		}

		saveInventory();
	}
}

void createInventory()
{
	size_t itemNo {};

	for (; itemNo < MAX_RECORDS && items[itemNo].description[0]; ++itemNo);

	if (itemNo < MAX_RECORDS) {
		cout << "Enter description: ";
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		std::cin.getline(items[itemNo].description, SIZE_DESC);

		items[itemNo].price = getDouble("Enter Price: ");
		items[itemNo].in_stock = getInt("Enter quantity in stock : ");
		items[itemNo].sold = getInt("Enter quantity sold: ");
	} else
		cout << "Inventory full\n";
}


void displayInventory()
{
	cout << std::left << std::setw(8) << "ITEM#" << std::setw(SIZE_DESC + 2) << "DESCRIPTION" << std::setw(8) << "PRICE" << std::setw(11) << "#INSTOCK" << "#SOLD\n";

	for (size_t i = 0; i < MAX_RECORDS; ++i)
		if (items[i].description[0])
			cout << std::left << std::setw(8) << i + 1 << std::setw(SIZE_DESC + 2) << items[i].description << std::right << std::setw(5) << items[i].price
			<< std::setw(11) << items[i].in_stock << std::setw(8) << items[i].sold << '\n';
}


void editInventory()
{
	char again {'y'};

	do {
		displayInventory();

		const int itemNo {getInt("Which item # do you want to edit (-1 to quit): ") - 1};

		if (itemNo == -2)
			break;

		if (itemNo < 0 || itemNo >= MAX_RECORDS || items[itemNo].description[0] == 0) {
			cout << "Please enter valid item #\n";
			continue;
		}

		cout << "1. Description\n";
		cout << "2. Price\n";
		cout << "3. Quantity In Stock\n";
		cout << "4. Quantity Sold\n";
		cout << "Enter choice: ";

		switch (getInt()) {
			case 1:
				cout << "Enter new description: ";
				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
				std::cin.getline(items[itemNo].description, SIZE_DESC);
				break;

			case 2:
				items[itemNo].price = getDouble("Enter new Price: ");
				break;

			case 3:
				items[itemNo].in_stock = getInt("Enter new quantity in stock : ");
				break;

			case 4:
				items[itemNo].sold = getInt("Enter new quantity sold: ");
				break;

			default:
				cout << "Invalid choice\n";
				break;
		}

		cout << "Do you want to edit another record (y/n)? ";
		cin >> again;

	} while (std::tolower(again) == 'y');
}

void makeAnOrder()
{
	while (true) {
		displayInventory();

		const int itemNo {getInt("Which item # do you want to order (-1 to quit): ") - 1};

		if (itemNo == -2)
			break;

		if (itemNo < 0 || itemNo >= MAX_RECORDS || items[itemNo].description[0] == 0) {
			cout << "Please enter valid item #" << endl;
			continue;
		}

		cout << "Description: " << items[itemNo].description << '\n';
		cout << "Price: " << items[itemNo].price << '\n';
		cout << "Quantity In Stock: " << items[itemNo].in_stock << '\n';
		cout << "Quantity Sold: " << items[itemNo].sold << '\n';

		const int qty {getInt("How many? ")};

		if (qty > items[itemNo].in_stock)
			cout << "Sorry, your order exceeds number in stock.\n";
		else {
			items[itemNo].in_stock -= qty;
			items[itemNo].sold += qty;
			cout << "Amount due: " << items[itemNo].price * qty << '\n';
		}
	}
}

void saveInventory()
{
	ofstream outfile("inventory.dat", ios::binary);

	if (outfile.is_open())
		outfile.write((char*)&items, sizeof(items));
	else
		cout << "File opening error.\n";
}

void readInventory()
{
	ifstream infile("inventory.dat", ios::binary);

	if (infile.is_open()) {
		infile.read((char*)&items, sizeof(items));
		cout << "Read data file OK\n";
	} else
		cout << "Input file does not yet exist\n";
}

int main()
{
	readInventory();

	while (true) {
		cout << "\n   ORCHARD TO TABLE ORDERING SYSTEM \n\n";
		cout << "1. Create Empty Inventory\n";
		cout << "2. Display State of Inventory\n";
		cout << "3. Edit Inventory\n";
		cout << "4. Make an Order\n";
		cout << "5. Create Reorder Report\n";
		cout << "6. Create Revenue Report\n";
		cout << "7. Save Current Inventory\n";
		cout << "8. Quit \n";
		cout << "9. Create an inventory item\n";

		cout << "Enter your choice: ";

		switch (getInt()) {
			case 1:
				createEmptyInventory();
				break;

			case 2:
				displayInventory();
				break;

			case 3:
				editInventory();
				break;

			case 4:
				makeAnOrder();
				break;

			case 5:
				break;

			case 6:
				break;

			case 7:
				saveInventory();
				break;

			case 8:
				return 0;

			case 9:
				createInventory();
				break;

			default:
				cout << "Invalid choice\n";
				break;
		}
	}
}

Last edited on
CPLUS your program didn't work when editing the items

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

   ORCHARD TO TABLE ORDERING SYSTEM

1. Create Empty Inventory
2. Display State of Inventory
3. Edit Inventory
4. Make an Order
5. Create a Reorder Report
6. Create Revenue Report
7. Save Current Inventory
8. Quit
9. Create an inventory item
Enter your choice: 3
ITEM#   DESCRIPTION           PRICE   #INSTOCK   #SOLD
Which item # do you want to edit (-1 to quit): 1
Please enter valid item # 


My code actually worked on the editing part, yours didn't


Andy thanks for the explanation, yes I can get rid of the switch, I decided, if necessary, I just need it to work

I fixed
#1 , empty the dat file
#2 , display the record the correct way
#4, edit the correct way


I still need help saving the data after editing the info and I need to fix 5,6,7

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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>

using namespace std;

const int DESC_SIZE = 21;
const int NUM_RECORDS = 10;
const int NO_OF_CURRENT = 7;
//#define NO_OF_CURRENT 7

struct Item{
char description[DESC_SIZE];
double price;
int quantitySold;
int quantityInStock;
};


Item items[NUM_RECORDS];


void createEmptyInventory();
void editInventory();
void displayInventory();
void makeAnOrder();
void createOrderReport();
void createRevenueReport();
void saveInventory();


void createEmptyInventory()
{
    char ch;
    cout << "Warning! This will destroy all data." << endl;
    cout << "Press 'y' to continue: ";
    cin >> ch;
    if (ch != 'y')
        return;
cout << "\nInventory Is Now Empty" << endl;
// Create an empty Inventory item structure.
Item record = { "",0.0, 0, 0 };
// Open the file for binary output.
fstream inventory("inventory.dat", ios::out | ios::binary);
// Write the blank records.

 // Close the file.
//inventory.write(reinterpret_cast<char *>(&record),
               //  sizeof(record));
 inventory.close();
}

// void displayInventory()
//{
//cout<<"ITEM# \t DESCRIPTION \t PRICE \t #INSTOCK \t #SOLD"<<endl;
//for(int i = 0; i < NO_OF_CURRENT; i++)
//   cout<<i+1<<"\t"<<items[i].description<<"\t"<<items[i].price
//       <<"\t"<<items[i].in_stock<<"\t"<<items[i].sold<<endl;
//}

void displayInventory()
{
    Item record;	// To hold an inventory record
// Open the file for binary input.
    fstream inventory("inventory.dat", ios::in | ios::binary);
// Now read and display the records.
    inventory.read(reinterpret_cast<char *>(&record), sizeof(record));
    int width = 14;
    cout << setw(5) << "ITEM#" << setw(2 * width) << "DESCRIPTION" << setw(width) << "PRICE" << setw(width) << "#INSTOCK" << setw(width) << "#SOLD" << endl;
    for (int i = 0; i < NO_OF_CURRENT; i++)
        cout << setw(5) << i + 1 << setw(2 * width) << items[i].description << setw(width) << items[i].price << setw(width) << items[i].quantityInStock << setw(width) << items[i].quantitySold << endl;
}



void editInventory()

{
Item record;
int recNum;
// To hold an inventory record
// To hold a record number
    fstream inventory("inventory.dat", ios::in | ios::out | ios::binary);
// Open the file in binary mode for input and output.
// Get the record number of the desired record.
     char ch;
    int choice, itemNo;
    do
    {
        displayInventory();
        cout << "Which item # do you want to edit (-1 to quit): ";
        cin >> itemNo;
        if (itemNo == -1)
            return;
        if (itemNo <= 0 || itemNo > NO_OF_CURRENT)
        {
            cout << "Please enter valid item #" << endl;
            ch = 'y';
            continue;
        }
// Move to the record and read it.

// Display the record contents.
    itemNo--;
    cout << "Description: ";
    cout << items[itemNo].description << endl;
    cout << "Price: ";
    cout << items[itemNo].price << endl;
    cout << "In Stock: ";
    cout << items[itemNo].quantityInStock << endl;
    cout << "Sold: ";
    cout << items[itemNo].quantitySold << endl;

// Get the new record data.
    cout << "Enter the new data:\n";
    cout << "Description: ";
    cin.ignore();
    cin.getline(items[itemNo].description, DESC_SIZE);

    cout << "Price: ";
    cin >> items[itemNo].price;

    cout << "In Stock: ";
    cin >> items[itemNo].quantityInStock;

    cout << "Quantity Sold: ";
    cin >> items[itemNo].quantitySold;
    //inventory.seekg(recNum * sizeof(record), ios::beg);
    //inventory.read(reinterpret_cast<char *>(&record), sizeof(record));

// Move back to the beginning of the this record's position.
    inventory.seekp(recNum * sizeof(record), ios::beg);
// Write the new record over the current record.
    //ventory.write(reinterpret_cast<char *>(&record), sizeof(record));
    saveInventory();
// Close the file.
      cout << "Do you want to edit another record (y/n)? ";
     cin >> ch;
    } while (ch != 'n');
}



void makeAnOrder()
{
int choice, itemNo, qty;
while(true){
    displayInventory();
    cout<<"Which item # do you want to order (-1 to quit): ";
    cin>>itemNo;
    if(itemNo == -1)
      return;
    if(itemNo <= 0 || itemNo > NO_OF_CURRENT){
      cout<<"Please enter valid item #"<<endl;
      continue;
    }
    itemNo--;
    cout<<"Description: "<<items[itemNo].description<<endl;
    cout<<"Price: "<<items[itemNo].price<<endl;
    cout<<"Quantity In Stock: "<<items[itemNo].quantityInStock<<endl;
    cout<<"Quantity Sold: "<<items[itemNo].quantitySold<<endl;
    cout<<"How many? ";
    cin>>qty;
    if(qty > items[itemNo].quantityInStock){
      cout<<"Sorry, your order exceeds number in stock."<<endl;
    }else{
      items[itemNo].quantityInStock -= qty;
      cout<<"Amount due: "<<items[itemNo].price*qty<<endl;
    }
}
}


void saveInventory()
{
ofstream outfile;
outfile.open("inventory.dat", ios::binary);
if(!outfile.is_open()){
    cout<<"File openning error."<<endl;
    return;
}
outfile.write((char*)&items, sizeof(items));
outfile.close();
}


int main()

{


// To hold an inventory record
// To hold a record number
int choice;
while(true){
    cout<<"\n    \n"<<endl;
    cout<<"\n   ORCHARD TO TABLE ORDERING SYSTEM \n"<<endl;
    cout<<"1. Create Empty Inventory"<<endl;
    cout<<"2. Display State of Inventory"<<endl;
    cout<<"3. Edit Inventory"<<endl;
    cout<<"4. Make an Order"<<endl;
    cout<<"5. Create Reorder Report"<<endl;
    cout<<"6. Create Revenue Report"<<endl;
    cout<<"7. Save Current Inventory"<<endl;
    cout<<"8. Quit \n"<<endl;
    cout<<"Enter your choice: "<<endl;
    cin>>choice;
    switch(choice){
      case 1:
        createEmptyInventory();
        break;
      case 2:
        displayInventory();
        break;
      case 3:
        editInventory();
        break;
      case 4:
        makeAnOrder();
        break;
      case 5:
        break;
      case 6:
        break;
      case 7:
        saveInventory();
        break;
      case 8:
        return 0;
      default:
        cout<<"Invalid choice"<<endl;
        break;
    }
}
return 0;
}

Last edited on
What you displayed above is correct. It is not showing any items in the display - so you can't edit them! You can only edit an existing item. If you want to add a new item then there is option 9. If you want, option 3 can be easily changed to be edit/create an inventory item with say item 0 being to create a new item - as below.

Also, in your revised code above, you've saving the data automatically after it has been edited/created - but not after an order is placed?? If this is wanted, then it's easy - but there is option 7 to save the data.

Re options 5 & 6 - you haven't said what they are supposed to do (I asked previously) and what the display should look like.

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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <limits>
#include <cctype>

using namespace std;

constexpr size_t MAX_RECORDS {10};
constexpr size_t SIZE_DESC {20};

struct Item {
	char description[SIZE_DESC] {};
	double price {};
	int in_stock {};
	int sold {};
};

Item items[MAX_RECORDS] {};

void createEmptyInventory();
void editInventory();
void displayInventory();
void makeAnOrder();
void createOrderReport();
void createRevenueReport();
void saveInventory();
void readInventory();
void createInventory();
double getDouble(const std::string& prm = "");
int getInt(const std::string& prm = "");

double getDouble(const std::string& prm)
{
	double d {};

	while ((std::cout << prm) && !(std::cin >> d)) {
		std::cout << "Invalid number\n";
		if (prm.empty()) std::cout << "Please re-enter: ";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	return d;
}

int getInt(const std::string& prm)
{
	int i {};

	while ((std::cout << prm) && !(std::cin >> i)) {
		std::cout << "Invalid number\n";
		if (prm.empty()) std::cout << "Please re-enter: ";
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
	}

	return i;
}

void createEmptyInventory()
{
	char ch {};

	cout << "Warning! This will destroy all data." << endl;
	cout << "Press 'y' to continue: ";
	cin >> ch;

	if (std::tolower(ch) == 'y') {
		for (size_t i = 0; i < MAX_RECORDS; ++i) {
			items[i].description[0] = 0;
			items[i].price = 0.0;
			items[i].in_stock = 0;
			items[i].sold = 0;
		}

		saveInventory();
	}
}

void createInventory()
{
	size_t itemNo {};

	for (; itemNo < MAX_RECORDS && items[itemNo].description[0]; ++itemNo);

	if (itemNo < MAX_RECORDS) {
		cout << "New item " << itemNo + 1 << '\n';
		cout << "Enter description: ";
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		std::cin.getline(items[itemNo].description, SIZE_DESC);

		items[itemNo].price = getDouble("Enter Price: ");
		items[itemNo].in_stock = getInt("Enter quantity in stock : ");
		items[itemNo].sold = getInt("Enter quantity sold: ");
	} else
		cout << "Inventory full\n";
}


void displayInventory()
{
	cout << std::left << std::setw(8) << "ITEM#" << std::setw(SIZE_DESC + 2) << "DESCRIPTION" << std::setw(8) << "PRICE" << std::setw(11) << "#INSTOCK" << "#SOLD\n";

	for (size_t i = 0; i < MAX_RECORDS; ++i)
		if (items[i].description[0])
			cout << std::left << std::setw(8) << i + 1 << std::setw(SIZE_DESC + 2) << items[i].description << std::right << std::setw(5) << items[i].price
			<< std::setw(11) << items[i].in_stock << std::setw(8) << items[i].sold << '\n';
}


void editInventory()
{
	char again {'y'};

	do {
		displayInventory();

		const int itemNo {getInt("Which item # do you want to edit (0 to create, -1 to quit): ") - 1};

		if (itemNo == -2)
			break;

		if (itemNo == -1) {
			createInventory();
			continue;
		}

		if (itemNo < 0 || itemNo >= MAX_RECORDS || items[itemNo].description[0] == 0) {
			cout << "Please enter valid item #\n";
			continue;
		}

		cout << "1. Description\n";
		cout << "2. Price\n";
		cout << "3. Quantity In Stock\n";
		cout << "4. Quantity Sold\n";
		cout << "Enter choice: ";

		switch (getInt()) {
			case 1:
				cout << "Enter new description: ";
				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
				std::cin.getline(items[itemNo].description, SIZE_DESC);
				break;

			case 2:
				items[itemNo].price = getDouble("Enter new Price: ");
				break;

			case 3:
				items[itemNo].in_stock = getInt("Enter new quantity in stock : ");
				break;

			case 4:
				items[itemNo].sold = getInt("Enter new quantity sold: ");
				break;

			default:
				cout << "Invalid choice\n";
				break;
		}

		cout << "Do you want to edit another record (y/n)? ";
		cin >> again;

	} while (std::tolower(again) == 'y');
}

void makeAnOrder()
{
	while (true) {
		displayInventory();

		const int itemNo {getInt("Which item # do you want to order (-1 to quit): ") - 1};

		if (itemNo == -2)
			break;

		if (itemNo < 0 || itemNo >= MAX_RECORDS || items[itemNo].description[0] == 0) {
			cout << "Please enter valid item #" << endl;
			continue;
		}

		cout << "Description: " << items[itemNo].description << '\n';
		cout << "Price: " << items[itemNo].price << '\n';
		cout << "Quantity In Stock: " << items[itemNo].in_stock << '\n';
		cout << "Quantity Sold: " << items[itemNo].sold << '\n';

		const int qty {getInt("How many? ")};

		if (qty > items[itemNo].in_stock)
			cout << "Sorry, your order exceeds number in stock.\n";
		else {
			items[itemNo].in_stock -= qty;
			items[itemNo].sold += qty;
			cout << "Amount due: " << items[itemNo].price * qty << '\n';
		}
	}
}

void saveInventory()
{
	ofstream outfile("inventory.dat", ios::binary);

	if (outfile.is_open())
		outfile.write((char*)&items, sizeof(items));
	else
		cout << "File opening error.\n";
}

void readInventory()
{
	ifstream infile("inventory.dat", ios::binary);

	if (infile.is_open()) {
		infile.read((char*)&items, sizeof(items));
		cout << "Read data file OK\n";
	} else
		cout << "Input file does not yet exist\n";
}

int main()
{
	readInventory();

	while (true) {
		cout << "\n   ORCHARD TO TABLE ORDERING SYSTEM \n\n";
		cout << "1. Create Empty Inventory\n";
		cout << "2. Display State of Inventory\n";
		cout << "3. Edit/Create Inventory\n";
		cout << "4. Make an Order\n";
		cout << "5. Create Reorder Report\n";
		cout << "6. Create Revenue Report\n";
		cout << "7. Save Current Inventory\n";
		cout << "8. Quit \n";
		//cout << "9. Create an inventory item\n";

		cout << "Enter your choice: ";

		switch (getInt()) {
			case 1:
				createEmptyInventory();
				break;

			case 2:
				displayInventory();
				break;

			case 3:
				editInventory();
				break;

			case 4:
				makeAnOrder();
				break;

			case 5:
				break;

			case 6:
				break;

			case 7:
				saveInventory();
				break;

			case 8:
				return 0;

			//case 9:
				//createInventory();
				//break;

			default:
				cout << "Invalid choice\n";
				break;
		}
	}
}

Last edited on
Hello Leonardo797,

I have been looking at your last code all morning and I am not sure where to start.

You have gone from a good start with your original code to something that makes no sense.

To start with, on the left, and changed to, on the right:
1
2
3
4
5
6
7
struct Item
{
    char description[20];
    double price;
    int in_stock;                      //--->
    int sold;                          //--->
};
struct Item
{
    char description[DESC_SIZE];
    double price;
    int quantitySold;
    int quantityInStock;
};

Although I do like the variable names in the new struct the order they are defined in needs to be the same as the old struct. Or you will have to create a whole new file to match the new struct.

Next is your global variable. You are counting on the variable being defined as a global variable to be initialized when it is defined. DO NOT count on this. There is no guarantee this will happen. This may be true for the newer compilers, but not for older compilers.

Since it is used often:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void displayInventory()
{
    Item record;	// To hold an inventory record

    // Open the file for binary input.
    fstream inventory("inventory.dat", ios::in | ios::binary);

    // Now read and display the records.
    inventory.read(reinterpret_cast<char *>(&record), sizeof(record));

    int width = 14;

    cout << setw(5) << "ITEM#" << setw(2 * width) << "DESCRIPTION" << setw(width) << "PRICE" << setw(width) << "#INSTOCK" << setw(width) << "#SOLD" << endl;

    for (int i = 0; i < NO_OF_CURRENT; i++)
        cout << setw(5) << i + 1 << setw(2 * width) << items[i].description << setw(width) << items[i].price << setw(width) << items[i].quantityInStock << setw(width) << items[i].quantitySold << endl;
}

This does not work.

Line 3 creates an object of type "Item" that is local to the function.

Line 6 creates an object of "fstream" to read the file and opens the file. This is OK.

Line 9 reads the first record in the file.

Line 11 is OK, but makes me think that you are not understanding the use of "setw()".

Line 15 is fine, but could be updated later on.

Line 16 is wrong. First in the use of the "setw()"s but mostly in what you are using to print.

You have read the file for the first record, but you are trying to print the array that is empty and never been changed. At this point it does not matter if the main menu choice is 2, 3 or 4 there is nothing in the array to print.

Make a choice either to print the file or the array.

It has been pointed out several times that the program never reads the file to fill the array with its information. This needs to be done.

The function:
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
void createEmptyInventory()
{
    char ch;

    cout << "Warning! This will destroy all data." << endl;
    cout << "Press 'y' to continue: ";
    cin >> ch;

    if (ch != 'y')
        return;

    cout << "\nInventory Is Now Empty" << endl;

    // Create an empty Inventory item structure.
    Item record = { "", 0.0, 0, 0 };

    // Open the file for binary output.
    fstream inventory("inventory.dat", ios::out | ios::binary);
    // Write the blank records.

    // Close the file.
    //inventory.write(reinterpret_cast<char *>(&record),
                   //  sizeof(record));
    //inventory.close();
}

Line 9 only accepts a lower case "y" to make the condition false, but rejects an upper case "Y". Somehow you need to account for both cases.

Line 12 is OK,but really done to early and in the end it does not apply based on the rest of the code.

Line 15 creates an object of type "Item". This becomes a local variabel to the function which you set when you define it.

Line 18 creates a file stream and opens the file, but you should check that the file is open before you try to use it. Even though it is an output file that will be created if it does not exist there are still other reasons that this may not happen, so it needs to be checked. This should be done every time you open a file stream for input or output.

After this you do not do anything to the array or write anything to the file to change anything.

Your original code was better.

For the function:
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
void editInventory()
{
    Item record;
    long recNum;

    // To hold an inventory record
    // To hold a record number
    fstream inventory("inventory.dat", ios::in | ios::out | ios::binary);
    // Open the file in binary mode for input and output.
    // Get the record number of the desired record.

    displayInventory();

    cout << "\Which record do you want to edit? ";
    cin >> recNum;

    recNum--;

    // Move to the record and read it.
    inventory.seekg(recNum * sizeof(record), ios::beg);
    inventory.read(reinterpret_cast<char *>(&record), sizeof(record));

    //Display the record contents.
    cout << "\nDescription: ";
    cout << record.description << endl;
    cout << "Price: ";
    cout << record.price << endl;
    cout << "In Stock: ";
    cout << record.quantityInStock << endl;
    cout << "Sold: ";
    cout << record.quantitySold << endl;

    // Get the new record data.
    cout << "\nEnter the new data:\n";
    cout << "Description: ";
    cin.ignore();
    cin.getline(record.description, DESC_SIZE);

    cout << "Price: ";
    cin >> record.price;

    cout << "In Stock: ";
    cin >> record.quantityInStock;

    cout << "Quantity Sold: ";
    cin >> record.quantitySold;

    // Move back to the beginning of the this record's position.
    inventory.seekp(recNum * sizeof(record), ios::beg);
    // Write the new record over the current record.
        //ventory.write(reinterpret_cast<char *>(&record), sizeof(record));
    saveInventory();
    // Close the file.
    inventory.close();
}

Line 3 and 4 are OK.

Line 12 displays the inventory, but there is nothing to display at this point.

What is displayed is:

ITEM#                 DESCRIPTION         PRICE      #INSTOCK         #SOLD
    1                                         0             0             0
    2                                         0             0             0
    3                                         0             0             0
    4                                         0             0             0
    5                                         0             0             0
    6                                         0             0             0
    7                                         0             0             0
Which record do you want to edit?


So when you enter a number 1 - 7 at line 15 you are off by 1.

Line 20 will reposition the file pointer, but if you had chosen 1 it will actually display record 2 not 1, which starts at (0) zero.

You need line 17, so that the "seekg" will position the file pointer in the right place.

I have already showed you how you can take the 8 lines 24 - 31 and shorten them to just 4 lines, but if you are not interested or ready for this that is fine.

Then again this is taking information from a file when it should be using the array.

Then after you have take all the input and changed the local variable you do not use it to change the array, but you do call "saveInventory();" to save an array that has not changed. Not what you want.

Your original code is better. The menu and switch is good it just to be in a loop to edit 1 or more variables instead of doing 1 at a time or entering information that may not change.

Over all your original code is better to work with than this new one.

And do not discount what seeplus has posted. Even if you can not use his code directly what is there is worth considering.

Sorry I have not started on the "makeAnOrder" function yet.

Andy
Hello Leonardo797,

I did a little work on the original code to get this:

    ORCHARD TO TABLE ORDERING SYSTEM
  1. Display State of Inventory
  2. Edit Inventory
  3. Make an Order
  4. Create Reorder Report
  5. Create Revenue Report
  6. Save Current Inventory
  9. Quit
 10. Create Empty Inventory
  Enter your choice: 2

ITEM#    DESCRIPTION        PRICE   #INSTOCK   #SOLD
----------------------------------------------------
  1   Johnathon Apples       65.75     100        2
  2   Green Beans            50.25     150       10
  3   Peas                   31.00     150        5
  4   Carrots                25.45     200       15
  5   Onions                 30.00     200       20
  6   Green Bell Pepers      45.00     100        3
  7   Red Bell Peppers       45.00     100        3
Which item # do you want to edit (-1 to quit): 1

1. Description
2. Price
3. Quantity In Stock
4. Quantity Sold
5. Done
  Enter choice: 3
Enter new quantity in stock: 150

ITEM#    DESCRIPTION        PRICE   #INSTOCK   #SOLD
----------------------------------------------------
  1   Johnathon Apples       65.75     150        2
  2   Green Beans            50.25     150       10
  3   Peas                   31.00     150        5
  4   Carrots                25.45     200       15
  5   Onions                 30.00     200       20
  6   Green Bell Pepers      45.00     100        3
  7   Red Bell Peppers       45.00     100        3

1. Description
2. Price
3. Quantity In Stock
4. Quantity Sold
5. Done
  Enter choice: 5

ITEM#    DESCRIPTION        PRICE   #INSTOCK   #SOLD
----------------------------------------------------
  1   Johnathon Apples       65.75     150        2
  2   Green Beans            50.25     150       10
  3   Peas                   31.00     150        5
  4   Carrots                25.45     200       15
  5   Onions                 30.00     200       20
  6   Green Bell Pepers      45.00     100        3
  7   Red Bell Peppers       45.00     100        3

Do you want to edit another record (y/n)? n



Something to think about.

Andy
I am not sure where to start.

You have gone from a good start with your original code to something that makes no sense.


I pasted that into VS2019, looked at it and then deleted it! I haven't the time nor the inclination to write an epistle re the issues.
Hi Andy thanks for your help, I fixed when I edit the order by adding -1 and it works fine

1
2
3
4
5
6
7
8
9
10
11
        displayInventory();
        cout << "Which item # do you want to edit (-1 to quit): ";
        cin >> itemNo;
        if (itemNo == -1)
            return;
        if (itemNo <= -1 || itemNo > NO_OF_CURRENT)
        {
            cout << "Please enter valid item #" << endl;
            ch = 'y';
            continue;
        }


now
1
2
3
4
5
6
7
8
ITEM#                 DESCRIPTION         PRICE      #INSTOCK         #SOLD
    1                        Andy          1             2             3
    2                                         0             0             0
    3                                         0             0             0
    4                                         0             0             0
    5                                         0             0             0
    6                                         0             0             0
    7                                         0             0             0


can you post the code that you modified from my original code?

thanks for your explanation
Last edited on
cplus thank you for your effort, your last program edit menu didn't show like mine and it doesn't allow to ADD items. Yes sorry If I didn't mention that, It has to edit and save the items and if there is nothing in the dat file, it needs to ADD them


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

   ORCHARD TO TABLE ORDERING SYSTEM

1. Create Empty Inventory
2. Display State of Inventory
3. Edit/Create Inventory
4. Make an Order
5. Create Reorder Report
6. Create Revenue Report
7. Save Current Inventory
8. Quit
Enter your choice: 3
ITEM#   DESCRIPTION           PRICE   #INSTOCK   #SOLD
Which item # do you want to edit (0 to create, -1 to quit): 1
Please enter valid item # 


for createOrderReport();

I need to generate a Re-order report which tells us which stock items we are low in If we have 5 or fewer items in-stock, then the items should appear on the re-order report.

for createRevenueReport()
I need to generate a Revenue report which tells us how much we have made on each of the items that we carry.
Notice that the number of items that we have sold have now shown up on our Inventory report as well as the Revenue report.

I will want to be able to save the Inventory File at the end of the day so that I know how much business I did on that particular day.
For example your inventory.dat file might be saved as inventory_2020-12-01.dat\•Also, this will back up my inventory, just in case I delete it by insisting on doing option 1 more than once.
Last edited on
Hey everyone, please don't keep pasting the same code or long explanations if you have a code paste it otherwise , thank you

If anyone can fix number 3 to save the data as well as:
5. Create Reorder Report
6. Create Revenue Report
7. Save Current Inventory

please paste your code here, I have fixed most issues by searching and trying except the once I mentioned above

I have been asking many times to get help saving the dat file and no one showed me how lol
this doesn't work
1
2
3
4
5
6
7
8
9
10
11
void saveInventory()
{
ofstream outfile;
outfile.open("inventory.dat", ios::binary);
if(!outfile.is_open()){
    cout<<"File openning error."<<endl;
    return;
}
outfile.write((char*)&items, sizeof(items));
outfile.close();
}
Last edited on
Pages: 12