Multiple input in a do while loop cin for int

Hello. I have this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int a;
int b;
	do {
		cout << "set a to: ";
		cin >> a;
		cin.clear();
		cin.ignore();
	} while (cin.fail());
	do {
		cout << "set b to: ";
		cin >> b;
		cin.clear();
		cin.ignore();
	} while (cin.fail());
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

It works, but if the user inputs multiple int characters separated by spaces, this happens:
set a to: 12 12
set b to: r = 2
h = 12


Or if he inputs multiple chars:
set a to: aa
set a to: set a to:


Why does it happen and how can I fix it?

I tagged it as News by accident, sorry
Last edited on
This happens because std::cin reads until a white space is hit, whether it be ' ', '\n' or '\t'
That's why you're able to put "12 12" in the same line and load both a and b simultaneously.

Also note std::cin as completely unaffected by what you do in std::cout.

Now, if you don't want this to happen the solution might be to load entire lines and convert them to int instead.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
	int a;
	int b;
	string line;

	cout << "set a to: ";
	getline(cin, line);
	a = strtol(line.c_str(), NULL, 10);

	cout << "set b to: ";
	getline(cin, line);
	b = strtol(line.c_str(), NULL, 10);

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}
Thanks! I also fixed this by using
1
2
cin.clear();
cin.ignore(INT_MAX, '\n');

in the do while loop.
This thing really can't get out of my head :) This is my code (which works as I want it to):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <climits>
using namespace std;

int main()
{
	int x;
	do {
		cout << "x: ";
		cin >> x;
		cin.clear();
		cin.ignore(INT_MAX, '\n');
	} while (cin.fail() || x< 0);
    return 0;
}


I understand that by writing cin.clear(); I remove the error flag so cin.fail(); will always be equal 0 in the while condition which makes it redundant. And if the user inputs something else than a number it gets converted to a negative value so the second condition still makes the loop continue. My question is whether it is a good practice to only use while(x<0); as the condition if I want to only accept input that is a number bigger than 0, or should I still write something like bool fail = cin.fail(); before cin.clear(); and then while(fail || x < 0); (when I know that I will not need the value of that specific cin.fail(); in the future, at least for this program)
Guess I'm overcomplicating it but want to be sure.
Guess I'm overcomplicating it but want to be sure.

Well, your code looks a bit complicated, but it’s not your fault :-)
This problem (of the trailing ‘\n’ in input instructions) is one of most most common requests for help on this forum, and I’m afraid it doesn’t have a simple answer. Every solution I’ve read so far requires quite a few lines of code.

In my (totally personal an perhaps not shared) opinion, the best way to solve this problem is by eliminating the trailing ‘\n’ from the input buffer from the very beginning. This can be done by the function std::getline(), as Ihatov proposed, which reads an entire line (spaces included) and discards the final ‘\n’:
http://en.cppreference.com/w/cpp/string/basic_string/getline

But once you have used std::getline(), you’ve got your input inside a std::string, not a number variable:
1
2
3
4
std::cout << "Please give me a number: ";
std::string line;
std::getline(std::cin, line);
// the user input is now stored inside the std::string line 

It means you can’t yet use it as a number.

Then you need to get if out of the string and store it into a number - and again you need to choose between different methods. The most used is creating an instance of an object called stringstream and passing the std::string to its constuctor:
std::stringstream ss(line);
http://en.cppreference.com/w/cpp/io/basic_stringstream
Now you can use that std::stringstream as you would use std::cin:
1
2
3
double mydouble = 0.0;
int myint = 0;
ss >> mynum >> myint;


It looks very complicated, but you’ve succeeded in getting rid of the trailing ‘\n’ :-)
Alternatively, you can use std::atoi() or std::atof() on the std::string (or std::strtol, as suggested by Ihatov):
http://en.cppreference.com/w/cpp/header/cstdlib
std::atoi(line.c_str());
or even std::stoi(), std::stod():
http://en.cppreference.com/w/cpp/string/basic_string/stol
std::stoi(line);
(but you need to know how to deal with exceptions, in this last case).

The other methods, in my opinion, are even more complicated.

Happy coding!
Thanks for the thorough explanation. I just have to practice using this method :)
Topic archived. No new replies allowed.