vending machine using strusctures

hello so my coding prompt is

"Write a program that simulates a soft drink machine. The program should use a structure named Drink that contains the following information:
•The drink name
•The drink cost
•The number of drinks in the machine
The program should then create an array of 5 Drink structures. The elements should be initialized with the following data
Drink Name Cost Number in Machine
Cola $0.65 20
Root Beer $0.70 20
Grape Soda $0.75 20
Lemon-Lime $0.85 20
Water $0.90 20

whenever a drink is purchased the number of that drink in the machine is supposed to change. at the end of the program, the total earnings, as well as the amount of each drink sold, is supposed to print out.

I cannot use classes for this assignment only structures.

The problems I'm running into is
1) I am not sure how to have the array print out, instead, I am just using cout for a menu option, therefore The number of specific drinks in the "machine" is not being adjusted.
2) To exit the program you have to enter "6" which is not working either, so im not sure if the total earnings is working either.

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
  #include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cctype>

using namespace std;

struct Drink
{
	string name;
	double price;
	int num;
};
Drink beverage;

int getChoice(Drink m[]);
void transaction(Drink m[], int choice, double &earnings);
const int NUM_DRINKS = 5;


int main()
{
	int choice;
	double earnings = 0.0;
	Drink machine[NUM_DRINKS] = 
	{
	{ "Cola      ", 0.65, 20 },
	{ "Root Beer ", 0.70, 20 },
	{ "Grape Soda", 0.75, 20 },
	{ "Lemon Lime", 0.85, 20 },
	{ "Water     ", 0.90, 20 }
	};

	cout << fixed << setprecision(2) << endl;

	do
	{
		choice = getChoice(machine);
		if (choice != NUM_DRINKS)
		{
			transaction(machine, choice, earnings);
		}
	} 
	while (choice = 6 || choice != NUM_DRINKS);
	
		cout << "Total money earned is: $" << earnings << endl;
	
	return 0;
}

int getChoice(Drink m[])
{
	int choice;
	bool menu = true;

	cout << "Please select a drink or press 6 to exit\n";
	while (menu)
	{
			cout << " 1. Cola        $0.65 \n"
			<< " 2. Root Beer   $0.70 \n"
			<< " 3. Lemon Lime  $0.75 \n"
			<< " 4. Grape Soda  $0.85 \n"
			<< " 5. Cream Soda  $0.90" << endl;
			
		cin >> choice;

		if (choice < 1 || choice > 6)
		{
		cout << "Please make a valid selection" << endl;
		menu = true;
		}
		else if (choice == 6)
		{
			menu = false;
		}
	}
	return choice;
}

void transaction(Drink m[], int choice, double &earnings)
{
	double moneyReceived;
	double change;

	cout << " Please enter an amount no more then a dollar ";
	cin >> moneyReceived;

		if (moneyReceived < 0 || moneyReceived > 1)
		{
			cout << " This vending machine only allows for change and bills up to a dollar and no less than 0 cents ";
		}

		if (moneyReceived < beverage.price)
		{
			cout << "Insufficient funds." << endl;
		}

		if (moneyReceived >= beverage.price)
		{
			cout << "Thank You!! Your drink will be coming right out " << endl;

			change = moneyReceived - m[choice - 1].price;

			cout << "Here is your change " << change << " Thank you come agian " << endl;

			earnings = moneyReceived - change;
		}
}
Hello mercedx,

As I look over the program I can see some problems.

You are good down to line 15. As a global variable this should be avoided. Secondly you never use it properly.

Line 19 is OK. As a constant it can not be changed, so as a global variable it it OK.

Here is a hint: when you define "NUM_DRINKS" set it to 6 not five. When you define the array it will be one more than you need, but in the end you will never use element "0" so it works out. Also the if statement on line 40 will work better.

For line 35 I tend to use this most often:
std::cout << std::fixed << std::showpoint << std::setprecision(2);. The "showpoint" will print ".00" if it occurs other wise it will print nothing. This tends to help with lining up output.

