user input causes console to flood

So i've been messing around with c++ for a bit now, I noticed that if I have an input (whether it be cin, getline, or scanf) within a while loop, if the user enters something 'bad' it causes the console to flood with my original output. In this case, I created a simple reservation system whereas the user can enter their name, but if they enter their full name then the program breaks and it floods console with my original output (so I have to make two separate cin's for first and last name)

tl;dr I'm trying to allow the user to input a string with whitespaces using one input, rather than two. In my case, if the user does that, the program console gets flooded with my original cout. I can get it to work with two inputs (the 2nd one is commented out) but with one it breaks.

e.g -> user inputs 'john smith' as name, console flooded with '1. Print All Reservers, 2. Add a reservation, 3. Remove a reservation'
but if i have two puts, they can input 'john smith'. I need one input to be put into one string, rather than creating two inputs

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
// reserv.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "iostream";
#include <vector>;
#include <iomanip>;
#include <string>;
using namespace std;

int main()
{
	int sel;
	int tables = 5;
	int seats = 20;
	int resSeat;
	string name;
	string r;
	vector <string> data;
	cout << "Welcome to reservation system, what would you like to do? ... " << endl;

	bool runner = true;
	while (runner) {
		cout << "1. Print All Reservers, 2. Add a reservation, 3. Remove a reservation ... \n";
		cin >> sel;
		switch (sel) {
		case 1: 
			cout << "Reservations: " << data.size()  << "\nAvailable Tables: " << tables << "\nAvailable Seats: " << seats << endl;

			for (unsigned int i = 0; i < data.size(); i++)
			cout << data[i] << endl; // print reservation data
 			break;
		case 2:
			if(tables>0){  // tables available must be >0
			cout << "Enter your full name : \n";
			cin >> r; // use enters name

		//	cout << "Enter last name: \n";   // full name entry breaks, if i have this as a 2nd input it works fine (user must enter first/last name seperately though)
	    //  cin >> name;
			name = r + " " + name;
			bool wrong = true;
			do  { 
			cout << "# Of Seats (max 4): " << endl;
			cin >> resSeat; // reserved seats
			if (resSeat <= 4) { // max 4
				wrong = false;
			}
			} while (wrong);
				name = to_string(data.size() + 1) + " " + name + " " + r; // add the reservation number to the string (e.g 1st reservation -> 1)
				name = name + "*" + to_string(resSeat); // add seats reserved to string after a *
				tables = tables - 1; 
				seats = seats - resSeat;

				data.push_back(name); //  push into vector
				cout << "Thank you! Reservation has been added\n";
			 
			}
			else {
				cout << "We are fully reserved today.. Sorry :-(\n";
			}
			break;
		case 3: 
			int deal;
			char conf;
			cout << "Enter which reservation to delete .. ";
			cin >> deal;
			deal = deal - 1;
			cout << "To erase: " << data[deal] << " y/n?" << endl;
			cin >> conf;
			if (conf == 'y' || conf == 'Y') {
				tables = tables + 1;
				int ia = data[deal].at(data[deal].find("*") + 1) - '0';
				cout << "Refunded: " << ia << " Seats.." << endl;
				seats = seats + ia;
				data.erase(data.begin() + (deal));

			}
			else {
				cout << "Operation cancelled..";
			}
 			break;

	 
		default: runner = false;
			break;


		}
	}



	system("pause");
    return 0;
}
Last edited on
cin >> name stops at the first space. To read an entire line you should use getline. But this can have problems when you mix it with cin >> x, since that leaves the newline in the buffer so that the next getline returns an empty string.

The best thing is to always read an entire line at a time, even if you are reading an integer or a single character. That way you won't leave any newlines behind.

Maybe 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
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 <vector>
#include <string>
#include <cctype>
using namespace std;

int readInt(int lo, int hi) {
    string line;
    int n;
    while (true) {
        getline(cin, line);
        istringstream iss(line);
        if (iss >> n && n >= lo && n <= hi)
            break;
        cout << "Value must be from " << lo << " to " << hi << '\n';
    }
    return n;
}

char readYN() {
    string line;
    char ch;
    while (true) {
        getline(cin, line);
        istringstream iss(line);
        iss >> ch;
        ch = toupper(ch);
        if (ch == 'Y' || ch == 'N')
            break;
        cout << "You must enter y or n\n";
    }
    return ch;
}

