do while loop invalid user inputs...

So I am having an issue getting a do while loop to only loop for invalid inputs, and end execution if any of the if statements within the loop are true. Depending on how I setup my if statements the loop either keeps looping the else statement or the way it is setup now it just skips the else statement all together. The main goal for the program right now is to have to user enter a string based on a question and then use that string to access other information, but if it is invalid i need to have them correct it. Keep in my mind I have been programming for a total of 3 months now(beginner). I've searched the best I could. Thanks in advance for any help.

Here is the program so far...

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

using namespace std;  //introduces namespace std needed to use cout and cin

void lowercase(string&);


int main()
{
	cout << "This program is designed to allow the user to create a table of unit conversions. First you will be given many choices of starting units and ending units.\n" 
	"Then you will be asked to enter the starting dimension(length, mass or time) and a corresponding initial unit and final unit to convert to. Next you will enter the starting value, ending value\n"
	"and the amount you would like to increment. Also, the program will ask for the number of digits after the decimal point for the starting unit and ending unit. After this\n"
	"occurs the table will increment the starting value to the ending value and convert all values from starting unit to ending unit. These values will be displayed in a table.\n";
	
	char continueLoop = 'Y';
	do
	{
	string DIM,invalid,start,end;
	bool userinput;
	
	do
	{
	cout << "\nEnter the dimension of choice(length, mass or time): ";
	getline(cin, DIM);
	lowercase(DIM);
	if(DIM == "length")
	{
		userinput = false;
	}
	else if(DIM == "mass")
	{
		userinput = false;
	}
	else if(DIM == "time")
	{
		userinput = false;
	}
	else
	{
		cout << "\nINVALID ENTRY - RESTARTING\n";
		userinput = true;
	}
	
	}while(userinput);
	
	do
	{
	if(DIM == "length"){
	{
	cout << "\nEnter the unit of choice(meters,feet,centimeters or inches): ";
	getline(cin, start);
	lowercase(start);
	}
	if(start == "meters" || start == "meter" || start == "m")
		userinput = false;
	else if(start == "feet" || start == "ft" || start == "foot")
		userinput = false;
	else if(start == "centimeter" || start == "centimeters" || start == "cm")
		userinput = false;
	else if(start == "inch" || start == "inches" || start == "in")
		userinput = false;
	else
	{
		cout << "\nINVALID ENTRY - RESTARTING\n";
		userinput = true;
	}
	}
	}while(userinput);

cout << "Enter Y to restart the program and N to quit: \n";
	cin >> continueLoop;
	}while(continueLoop == 'Y'); 
	return 0;
}
void lowercase(string& DIM)
{
	for(int i=0; i<DIM.length();i++)
	{
		DIM[i] = tolower(DIM[i]);
 	}
}


This is the second do while loop, the one I am having the issue with right now...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
do
	{
	if(DIM == "length"){
	{
	cout << "\nEnter the unit of choice(meters,feet,centimeters or inches): ";
	getline(cin, start);
	lowercase(start);
	}
	if(start == "meters" || start == "meter" || start == "m")
		userinput = false;
	else if(start == "feet" || start == "ft" || start == "foot")
		userinput = false;
	else if(start == "centimeter" || start == "centimeters" || start == "cm")
		userinput = false;
	else if(start == "inch" || start == "inches" || start == "in")
		userinput = false;
	else
	{
		cout << "\nINVALID ENTRY - RESTARTING\n";
		userinput = true;
	}
	}
	}while(userinput);
Last edited on
Hello Dustin792,


PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button, but you may still to indent your code.

You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.



When I put your code in VS2017 it appeared to run correctly, so I am having a hard time understanding your problem.

I would say that it is not the best way to go about this, but it does work. I will have to work on that tomorrow.

Think about this. You are asking the user to type in a word to match. For someone like me who can not spell or type that is asking a lot. Consider reworking the input to be a single character or a number.

The variable "DIM" makes me think that this is defined as a constant variable that can not be changed. Generally lower case letters are used to start a regular variable along with "camelCase" or the use of the underscore to separate words. Variable names in all upper case letters tend to be used for variables defined as constant variables.

I did a little work on the program and came up 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
#include <cctype>  // <--- Added. For "std::tolower()" and "std::toupper()".
#include <iostream>
#include <string>

using namespace std; //introduces namespace std needed to use cout and cin. And many other variables ans functions that will cause a problem.

void lowercase(string&);