In the do/while loop the while condition: while (choice = 6 || choice != NUM_DRINKS); is a problem. "choice = 6" is setting the value of "choice" to six. Any number greater than zero is considered true, so the lhs of the || is evaluated to true and the rhs is never checked. You should be able to use just choice != NUM_DRINKS and it should work. As long as "NUM_DRINKS" is given a value of 6.

The if statement if (choice != NUM_DRINKS) will fail if "choice" is 5. Not what you want. It does work if "NUM_DRINKS" is 6.

Watch the indenting on line 47. It is not needed.

In the "getChoice" function the concept is good, but I do not believe it will work the way you want. I tend to use a do/while loop in this type of function. This way you will enter the loop at least once and the tend to be less work than a while loop.

In both the "getChoice" and "transaction" functions I would suggest Drink machine[]. Since this creates a local variable to the function you can use the same nmae as you did in "main". It does tend to make things easier to keep track of.

In the "transaction" function.

Your if statements would work better as:
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
if (machine[choice].num)
{
	if (moneyReceived < 0 || moneyReceived > 1)
	{
		cout << " This vending machine only allows for change and bills up to a dollar and no less than 0 cents ";
	}

	if (moneyReceived < beverage.price)
	{
		cout << "Insufficient funds." << endl;
	}

	if (moneyReceived >= beverage.price)
	{
		cout << "Thank You!! Your drink will be coming right out " << endl;

		change = moneyReceived - m[choice - 1].price;

		cout << "Here is your change " << change << " Thank you come agian " << endl;

		earnings = moneyReceived - change;
	}
}
else
{
	 // <--- Error message.
}

Line 1 will check if there is something to sell for that drink choice. If not the else and error message could say something about being sold out.

On line 94 where did "beverage.price" ever receive a usable value?

You have passed the array to the function and need to use it here. Similar to what I did in line 1.
The function is missing one part. You deal with money, but if you have a sale you do not deduct from the quantity of that drink.

There are some things that are more business and sales that your program is handling incorrectly, but that is not a big issue right now,

I will load up the program and give it a test to see if I find anything else.

Hope that helps,

Andy
Hello mercedx,

1) I am not sure how to have the array print out, instead, I am just using cout for a menu option

The quick answer is tell it to. You pass the array to the "getChoice" function, but never use it. You could do something like 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
26
27
int getChoice(Drink machine[])
{
	int choice;
	
	std::cout << std::left;  // <--- Added. You may not need this line.
	
	do
	{
		cout << "\n Please select a drink or press 6 to exit\n";

		for (size_t lc = 1; lc < NUM_DRINKS; lc++)
		{
			std::cout << ' ' << lc << ". " << std::setw(13) << machine[lc].name << '$' << machine[lc].price << '\n';
		}

		std::cout << " Enter selection: ";  // <--- Added.

		cin >> choice;

		if (choice < 1 || choice > 6)
		{
			cout << "\n  Please make a valid selection" << endl;
		}
	} while (choice < 1 || choice > 6);

	return choice;
}

On line 13 notice how I used the array to get the name and price.

therefore The number of specific drinks in the "machine" is not being adjusted.

For this part of problem one this would be taken care of in the "transaction" function.

2) To exit the program you have to enter "6" which is not working either, so im not sure if the total earnings is working either.

As I mentioned earlier this has to do with line 40. When I changed "NUM_DRINKS" to 6 it works the way it should.

Now that I have had a chance to work with the program I have found:

The header files "algorithm" and "cctype" are never used in the program and are not needed. Removing them will make the program smaller. And will have no adverse affect on the program.

line 7 is best not to use. There have been many posts about this in the "beginners Forum". Just do a search. And there may even be an article or two in the "Articles Forum". You can try a search there also. This is always a good read http://www.lonecpluspluscoder.com/2012/09/22/i-dont-want-to-see-another-using-namespace-xxx-in-a-header-file-ever-again/

I rearranged the beginning of the program. It now looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;  // <--- Best not to use.

const int NUM_DRINKS = 6;
constexpr size_t MAXDRINKS{ 20 };

struct Drink
{
	string name;
	double price;
	int quantity;
	double qtySold{};
	double amtReceived{};
};

