954,500 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Junk Input Causes the Program to Ignore "cin.ignore(1000, '\n');"

I'm having trouble with this section my code and am hoping that you can help me diagnose and solve the problem. I'm not sure if it makes a difference, but I compile and run my code in Cygwin.

The problem:
At run time when the program asks for the user input I can input somethimg like: "Guybrush Threepwood Throe" and the code will run just fine, but if I type the same thing and then use the left arrow button to move the cursor back over the input to make a correction (for instance to change the third word of the input from "Throe" to "Three"), the program will ignore (or seem to ignore) all of my "cin.ignore(1000, '\n');" and "cin.getline(input1, 31, '\n');" commands. I'm aware that you're not technically supposed to use the arrow keys in Cygwin, but I'm trying to make my code fool-proof.

Why does this happen, and assuming the user will eventually use those arrow keys, how can I prevent the undesired side-effects?

#include <cstdlib>
#include <iostream>
using namespace std;

int main ()
{
  char input1[31];
  char default1[31] = "                              ";
  int success = 0;
  int tries = 0;
  while ((success != 0) && (tries < 4))
  {
     cout << "[By what name shall you be known? Max: 30 Characters]" <<   endl;
     cout << ":" << endl;
  // Point of possible conflict follows immediately
     cin.getline(input1, 31, '\n');
     if (((input1[0] > 64) && (input1[0] < 91)) || ((input1[0] > 96) && (input1[0] < 123))) 
        success = 1; // Success = 1 if input1 starts with a letter.
     else
     {
        cout << "What kind of name doesn't begin with a letter?" << endl;
        cout << "(Type a name that starts with a letter.)" << endl;
        tries++;
     }
  }

  if (tries >= 4)
  {
     char guybrush[31] = "Guybrush";
     strcpy (input1, guybrush);
     cout << "Fine. I'm going to assume your name is Guybrush." << endl;
  }


  cout << "Some text here..." << endl;
  cin.ignore(1000, '\n');     // Used as a pause function
  cout << "Some more text here..." << endl;
  cin.ignore(1000, '\n');

  strcyp (input1, default1);
  cout << "Input command." << endl;
  cout << ":";
  cin.getline(input1, 31, '\n');
  return 0;
}


Thank you for your input.

LordoftheFly
Newbie Poster
7 posts since Oct 2008
Reputation Points: 32
Solved Threads: 0
 

Excellent first post - code tags, environment, statement of problem and example code. Everyone else should learn from this!

> strcyp (input1, default1);
Does this compile?
Isn't it supposed to be strcpy() ?

> the program will ignore (or seem to ignore) all of my "cin.ignore(1000, '\n');" and
> "cin.getline(input1, 31, '\n');" commands.
Or they could be returning error.
Check the return result to see if this is the case.

Salem
Posting Sage
Team Colleague
11,531 posts since Dec 2005
Reputation Points: 5,862
Solved Threads: 953
 
> strcyp (input1, default1); Does this compile? Isn't it supposed to be strcpy() ?


Sorry about this one. I had to retype the code on another computer to put it online; so no.. it probably wouldn't compile. Additionally, on line 14, a correction would have to be made to cause the program to go into that while loop.

It would be changed from:

while ((success != 0) && (tries < 4))


to

while ((success == 0) && (tries < 4))
> the program will ignore (or seem to ignore) all of my "cin.ignore(1000, '\n');" and > "cin.getline(input1, 31, '\n');" commands. Or they could be returning error. Check the return result to see if this is the case.

I checked the value of input1 by adding the following code after the if-statement that starts on line 30.

cout << "input1 =" << input1 << "!" << endl;


I experimented with different input and arrow key combinations, and came to some realizations.

1. I started with the standard input that I used for all of the debugging:
Guybrush Threepwood T2345
2. When I used any left-right combination that started with theleft arrow, the output always came out the same (regardless of whether or not I replaced characters.):

input1 =Guybrush Threepwood T234ome text here...
Some more text here...


3. When I used any left-right combination that started with theright arrow, I got:

input1 =Guybrush Threepwood T2345 ome text here... 
Some more text here...



I didn't bother with the up or down arrows because it made things way more complicated.

I'm sorry that this this getting more complicated, but I thank you for your patience and responses.

LordoftheFly
Newbie Poster
7 posts since Oct 2008
Reputation Points: 32
Solved Threads: 0
 