int main()
{
	cout <<
		"This program is designed to allow the user to create a table of unit conversions.\nFirst you will be given many choices of starting units and ending units.\n\n"

		"Then you will be asked to enter the starting dimension(length, mass or time) and a corresponding\ninitial unit and final unit to convert to.\n\n"

		"Next you will enter the starting value, ending value and the amount you would like to increment.\n\n"
		
		"Also, the program will ask for the number of digits after the decimal point for the starting unit and ending unit.\n\n"

		"After this occurs the table will increment the starting value to the ending value and convert all values\n"
		"from starting unit to ending unit. These values will be displayed in a table.\n";

Most of it was with the "cout" statement. Give it a run and see what you think.

Andy
Hello Andy,

Thanks for the response, the problem is I am under constraints and need to use strings. That's why I created the lowercase() function so I can narrow down the amount of strings to check. Also that's where my problems comes into play I need to allow the user to correct their incorrect input to match the string. I need to use a loop to check the input and loop again if it is an incorrect input, I'm just not sure how to make this loop work...I hope this helps your understanding. Let me know if I can clarify.
Hello Dustin792,

After I posted my response I noticed you figured out code tags. The second link is worth reading a time or two to understand the extras that you can use with the code tag and the quote tag.

Having a chance to run your program the problem is not with the inner do/while loops, but with this:
1
2
cout << "\n\nEnter Y to restart the program and N to quit: ";
cin >> continueLoop;

First you need to understand the difference between formatted and unformatted input.

The "std::getline()" is unformatted input. It will extract everything up to and including the "\n" at the end, but it discards the "\n" leaving the input buffer empty. Best used when you have a space in your input that you want to keep.

Using something like: std::cin >> dim;is formatted input and will extract from the input buffer anything up to a white space or "\n" whichever comes first, but it leaves the "\n" in the input buffer.

When you reach: cin >> continueLoop; this leaves the "\n" in the input buffer and your next call to "std::getline()" extracts this into "dim" not waiting for any user input making it look like it is invalid input.

There are 2 ways, maybe more, to fix this.

First:
1
2
3
cout << "\n\nEnter Y to restart the program and N to quit: ";
cin >> continueLoop;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>. 

The first parameter just creates a very large number and as I understand it considered the most portable way to do this that can be used by any set of header files and compiler. Truth be told a large number like 1000 or more will work.

The other option is to change your "std::getlin()"s to formatted input: std::cin >> dim; and std::cin >> start;.

I have tried both methods and they work giving an output of:

This program is designed to allow the user to create a table of unit conversions.
First you will be given many choices of starting units and ending units.

Then you will be asked to enter the starting dimension(length, mass or time) and a corresponding
initial unit and final unit to convert to.

Next you will enter the starting value, ending value and the amount you would like to increment.

Also, the program will ask for the number of digits after the decimal point for the starting unit and ending unit.

After this occurs the table will increment the starting value to the ending value and convert all values
from starting unit to ending unit. These values will be displayed in a table.

Enter the dimension of choice(length, mass or time): len

    INVALID ENTRY - RESTARTING

Enter the dimension of choice(length, mass or time): ma

    INVALID ENTRY - RESTARTING

Enter the dimension of choice(length, mass or time): tim

    INVALID ENTRY - RESTARTING

Enter the dimension of choice(length, mass or time): length

Enter the unit of choice(meters,feet,centimeters or inches): mt

    INVALID ENTRY - RESTARTING

Enter the unit of choice(meters,feet,centimeters or inches): feet


Enter Y to restart the program and N to quit: y

Enter the dimension of choice(length, mass or time):



I also made a change:
1
2
3
4
5
6
7
8
9
if (dim == "length" || dim == "mass" || dim == "time")
{
	userinput = false;
}
else
{
	cout << "\n    INVALID ENTRY - RESTARTING\n";
	userinput = true;
}

It gets a bit long, but you could write the next if statement as:
1
2
3
4
5
6
7
8
9
10
	if (start == "meters" || start == "meter" || start == "m"
	|| start == "feet" || start == "ft" || start == "foot"
	|| start == "centimeter" || start == "centimeters" || start == "cm"
	|| start == "inch" || start == "inches" || start == "in")
	userinput = false;
else
{
	cout << "\n    INVALID ENTRY - RESTARTING\n";
	userinput = true;
}

Just a thought.

I believe that using the "ignore()" or changing the "std::getline()" to formatted should solve your problem

Andy
Hello Dustin792,

Sorry a little thing I missed: } while (std::toupper(continueLoop) == 'Y');. Otherwise you would need an (||) to check for both cases. If not a lower case "y" would end the program.

Andy
Hello Handy Andy,

I am grateful for you help. I was able to use the trimmed code you provided with cin.ignore() to keep the flow of the code going. Also, thanks a ton for the tips to make the code more efficient. I am going to complete some more code, if everything still checks out I will mark this topic solved. Thanks again.
Hello Dustin792,

You are welcome.

It is usually easier to use what you have than to make extra work with code that is kind of redundant.

Andy
Topic archived. No new replies allowed.