int getChoice(const Drink machine[]);
void transaction(Drink (&machine)[NUM_DRINKS], int choice, double &totalMoneyReceived);

I moved the constant variables to the top so the entire file can use them.

On line 19 I made the array constant because you just need to use the array and there is no reason to make any changes here.

On line 20 I passed the array by reference. Passing the array by value the array will degrade to a pointer and the only part is is seen is the first element of the array. Passing by reference during testing has the advantage of being able to see the whole array. Passing the array by reference is not necessary and you can keep what you have, its just a help when developing the program.

In the struct the two variables I added the "qtySold" can be achieved through simple math, but "amountReceived" could be very useful in the final output.

In "main" the array machine now looks like this:
1
2
3
4
5
6
7
8
9
	Drink machine[NUM_DRINKS] =
	{
	{ "Unused", 0.0, 0 },
	{ "Cola", 0.65, MAXDRINKS },
	{ "Root Beer ", 0.70, MAXDRINKS },
	{ "Grape Soda", 0.75, MAXDRINKS },
	{ "Lemon Lime", 0.85, MAXDRINKS },
	{ "Water", 0.90, MAXDRINKS }
	};

Doing this line 3 becomes a place holder for element zero which is not used. This way when you receive a value for "choice" it will become the correct subscript to the array.

After defining the array I changed the next line to cout << fixed << std::showpoint << setprecision(2);. I found that the "std::endl" was giving an extra blank line at the beginning of the output.

After the do/while loop I changed the next line to
cout << "\n\n Total money received is: $" << totalMoneyReceived << '\n' << endl;. Notice the use of the "\n"s and that "totalMoneyReceived" is more descriptive than "earnings" as you have not earned anything yet just received money. You may be stuck with the variable name "earnings" and if that is what you have to use then use it.

After this I created a for loop that displays this.

  Total money received is: $2.80

 Cola         sold 2 for $0.65 each for a total of $1.30
 Root Beer    sold 0 for $0.70 each for a total of $0.00
 Grape Soda   sold 2 for $0.75 each for a total of $1.50
 Lemon Lime   sold 0 for $0.85 each for a total of $0.00
 Water        sold 0 for $0.90 each for a total of $0.00


This my be more than what you want, but sounded good at the time.

In the function "transaction" I added bool good{ false }; and a do/while loop. The loop will keep repeating if you enter something larger than $1.00 or if you enter less than the amount needed. It gives the opportunity to correct something that is wrong without going back to the main menu.

At some point you may consider a way to cancel the transaction and return to the main menu.

Like I showed you earlier I wrapped all the if statements inside an if statement. Then the second and third if statements I had to change to "else if" to make it work.

In the two "else if" statement you need to use machine[choice].price to refer to the proper element of the array. Also the same concept is used to change information in the struct based on the correct subscript which comes from the value of "choice".

Inside the last "else if" statement is where you work with the array to make changes. If you are not sure how to do this, show me the code of what you think and we can work from there.

The last line of the last "else if" statement is good = true; to allow you to exit the do/while loop and return to "main" to make another selection.

Remember in this program for loops start at "1" and not "0" (zero) to work with array properly. This will save you from doing choice - 1 to access the array.

Hope that helps,

Andy
Wow! Thank you so much for all of this information. I will be able to get some work done later and try everything you have suggested out. Thank you so much, will update when I get to coding. :)
Hello mercedx,

You are welcome. Have fun.

Andy
Hey Andy, so here is what I have so far, I actually can't test it because I am getting this error message and I can't seem to figure out what it means.

"Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "int __cdecl getChoice(struct Drink const * const)" (?getChoice@@YAHQEBUDrink@@@Z) referenced in function main assignment 7 project 1 D:\cs1\assignment 7\assignment 7 project 1\assignment 7 project 1\assignemnt 7 project 1.obj 1
"

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
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

const int NUM_DRINKS = 6;
constexpr size_t MAX_DRINKS{ 20 };


struct Drink
{
	string name;
	double price;
	int num;
	double amtReceived{};
};
Drink beverage;

