Using if statement to check whether string has value or not (homework)

Here is the actual question,
"Write a program for a bottle vending machine in which you have to insert amount in the machine (take amount as an input from the user). It will ask you then with a choice of hot drinks and cold drinks. If user selects cold drinks then allow him to choose among 5 beverages (Coke, Water, Sprite, Pepsi, mineral water). Else allow him to choose among 4 beverages (Black Tea, Coffee, Green Tea, Cappuccino). Output which beverage they chose, its cost and remaining amount after purchase of that drink. Machine will print “Out of money” if the amount entered by the user is less than the cost of drink he’s purchasing. Price of each drink will be Rs. 60/- (Note: Your program must be menu driven and you should display drink name followed by its price)"

I made the following code for this program. The program works fine. However, there is just one problem. Let's say that I enter "C" to go to Cold Drinks menu but then enters "V", so it will show that I have entered invalid code but it then will also execute the last cout commands of "Invoice". I don't want that to execute and I want the program to stop at that "Invalid code"

(This is what it is giving in output)
https://imgur.com/a/x0UNxyF
https://imgur.com/a/HDuMg7p


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 <string>
using namespace std;

int main()
{
	int a;
	char b, c;
	string z;

	cout << "Enter Amount: ";
	cin >> a;
	cout << "\t\t\tVending Machine Menu"
		<< "\nBeverage \tCode"
		<< "\nCold Drinks\tC"
		<< "\nHot Drink \tD"
		<< "\nEnter Beverage Code: ";
	cin >> b;
	if (b == 'C')
	{
		cout << endl << endl
			<< "Cold Drinks: "
			<< "\nDrink\t\tCode\tCost "
			<< "\nCoke\t\tC\tRs. 60/-"
			<< "\nWater\t\tW\tRs. 60/-"
			<< "\nSprite\t\tS\tRs. 60/-"
			<< "\nPepsi\t\tP\tRs. 60/-"
			<< "\nMinear Water\tM\tRs. 60/-";
		cout << endl << endl << "Enter Drink Code: ";
		cin >> c;
		switch (c)
		{
		case 'C':
			z = "Coke";
			break;
		case 'W':
			z = "Water";
			break;
		case 'S':
			z = "Sprite";
			break;
		case 'P':
			z = "Pepsi";
			break;
		case 'M':
			z = "Mineral Water";
			break;
		default:
			cout << "Invalid code";


		}

	}
	else if (b == 'D')
	{
		cout << endl << endl
			<< "Hot Drinks: "
			<< "\nDrink\t\t\tCode\tCost"
			<< "\nBlack Tea\t\tB\tRs. 60/-"
			<< "\nCoffee\t\t\tC\tRs. 60/-"
			<< "\nGreen Tea\t\tG\tRs. 60/-"
			<< "\nCappuccino\t\tP\tRs. 60/-"
			<< endl << endl;
		cout << "Enter Drink Code: ";
		cin >> c;
		switch (c)
		{
		case 'B':
			z = "Black Tea";
			break;
		case 'C':
			z = "Coffee";
			break;
		case 'G':
			z = "Green Tea";
			break;
		case 'P':
			z = "Cappuccino";
			break;
		default:
			cout << "Invalid code.";
		}
	}
	else
		cout << "Invalid Beverage drink code. ";

	if (a >= 60)
	{
		cout << endl << endl << "\t\t\t\tInvoice" << endl << "Beverage: " << z << endl << "Cost: Rs. 60/-" << endl << "Remaining amount: Rs. " << a - 60 << "/-";
	}
	else
	{
		cout << endl << "You are out of money to buy this item." << endl;
	}
	cout << endl;
	system("pause");

	return 0;
}


So, one solution I came up with, is to use that last if command which includes Invoice messages with every "case" in my switch functions.. But that will make the program very lengthy..

Other solution is to execute the last if command only and only if the string "z" has any value. If it doesn't then it won't execute the if command.. So, this is what I did

1
2
3
4
5
6
7
8
9
10
11
12
 
if (z)
{
if (a >= 60)
	{
		cout << endl << endl << "\t\t\t\tInvoice" << endl << "Beverage: " << z << endl << "Cost: Rs. 60/-" << endl << "Remaining amount: Rs. " << a - 60 << "/-";
	}
	else
	{
		cout << endl << "You are out of money to buy this item." << endl;
	}
}