int main() {
    int tables = 5;
    int seats = 20;
    string name;
    vector<string> data;

    cout << "Welcome to reservation system, what would you like to do?\n";

    bool runner = true;
    while (runner) {
            cout << "1. Print reservations, "
                    "2. Add a reservation, "
                    "3. Remove a reservation, "
                    "4. Quit\n";
        int sel = readInt(1, 4);

        switch (sel) {
        case 1:
            cout << "Reservations: "       << data.size()
                 << "\nAvailable Tables: " << tables
                 << "\nAvailable Seats: "  << seats << '\n';
            for (size_t i = 0; i < data.size(); i++)
                cout << i + 1 << ": " << data[i] << '\n';
            break;
        case 2: {
            if (tables == 0) {
                cout << "We are fully reserved today.. Sorry :-(\n";
                break;
            }
            cout << "Enter your full name: ";
            getline(cin, name);
            cout << "# Of Seats (max 4): ";
            int resSeat = readInt(1, 4);
            name += ',' + to_string(resSeat);
            tables--;
            seats -= resSeat;
            data.push_back(name);
            cout << "Thank you! Reservation has been added\n";
            }
            break;
        case 3: {
            if (data.size() == 0) {
                cout << "There are no reservations to delete.\n";
                break;
            }
            cout << "Enter which reservation to delete: ";
            int del = readInt(1, data.size());
            del--;
            cout << "To erase: " << data[del] << " y/n?\n";
            char conf = readYN();
            if (conf != 'Y') {
                cout << "Operation cancelled\n";
                break;
            }
            tables++;
            int ia = data[del].at(data[del].find(",") + 1) - '0';
            cout << "Refunded: " << ia << " Seats\n";
            seats += ia;
            data.erase(data.begin() + del);
            }
            break;
        case 4:
            runner = false;
            break;
        }
    }
}

Hello valkjo1,

Welcome to the forum.

As an example in line 36 the std::cin >> r; is known as formatted input. Some times this can be useful, but with input to a "std::string" the keyboard does not go directly into the variable, but into a buffer, i.e., "input buffer" and will only extract from the input buffer up to the first white space or new line whichever comes first.

If you want to enter a full name with a space between names then you will have to use "std::getline(std::cin, r);" which will extrat everything up to the new line, but not the new line. I would also suggest changing "r" to "fullName" for a better understanding of what the variable is. Single letters are easy, but hard to understand. Best to leave a single letter for the loop counter in a for loop.

Just a hint this, at least for me, makes the output on the screen easier to understand:
1
2
cout << "Enter your full name: ";
cin >> r; // use enters name 

Removing the "\n" from the cout statement will put your input at the end of the prompt instead of the next line.

A few more blank lines and better indenting would make your code much easier to read.

Tomorrow I will show you your code in a different way.

Using the "std::getline(...);" would work better otherwise you would have to use "std::cin >> firstName" and "std::cin >> lastName" or "std::cin >> firstName >>lastName;".

Hope that helps,

Andy
@Andy, I tried to use getline(cin, name) for inputting firstname but it would immediately skip over to the output I had after. Thanks for your support btw.