int getChoice(const Drink machine[]);
void transaction(Drink (&machine)[NUM_DRINKS], int choice, double &totalMoney);



int main()
{
	int choice;
	double totalMoney = 0.0;
	Drink machine[NUM_DRINKS] = 
	{
	{ "Unused    ", 0.0, 0},
	{ "Cola      ", 0.65, MAX_DRINKS },
	{ "Root Beer ", 0.70, MAX_DRINKS },
	{ "Grape Soda", 0.75, MAX_DRINKS },
	{ "Lemon Lime", 0.85, MAX_DRINKS },
	{ "Water     ", 0.90, MAX_DRINKS }
	};

	cout << fixed << showpoint << setprecision(2) << endl;

	do
	{
		choice = getChoice(machine);
		if (choice != NUM_DRINKS)
		{
			transaction(machine, choice, totalMoney);
		}
	} 
	while (choice != NUM_DRINKS);
	
	cout << "\n\n Total money earned is: $" << totalMoney << '\n' << endl;

	for (int i = 1; i < NUM_DRINKS; i++)
	{
		cout << machine[i].name << setw(13) << machine[i].num << endl;
	}
	
	return 0;
}

int getChoice(Drink machine[])
{
	int choice;

	do
	{
		cout << "Please select a drink or press 6 to exit\n";

		for (size_t lc = 1; lc < NUM_DRINKS; lc++)
		{
			cout << ' ' << lc << setw(13) << machine[lc].name << '$' << machine[lc].price << ' ' << machine[lc].num << endl;
		}
		cout << "Enter selection: ";
		cin >> choice;

		if (choice < 1 || choice > 6)
		{
			cout << "\n Please make a valid selection" << endl;
		}
	} while (choice < 1 || choice > 6);

	return choice;
}

void transaction(Drink(&machine)[NUM_DRINKS], int choice, double &totalMoney)
{
	double moneyReceived;
	double change;
	bool good = false;

	cout << " Please enter an amount no more then a dollar ";
	cin >> moneyReceived;

	do
	{
		if (machine[choice].num)
		{
			if (moneyReceived < 0 || moneyReceived > 1)
			{
				cout << " This vending machine only allows for change and bills up to a dollar and no less than 0 cents ";
			}

			else if (moneyReceived < machine[choice].price)
			{
				cout << "Insufficient funds." << endl;
			}

			else if (moneyReceived >= machine[choice].price)
			{
				cout << "Thank You!! Your drink will be coming right out " << endl;

				change = moneyReceived - machine[choice].price;

				cout << "Here is your change " << change << " Thank you come agian " << endl;

				totalMoney = moneyReceived - change;

				good = true;
			}
		}
		else
		{
			cout << "That drink is unavailable" << endl;
		}
	} while (machine[choice].num >= 1);
}
Last edited on
Hello mercedx,

Just woke up, so I have not had a chance to look over the whole program yet.

As for the error you have:
1
2
3
int getChoice(const Drink machine[]);  // <--- Prototype.

int getChoice(Drink machine[])  //<--- Function definition. 

These two need to match from the return value, the function name (spelled the same way with the same letters) and the parameter list. In this case the parameter list is different.

In this case the error message is saying I see the prototype, but can not find a matching function. The reverse of that is that the function follows "main" and the compiler does not know about it because it would be compiled after "main" and by then it is to late.

That should take care of your error. Give me a little time to look over the rest of the program.

Hope that helps,

Andy
Hello mercedx,

Changing the function parameters to match the prototype made the error go away.

When the program compiled and ran I found the problem with the "transaction" function. It turned out to be printing the same thing to the screen over and over again. I think it was basicly an endless loop.

The condition on the do/while loop of (machine[choice].num >= 1) is the problem. I do not know what made you think of this, but since the value of "num" never changes it is always be 20 >= 1 which will always evaluate to true.

The reason for the bool variable good is:
1
2
3
do
{
} while(!good);

Since "good" starts as "false" the "!good" becomes "true" until you enter the last "if else" statement where you change "goof" to true causing the while condition to evaluate to "false" and the loop ends.