So if you have

while ( cin.getline(input1, 31, '\n') ) {
  cout << "--" << input1 << "--" << endl;
}
if ( cin.fail() ) {
  cout << "Failed" << endl;
}
if ( cin.eof() ) {
  cout << "EOF" << endl;
}
if ( cin.bad() ) {
  cout << "bad, very bad" << endl;
}

If you use an arrow key, what happens here?
- loops a few times, then prints one of the exit messages?
- loops a few times, printing various fragments of the edited input, then goes back to waiting. http://www.cppreference.com/wiki/io/fail

To get out of the loop, press ctrl-d, and you should see EOF printed.

If the code keeps in the loop, but prints various fragments of the line in several attempts, you should be able to recover.

Oh, and please find a way of copying the code accurately (pen drive, email yourself, whatever). It'll save a lot of confusion in the long run.

Salem
Posting Sage
Team Colleague
11,531 posts since Dec 2005
Reputation Points: 5,862
Solved Threads: 953
 
while ( cin.getline(input1, 31, '\n') ) {
  cout << "--" << input1 << "--" << endl;
}
if ( cin.fail() ) {
  cout << "Failed" << endl;
}
if ( cin.eof() ) {
  cout << "EOF" << endl;
}
if ( cin.bad() ) {
  cout << "bad, very bad" << endl;
}

This is a clever test. Thanks for this insight.If you use an arrow key, what happens here?
- loops a few times, then prints one of the exit messages?
- loops a few times, printing various fragments of the edited input, then goes back to waiting.
When I use the arrow keys it prints "Failed." And according to the link "Once set, the fail state will make all other operations on the stream fail instantly, until the error state is cleared with the clear function." ( http://www.cppreference.com/wiki/io/fail )

So it sounds like the fail flag is being tripped, would which apparently cause my program to go haywire. I'm looking around and can't seem to find any information on the "clear function."
Oh, and please find a way of copying the code accurately (pen drive, email yourself, whatever). It'll save a lot of confusion in the long run.
I shall try. Again, thanks for your patience and input.

LordoftheFly
Newbie Poster
7 posts since Oct 2008
Reputation Points: 32
Solved Threads: 0
 

http://www.cppreference.com/wiki/io/clear

link to the clear() method of input stream. It's under the C++ I/O link on the main page, then click on clear.

This site deserves to be on your list of favorites, if it isn't already.

Lerner
Nearly a Posting Maven
2,382 posts since Jul 2005
Reputation Points: 739
Solved Threads: 396
 

Make a function like this (with iostream included and the std namespace):

ostream & Flush (ostream & myStream)
{
myStream.clear();
myStream.ignore(myStream.rdbuf()->in_avail());
return myStream;
}

Then call it for whatever stream you want to clear, and it supports chaining. ie Flush(cin) >> iInput;

skatamatic
Posting Shark
959 posts since Nov 2007
Reputation Points: 403
Solved Threads: 129
 
http://www.cppreference.com/wiki/io/clear This site deserves to be on your list of favorites, if it isn't already.


It definitely is now.Make a function like this (with iostream included and the std namespace):

ostream & Flush (ostream & myStream)
{
myStream.clear();
myStream.ignore(myStream.rdbuf()->in_avail());
return myStream;
}

Then call it for whatever stream you want to clear, and it supports chaining. ie Flush(cin) >> iInput;
I actually had a lot of trouble trying to figure out how exactly to implement the code, and it took three webpages and this thread for the information to make a modicum of sense to me. I came up with this seemingly simple function:

void clear (ios::iostate flags = ios::goodbit);

which I call using the following segment of code, which is partially borrowed from Salem's code:

if ( cin.fail() )
{
  cout << "Failed." << endl;
  cout << "Please do not use the arrow keys." << endl;
  cin.clear();
}


The sources that proved helpful to me are listed here: http://www.cppreference.com/wiki/io/clear
http://www.cplusplus.com/reference/iostream/ios_base/iostate.html
http://www.cplusplus.com/reference/iostream/ios/clear.html

It seems that this problem is solved, so thank you to everyone who contributed time and information to my code.
-- LordoftheFly

LordoftheFly
Newbie Poster
7 posts since Oct 2008
Reputation Points: 32
Solved Threads: 0
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You