But now it showed me error, saying my if(z) command is not correct. So, my question is, how can I possibly check if the string variable has any variable or not?
If that's not possible, is there any alternate way to do what I am trying to do? Thank you..
Last edited on
Hello Hassan Ashas,

Your program is doing what it should. The problem is the way the program flows. As you have it it starts at the top and executes each line until it reaches the bottom.

Adding the extra if statement is not the way to fix the program. It is just telling you that the program is wrong.

To answer your question if (z) does not work because it does not evaluate to false or true. Actually it does nothing. What you could use is if (z.size()). The return value of the function is either zero or the number of bytes in the string. The return value of zero will evaluate to false and any number greater than zero will evaluate to true.

As you say
So, one solution I came up with, is to use that last if command which includes Invoice messages with every "case" in my switch functions.. But that will make the program very lengthy..
this might work, but again it is telling you that the program is wrong and I would not even consider that.

A thought I have is the the menus after the main menu should have a choice to cancel what you are doing and return to the main menu. Later you can work on if someone wants to order more than one drink.

One last note: use better names for your variables. "a", "b", "c" and "z" just do not do the job and it makes the code hard to follow.

I will load up the program and see what I can do with it.

Hope that helps,

Andy

Edit:
Last edited on
Andy's points are valuable.

In addition to what he has pointed out, the normal trick I do to handle the scenario "So, one solution I came up with, is to use that last if command which includes Invoice messages with every "case" in my switch functions.. But that will make the program very lengthy.. " is that I will add one more boolean variable to track the invalid 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
33
34
35
36
37
38
39
40
41
bool bIsValid = true;
if (b == 'C')
{
    ...
    switch (c)
    {
    ...
    default:
        cout << "Invalid code.";    
        bIsValid = false;
    }
}
else if (b == 'D')
{
    ...
    switch (c)
    {
    ...
    default:
        cout << "Invalid code.";    
        bIsValid = false;
    }
}
else
{
    cout << "Invalid Beverage drink code. ";
    bIsValid = false;
}

if (bIsValid)
{
    if (a >= 60)
    {
		cout << endl << endl << "\t\t\t\tInvoice" << endl << "Beverage: " << z << endl << "Cost: Rs. 60/-" << endl << "Remaining amount: Rs. " << a - 60 << "/-";
    }
    else
    {
		cout << endl << "You are out of money to buy this item." << endl;
    }
}
...
Last edited on
In my opinion if (z.size()) is a better approach instead of unnecessarily using more variables because z is only assigned when there is a valid input anyway.

And like Handy Andy said, you could use while loops etc and also make it so that the user can exit the program. But what it all comes down to is beautifying the program.

But for all practical purposes, just changing that one if statement would give you a perfectly functioning program. But if you want to do more than just make a functioning program then go ahead and kill it man ^_^
Hello Hassan Ashas,

After working with the program I came up with this idea working with what you started with instead of rewriting the whole program. If you have learned about functions it could be done differently.

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
#include <iostream>
#include <string>
#include <cctype>  // <--- Added. std::tolower() and std::toupper().
#include <limits>  // <--- Added.
#include <chrono>  // <--- Added.
#include <thread>  // <--- Added.

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