For what you have line 116 is wrong. Using just the "=" sets "totalMoney" equal to the calculation each time through the function. Not what you want for a running total. What you need here is totalMoney += .... This way you add to what is already in "totalMoney" each time through the function. By the end of the program "totalMoney" will reflect the total amount of money collected for each beverage dispensed.

Also this last "else if" statement is where you need to adjust (or deduct) from the quantity of available drinks. Also you need to adjust the variable "amtReceived" in the struct. This is similar to what you did for "totalMoney"except you are using the struct in the array.

Then you will end the "else if" block with good = true;, as you have, to make the while condition fail ending the loop and allowing the function to return to main for the next selection.

at the end of the program, the total earnings, as well as the amount of each drink sold, is supposed to print out.

The for loop at the end of main is the right concept, but not what the directions are asking for.

Your use of cout << machine[i].name << setw(13) << machine[i].num << endl; will always print "20" because the variable never changes in the "transaction" function. Any how what this should be is
MAX_DRINKS - machine[i].num to print what was actually sold. And now what is left in the machine.

Hope that helps,

Andy
ok so i was able to adjust the total quantity of available drinks inside the struct. Question i do have is what exactly is the variable "amtReceived" being used for if i already have "totalMoney"?

another problem i am running into is, i wanted to restrict character entry in the menu when selecting a drink, here is the code

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
int getChoice(const Drink machine[])
{
	int choice;

	do
	{
		cout << "Please select a drink or press 6 to exit\n";

		for (size_t c = 1; c < NUM_DRINKS; c++)
		{
			cout << ' ' << c << setw(13) << machine[c].name << setw(14) << '$' << machine[c].price << setw(15) << "QTY: " << machine[c].num << endl;
		}
		cout << "Enter selection: ";
		cin >> choice;
		cout << endl;

		while (!(cin >> choice)) <-- loop to not allow character entry
		{
			cin.clear();
			cin.ignore(100, '\n');
			cin.sync();
			cout << "Invalid entry, please make another selection: " << endl;
		}

		if (choice < 1 || choice > 6)
		{
			cout << "Please make a valid selection" << endl;
		}
	} while (choice < 1 || choice > 6);

	return choice;
}


What's happening though is even when i put in a valid entry like 1, it makes me enter it twice. Did i do something incorrect with the while loop i have?

thank you :)
Last edited on
Hello mercedx,

Did i do something incorrect with the while loop i have?

Yes. Right idea wrong approach.

What you want is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while (!std::cin)  // < --loop to not allow character entry
{
	cout << "\n    Invalid entry, Please use numbers 1 - 6: " << endl;
	
	std::cin.clear();
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

	std::cout << " Enter selection: ";
	std::cin >> choice;
}

if (choice < 1 || choice > 6)
{
	std::cout << "\n Invalid Choice. Please make a valid selection" << endl;
}

On line 1 you need to start the comment with two forward slashes "//".

The reason you have to enter twice is the while condition. while (!(cin >> choice)). The while condition is asking for input a second time. All you need to check for is if "cin" has failed while (!std::cin).

Line 6 is most often written this way. It makes the code more portable since different computer could have a different size for the input buffer. This also works for file streams by changing "cin" to the name of the file stream. The way this works is that it will ignore the numbers of characters specified by the first number or a "\n" whichever comes first. The larger the number the better chance you have of clearing the buffer.

The last part prompts for a new entry and if it is a number the while loop ends and you goto the if statement.

Another option is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while (!std::cin || (choice < 1 || choice > 6))
{
	if (!std::cin)
	{
		std::cout << "\n    Invalid entry, Please use numbers 1 - 6: " << endl;

		std::cin.clear();
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

	}
	else
		std::cout << "\n    Invalid Choice. Please make a valid selection" << endl;

	std::cout << " Enter selection: ";
	std::cin >> choice;
}

Either method will work.

"amtReceived" is like "totalMoney", but only for each beverage. It is a way of keeping track of how much money was collected for each drink.

I may have put some extra in this output to come up with this:

                   Machine Stats
