A problem with clearing std::cin

I wrote a program to test if I could successfully input text from my keyboard into different vectors and then have the program output all the text.


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

using namespace std;

int main()
{
	
string s;
vector<string> first;
vector<string> second;
cout << "enter strings of words for the first column." << endl;
 while (getline(cin, s))
	first.push_back(s);
cout << endl;
	
s.clear();
cin.clear();
	
cout << "enter strings of words for the second column." << endl;
while (getline(cin, s))
	second.push_back(s);
cout << endl;

for (vector<string>::const_iterator i = first.begin(); i!=first.end(); ++i)
	cout << *i << endl;
for (vector<string>::const_iterator i = second.begin(); i!=second.end(); ++i)
	cout << *i << endl;

return 0;
}


In my code, the user is supposed to input lines of words for one vector, and then another set of lines for a second vector. The program is then supposed to output each line on the screen.

My problem is that I never get to input text for the second vector. It seems my program skips over the second while loop on line 22. Actually, I'm pretty sure it skips over the second while loop. I don't know why the getline function is returning a false bool, other than the possibility that cin is still in a fail state. I don't know why it would be, because I thought calling cin.clear() took care of that.

I am on Mac OSX Snow Leopard, typing out my code on TextWrangler, and compiling, building, and running everything in the Terminal window with g++.

I gave my code to a friend who is running Visual C++ on Windows 7. He says the code works perfectly on his computer and he gets to input lines of text for each prompt.

When I run my program, I get my first prompt. I then input something like:

asdsads <return> dfdfdsfsfs <return> sdfdfs <return> CNTRL-D

The program then prints out my second prompt, but doesn't stop to allow me to input anything. It then ends up printing out only the first vector, since the second vector never had an opportunity to be filled. The program then terminates.

I feel like it is a problem with how my Terminal window handles the end of file command. I understand that when I type in CNTRL-D the first time, it puts cin in a fail state, but for some reason the implementation doesn't seem to listen when I ask it to cin.clear().

Any help would be appreciated. I just started learning C++ two weeks ago and I'm very new at this. Thank you in advance.


Last edited on
I'm on Windows Vista, using MinGW g++. I copied as is, and compiled with g++. It just keeps waiting for more input... I type something, hit enter, and this will go on forever until I terminate it with Ctrl-C.

There is definitely a problem with the while loop.

I ran a debug in Eclipse, and it seems to be getting stuck on first.push_back(s); in your first while loop.
Last edited on
@RyanCaywood: You have to press end-of-file escape character (CTRL-Z on Windows and DOS) to stop the input.

@LacusAestatis: cin.clear() is not enough. You need to synchronize stream with
cin.sync();
or you can use this trick:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
Thank you for the help, but the problem still has not been resolved. I tried both of your methods and a combination of the two.

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

using namespace std;

int main()
{

string s;
vector<string> first;
vector<string> second;

cout << "enter strings of words for the first column." << endl;
while (getline(cin, s)) {
	first.push_back(s); }
cout << endl;

s.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n'); 

if (!cin) {
 cout << "FAILURE" << endl;
 return 1;
}

cout << "enter strings of words for the second column." << endl;
while (getline(cin, s)) {
	second.push_back(s); }
cout << endl;

for (vector<string>::const_iterator i = first.begin(); i!=first.end(); ++i)
	cout << *i << endl;
for (vector<string>::const_iterator i = second.begin(); i!=second.end(); ++i)
	cout << *i << endl;

return 0;
}


I added the if statement on the 25th line to see if the cin stream clears. When I run this program above, I get FAILURE, which means cin is still in a fail state. I also replaced cin.ignore(numeric_limits<streamsize>::max(),'\n'); with cin.sync() and still get FAILURE. I tried both lines, cin.sync; followed by cin.ignore(numeric_limits<streamsize>::max(),'\n');, and it still didn't clear out cin.

I'm quite at a loss. Is there any other advice you may be able to give me?

Last edited on
You still need cin.clear(); on line 23. You need this because after you pressed CTRL-D, cin is still in bad state and you have to clear it.
Last edited on
My cin is definitely cleared now, Thanks! Yet, I am still not able to input text for my second prompt.

When I run my program it no longer gets caught in the if statement, but it still skips over the second while loop.

I don't think the getline on line 30 (line 33 on the program below) would return a false bool now. So it might be the case that it's getting an end of file immediately once it enters? But I would think that cin.ignore took care of that. I'm not knowledgeable enough about the way iostream works to really know what's happening.

This is my code, updated with the cin.clear() command and an extra else statement:

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

using namespace std;

int main()
{

string s;
vector<string> first;
vector<string> second;

cout << "enter strings of words for the first column." << endl;
while (getline(cin, s)) {
	first.push_back(s); }
cout << endl;

s.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n'); 
cin.clear();

if (!cin) {
 cout << "FAILURE" << endl;
 return 1;
} else {
 cout << "cin is OK!" << endl;
}

cout << "enter strings of words for the second column." << endl;
while (getline(cin, s)) {
	second.push_back(s); }
cout << endl;

for (vector<string>::const_iterator i = first.begin(); i!=first.end(); ++i)
	cout << *i << endl;
for (vector<string>::const_iterator i = second.begin(); i!=second.end(); ++i)
	cout << *i << endl;

return 0;
}


Thank you so much for your help. I really appreciate it.


Last edited on
cin.ignore(numeric_limits<streamsize>::max(),'\n');


That line doesn't make much sense if you ask me. getline already advances the stream beyond the '\n' anyway. It probably has something to do with the ctrl-d or whatever special key that you are pressing. I'm not sure how to resolve that but you could just tell the user to enter "done" and add an additional statement to the while to allow termination after a specific word. Unfortunately I have never setup a loop to end on the ctrl-d so I don't know what ends up in the input stream when you do that. Perhaps you need to specify a different delimiter in the ignore call.
Ugh. I'm out of ideas.... how about cin.sync(); instead of cin.ignore(numeric_limits<streamsize>::max(),'\n'); ?

According to reference ( http://www.cplusplus.com/reference/iostream/istream/sync/ )
Synchronizes the buffer associated with the stream to its controlled input sequence. This effectively means that the unread characters in the buffer are discarded.

Hello Friends

i am jim smith and i am new to this forum.
When I run this program above, I get FAILURE, which means cin is still in a fail state. I also replaced cin.ignore(numeric_limits<streamsize>::max(),'\n'); with cin.sync() and still get FAILURE.
--------------------------------------------------

For connecting to remote desktop of another computer (via internet or network) and controls. Also connecting to VNCServer through Repeater or directly to VNCServer and a lot of other configuration options.
For more details [url=http://www.abtollc.com/VNCViewer.aspx /]VNCServer [/url]
Topic archived. No new replies allowed.