int main()
{
	// <--- Ideas I had for better variable names.
	int amount{ 500 };  // <--- Did this for testing. Change the number as you need. Or leave the {}s empty to initialize to zero.
	char beverageType{}, beverage{};
	std::string drinkName{};
	bool cont{ true };  // <--- Added.

	do
	{
		//std::cout << "Enter Amount: ";  // <--- Seems a bit early for this.
		//std::cin >> amount;

		std::cout << "\t\t\tVending Machine Menu"
			<< "\nBeverage \tCode"
			<< "\nCold Drinks\tC"
			<< "\nHot Drink \tD"
			<< "\nEnter Beverage Code: ";
		std::cin >> beverageType;
		beverageType = std::toupper(beverageType);

		if (beverageType == 'C')
		{
			do  // <--- Added.
			{
				std::cout << '\n' << std::endl
					<< "Cold Drinks: "
					<< "\nDrink\t\tCode\tCost "
					<< "\nCoke\t\tC\tRs. 60/-"
					<< "\nWater\t\tW\tRs. 60/-"
					<< "\nSprite\t\tS\tRs. 60/-"
					<< "\nPepsi\t\tP\tRs. 60/-"
					<< "\nMinear Water\tM\tRs. 60/-"
					<< "\nQuit\tQ";
				std::cout << '\n' << std::endl << "Enter Drink Code: ";
				std::cin >> beverage;
				beverage = std::toupper(beverage);

				switch (beverage)
				{
					case 'C':
						drinkName = "Coke";
						break;
					case 'W':
						drinkName = "Water";
						break;
					case 'S':
						drinkName = "Sprite";
						break;
					case 'P':
						drinkName = "Pepsi";
						break;
					case 'M':
						drinkName = "Mineral Water";
						break;
					case 'Q':
						break;
					default:
						std::cout << "Invalid code";
						std::this_thread::sleep_for(std::chrono::seconds(3));  // Requires header files "chrono" and "thread". This reeplaces the "system("pause")".
				}
			} while (beverage != 'C' && beverage != 'W' && beverage != 'S' && beverage != 'P' && beverage != 'M' && beverage != 'Q');

			if (beverage != 'Q')  // <--- Added.
				cont = false;     // <--- Added.
		}
		else if (beverageType == 'D')
		{
			std::cout << '\n' << std::endl
				<< "Hot Drinks: "
				<< "\nDrink\t\t\tCode\tCost"
				<< "\nBlack Tea\t\tB\tRs. 60/-"
				<< "\nCoffee\t\t\tC\tRs. 60/-"
				<< "\nGreen Tea\t\tG\tRs. 60/-"
				<< "\nCappuccino\t\tP\tRs. 60/-"
				<< '\n' << std::endl;
			std::cout << "Enter Drink Code: ";
			std::cin >> beverage;
			beverage = std::toupper(beverage);

			switch (beverage)
			{
				case 'B':
					drinkName = "Black Tea";
					break;
				case 'C':
					drinkName = "Coffee";
					break;
				case 'G':
					drinkName = "Green Tea";
					break;
				case 'P':
					drinkName = "Cappuccino";
					break;
				default:
					std::cout << "Invalid code.";
					break;
			}
		}
		else
			std::cout << "Invalid Beverage drink code. ";

	} while (cont);  // <--- Could be reworked to loose the "cont" variable.

	std::cout << std::endl;

	if (amount >= 60)
		std::cout << '\n' << "\t\t\t\tInvoice\n" << "Beverage: " << drinkName << '\n' << "Cost: Rs. 60/-\n" << "Remaining amount: Rs. " << amount - 60 << "/-" << std::endl;
	else
		std::cout << "\nYou are out of money to buy this item." << std::endl;
	
        // <--- Used mostly for testing in Debug mode. Removed if compiled for release.
	// <--- Used to keep the console window open in Visual Studio Debug mode.
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed.
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue";
	std::cin.get();

	//system("pause");

	return 0;  // <--- Not really necessary, but good form and a good break point in the IDE.
}

I did not change the else if section yet, but it should have the same format as the if section. This way until you make a valid drink choice it stays in a loop instead of ending the program. Once a valid drink choice is made the do/while loops end and the invoice part is executed.

Doing it this way does set you up for making multiple drink choices in the future.

At the end of the program you will see that I put a comment on system("pause");. The lines above it are a replacement. Maybe not the best, but it works. The comments are there to let you know how it works. They can be deleted if necessary.

It is best not to use "system" anything as it could leave the program open to attack and it limits your program to Windows operating systems. If your use is limited to personal or school use continue to use it. And in that case "system("cls") would be useful or I do use a function to clear the screen if you are interested, but again it is limited to Windows.

I did allow an exit back to the main menu, but not from the program. That is your choice. Easily adjusted. You do not have to put an exit choice in the main menu, but you could code for it and have an exit if you need one.

Please notice my use of the "\n" in the "cout" statements. This breaks up the output and makes it more readable. And along with well placed statements to clear the screen it looks much nicer.

The last if statement:
First for a single line the {}s are not needed.

Second you could move lines 116 - 119 inside the outer do/while loop and comment out or remove lines 73 and 74 then change the while condition of the outer while loop to } while (true); and the program will always continue to run.

See what you think and if it does what you want. If I think of anything else I will let you know. Any questions let me know.

Hope that helps,

Andy
Topic archived. No new replies allowed.