---------------------------------------------------
 Cola                  sold  2 for a total of $1.30
 Root Beer             sold  1 for a total of $0.70
 Grape Soda            sold  1 for a total of $0.75
 Lemon Lime            sold  1 for a total of $0.85
 Water                 sold  1 for a total of $0.90
---------------------------------------------------
 Total money received is                      $4.50


For each beverage the last number showing a dollar amount comes from "amtReceived" which is in each struct of the array. And the last line is the total of each preceding lines.

Is this is something that would work for you I will go over the code I used. Let me know.

Hope that helps,

Andy
Hey Andy, sorry i haven't replied in a little while, I believe I fixed the issue with while loop that was having me enter choice twice, here is what i wrote..

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
int getChoice(const Drink machine[])
{
	int choice;

	do
	{
		cout << "Please select a drink or press 6 to exit\n";

		for (size_t c = 1; c < NUM_DRINKS; c++)
		{
			cout << ' ' << c << setw(13) << machine[c].name << setw(14) << '$' << machine[c].price << setw(15) << "QTY: " << machine[c].num << endl;
		}
		cout << "Enter selection: ";
		cin >> choice;
		cout << endl;

		if(cin.fail())
		{
			cin.clear();
			cin.ignore(100, '\n');
			cin.sync();
			cout << "Invalid entry, please make another selection: ";
			cin >> choice;
		}
		
		if (choice < 1 || choice > 6)
		{
			cout << "Please make a valid selection" << endl;
		}
	} while (choice < 1 || choice > 6);

	return choice;
}



for the "amtReceived" variable, I dont actually need that as part of the project...BUT if i did would i just have to include "amtReceived" in the function prototype and have it pass by reference into the function? almost exactly like I did for "totalMoney"?

thank you
Hello mercedx,

Line 11. The setW(13) act on the "machine[c].name", but the "setw(14)" is acting on the "$" and not the "machine[c].price". The end result is that the "$" will be put in a block of 14 characters padded with spaces for the unused portion. As I went through the rest of the line is makes a mess of the menu. A little thought here can make a big difference.

Using this code:
1
2
cout << ' ' << /*std::left <<*/  lc << ". " << setw(13) << machine[lc].name << '$' << /*std::right <<*/ machine[lc].price
	<< ' ' << std::setw(2) << machine[lc].num << " left" << endl;

I put a comment on the "left" and "right" as you may not need them. Try it without and see what you get. If you need to, uncomment the "left" and "right" and see if it changes the output.

It produces a menu of:

 Please select a drink or press 6 to exit
 1. Cola         $0.65 20 left
 2. Root Beer    $0.70 20 left
 3. Grape Soda   $0.75 20 left
 4. Lemon Lime   $0.85 20 left
 5. Water        $0.90 20 left
 Enter selection:


I may even be inclined to put a blank line between lines 1 and 2.

Another thing you do not have to do is:
1
2
3
4
5
6
7
8
9
Drink machine[NUM_DRINKS] =
{
{ "Unused", 0.0, 0},
{ "Cola      ", 0.65, MAX_DRINKS },
{ "Root Beer ", 0.70, MAX_DRINKS },
{ "Grape Soda", 0.75, MAX_DRINKS },
{ "Lemon Lime", 0.85, MAX_DRINKS },
{ "Water     ", 0.90, MAX_DRINKS }
};

The extra spaces after "Cola", "Root Beer" and "Water" are not needed. The "setw" will take care of the difference of the lengths.

For line 17. All you need is "(!std::cin)". Using "(std::cin.fail())" may work, but it is a narrow focus. Only one of the state bits. Should the "fail" bit not be set in favor of something else the if statement will be bypassed. By using "!std::cin" you are checking the "good" bit which is changed when any of the other state bits are set.

std::cin.ignore(100, '\n'); and std::cin.sync(); are about the same. Use one or the other, but not both and
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>. is a better choice even though what you have works.

When looking into "std::cin.sync();" I found this https://stackoverflow.com/questions/10585392/the-difference-between-cin-ignore-and-cin-sync It is worth a read.