1
2
3
4
if(tables>0){  // tables available must be >0
			cout << "Enter your full name : ";
		    getline(cin, name);	
			cout << name;

@tpb Thanks for making those methods for me, i'll incorporate them into the program. edit: same issue with getline, immediately skips to cout
1
2
3
4
5
6
Welcome to reservation system, what would you like to do? ...
1. Print All Reservers, 2. Add a reservation, 3. Remove a reservation ...
2
Enter your full name :
# Of Seats (max 4):
Last edited on
I think they meant you should use std::getline for every input that you read, not just the name. If you don't want to do that I can recommend using std::ws before each time you use getline. It makes getline behave much the same as >> in the sense that it first discards any leading whitespace characters (spaces, newlines, tabs, etc.) before trying to read the input.

1
2
cout << "Enter your full name: ";
getline(cin >> ws, name);
Last edited on
Hello valkjo1,

As I promised here is your program with some blank lines and better formatting. Read the comments that I put in the program and notice how I used "fullName"ninsted of "r" and how "fullName" was used later.

The use of the "std::cin.ignore()" line is needed after a "std::cin >>"" and before a "std::getline" to remove the new line from the input buffer and anything else that might be there.

I did test your program and did make some changes that you may find work better and give a better output to the display. Mostly the use of a new line at the beginning of the text of a "std::cout" statement and the removal of the "std::endl" at the end of some lines.

Your problem with using "getline" with the variable "name" is most likely the problem because of the way some of the code is written, e.g., name = to_string(data.size() + 1) + " " + name + " " + r;, is putting to much information into "name" Notice how I changed that in my 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
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
// reserv.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"  // <--- Not needed when posting code here.
#include "iostream"  // <--- semi-colons not needed here.
#include <vector>
#include <iomanip>
#include <string>
#include <limits>

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

int main()
{
	int sel{};
	int tables = 5;
	int seats = 20;
	int resSeat{};
	std::string name;
	std::string fuleName;  //<--- Changed from "r".
	std::vector <std::string> data;
	
	std::cout << "Welcome to reservation system, what would you like to do? ... " << std::endl;

	bool runner = true;

	while (runner)
	{
		// <--- Needs an exit. Choice 4.
		//std::cout << "1. Print All Reservers, 2. Add a reservation, 3. Remove a reservation ...: ";
		std::cout << "\n1. Print All Reservers\n2. Add a reservation\n3. Remove a reservation\n4. Exit: " << std::endl;
		std::cout << "Enter Choice: ";  // <--- Added.
		std::cin >> sel;

		switch (sel)
		{
			case 1:
				std::cout << "\nReservations: " << data.size() << "\nAvailable Tables: " << tables << "\nAvailable Seats: " << seats << std::endl;

				// <--- Kind of pointless if "data.size()" is zero. Would not run any how.
				for (unsigned int i = 0; i < data.size(); i++)
					std::cout << data[i] << std::endl; // print reservation data
				break;

			case 2:
				if (tables > 0)  // tables available must be > 0
				{
					std::cout << "\nEnter your full name: ";  // <--- Changed.
					std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
					std::getline(std::cin, fuleName); // use enters name

					//	cout << "Enter last name: \n";   // full name entry breaks, if i have this as a 2nd input it works fine (user must enter first/last name seperately though)
					//  cin >> name;

					//name = fuleName + " " + name;  // <--- Too much information going into "name".
					//name = fuleName;  // <--- Not needed here because of what you do later.

					bool wrong = true;

					do
					{
						std::cout << "# Of Seats (max 4): ";  //<--- Changed.
						std::cin >> resSeat; // reserved seats
					
						if (resSeat <= 4) // max 4
						{
							wrong = false;
						}
					} while (wrong);

					// <--- Changed next line. TMI. Also changed to "+=".
					name += std::to_string(data.size() + 1) + ". " + fuleName; // +" " + name + " " + fuleName; // add the reservation number to the string (e.g 1st reservation -> 1)

					// <--- Next line can be combined with the above line.
					name += "*" + std::to_string(resSeat); // add seats reserved to string after a *

					tables = tables - 1;

					seats = seats - resSeat;

					data.push_back(name); //  push into vector

					std::cout << "\nThank you! Reservation has been added\n";

				}
				else
				{  //<--- {}s not needed for one line, but OK.
					std::cout << "\nWe are fully reserved today.. Sorry :-(\n";
				}
				break;

			case 3:
				int deal;
				char conf;

				// <--- You might want to print the reservations first to make it easier to know which reservation number to delete. Also check if "data" is has information to delete. > zero.

				std::cout << "\nEnter which reservation to delete: ";  // <--- Changed.
				std::cin >> deal;

				deal = deal - 1;

				std::cout << "To erase: " << data[deal] << " y/n?: ";  // <--- Changed.
				std::cin >> conf;

				if (conf == 'y' || conf == 'Y')
				{
					tables = tables + 1;

					int ia = data[deal].at(data[deal].find("*") + 1) - '0';

					std::cout << "\nRefunded: " << ia << " Seats.." << std::endl;
					seats = seats + ia;

					data.erase(data.begin() + (deal));

				}
				else
				{
					std::cout << "\nOperation cancelled..";  // <--- Changed.
				}
				break;

			case 4:  // <--- Added.
				runner = false;
				break;

			default:
				runner = false;  // <--- Not the best idea. An error message would be bettern in place of this line.
				break;
		}
	}

	//system("pause");  // <--- Best not to use "system" anything.

	// 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();

	return 0;
}

The lines just before the "return" you can use to replace the system("pause"); that you have used and not everyone can use.

When posting code here it is best to leave out the line #include "stdafx.h" as it is only by Visual Studio and is consider a non standard C++ header file.

As far as the compiler is concerned where you put the opening { of a set is not a problem. As you can see in the above code putting th opening { on the next line and proper indenting makes the code easier to read along with the {}s lining up in the same column makes it easier to find when one is missing.

Hope that helps,

Andy

P.S. Notice the "std::cin.ignore" before the getline. What happens is the use of "std::cin >>" before a "std::getline()" leaves the new line in the input buffer that the "std::getline()" will read and process continuing on to the next line of code. Referring to line 48 in my code.
Last edited on
Thank you for fixing up my code, I wasn't aware of cin.ignore either. It's working perfectly now, i'll be sure to use your tips for future code too.
Topic archived. No new replies allowed.