I tested the function and it does work, but you could combine both is statements by using one while loop as I did in http://www.cplusplus.com/forum/beginner/254178/#msg1117053 with the second bit of code.

for the "amtReceived" variable, I dont actually need that as part of the project...BUT if i did would i just have to include "amtReceived" in the function prototype and have it pass by reference into the function? almost exactly like I did for "totalMoney"?

No. The variable "amount"Received" is part of the struct that you pass to the functions in the array. You can access it like machine[choice].amountReceived. Since you are working with only one array element this stores the amount received for each beverage in the struct of the given element of the array. This may not be required, but it can be useful.

When I was in school, way back when, I found the going beyond what was required made a big difference in how I was looked at and treated in the class. Even little things like how the output looks help. It shows you are willing to do more than just what is required. Do not be afraid to put a little extra into the program to dress it up. Whether it is in the code or in the output from the code. In the end it all helps.

Hope that helps,

Andy
Hello mercedx,

My turn. Sorry for the delay I have had a time of staying awake long enough to work much on this.

Thursday I worked out the problems with the new function and this is what I came up with:
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
int getChoice(const Drink machine[])
{
	int choice;

	do
	{
		cout << "\n     Please select a drink or press 6 to exit\n\n";

		for (size_t c = 1; c < NUM_DRINKS; c++)
		{
			cout << "  " << c << ". " << std::left << setw(13) << machine[c].name << '$' << std::right
				<< setw(5) << machine[c].price << "  QTY: " << setw(2) << machine[c].num << endl;
		}

		cout << "  Enter selection: ";
		cin >> choice;
		cout << endl;

		if (!std::cin)
		{
			cin.clear();
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
			cout << "    Invalid entry, please make another selection:\n" << std::endl;
			//cin >> choice; // <--- Stops here for extra input. Not needed. Does work in a while loop.
		}
		else if (choice < 1 || choice > 6)
		{
			cout << "    Not a valid choice.\n\n    Please make a valid selection (1 - 6).\n" << endl;
		}
	} while (choice < 1 || choice > 6);

	return choice;
}

The changes I made are in bold.

For line 11 compare my "cout" statement to what you have and notice where the "setw"s are placed. Put a comment on your "cout" and insert mine. This way you can flip between the two and see the difference in the output.

Hope that helps,

Andy
I keep missing your replies Andy. What you said about amountreceived I do understand, I will ask my professor if he is ok with it in there because sometimes he doesn’t want anything else but what his example runs show us.

I see the issues with my setw() situation and will correct it, thank you for catching that.

As soon as I get to my computer I will run what you have in hold with my code commented out. The only issue I may run into is my professor doesn’t like to see us use some libraries/code that we haven’t learned yet, like <limits> for instance. I will do some reading about it so I know what it actually does rather than just put it in.

As always thanks for your time and effort Andy :)
Hello mercedx,

Sorry for the delay. I lost track of this when I had to shut down and restart the computer.

Using "amountReceived" can be left out if you do not need it, but using it shows that you took the initiative do do something that was not asked for. The value of "amountReecived" can be used at the end of the program to see how well each beverage preformed. This can be used to determine if one beverage should be increased in quantity or if another should be taken out because it does not sell.

I understand that some professors do not want you to learn what you need to unless it is part of the class. This does not mean it is the right way to teach. Learning C++ or any language is not just book work or class room instruction, but whatever you can learn wherever it can be found.

I have found this forum along with "Stack Overflow" ( https://stackoverflow.com/ ) to be a great resource.

Just because <limits> has not been taught in class yet does not mean that you should not use it. Someday it will likely be in every program that you write and in the future you will likely be using more of it than I do right now.

Do what you need to do for the class. You can always save this program to a different file for future reference and then paste it into a new "main" file, or whatever you like to call it, and remove what you do not need.

Hope that helps,

Andy
Turned the project in and got 100% on it. I have started adding new things to the code in my own spare time, enjoying the end of the semester for now haha.

thanks again for all your help andy :D
Hello mercedx,

Good job. Glad to hear it.

Andy
Topic archived. No new replies allowed.