char data type and processing it

Started by
5 comments, last by Zahlman 14 years, 11 months ago
Hello all, Quick question about char's as a data type and something odd I am getting in a simple program. Since I am so rusty with my C++, I pulled out an old text, and I am running through the end of chapter exercises to see what all I need to review. The following program was just to create a simple Navigation system allowing movement along the x-y axis, one unit at a time, in a user selected direction. So, I did the following:

#include <iostream>

using namespace std;

int main()
{
	int xCoordinate=0;
	int yCoordinate=0;
	char direction=' ';

	while (toupper(direction) != 'Q')
	{
		cout << "Current coordinates: (" << xCoordinate << ", " << yCoordinate << ")" << endl;
		cout << "Please enter a direction to move (n, s, e, w, q to quit): ";
		cin >> direction;

		switch (toupper(direction))
		{
		case 'N':
			yCoordinate++;
			break;
		case 'S':
			yCoordinate--;
			break;
		case 'E':
			xCoordinate++;
			break;
		case 'W':
			xCoordinate--;
			break;
		default:
			cout << "Please enter n, s, e, w, or q" << endl;
			break;
		}
	}

	return 0;
}

Simple enough, and it works fine. Figured I was ready to move on. Decided to run it one more time, and this time when prompted, I entered my direction choice as literally 'eeee'. Oddly enough (at least to me), the program quickly moved me 4 units to the east on the x axis. My question/confusion is why did it process all 4 e's? Is it something to do with the char data type or input stream? I am actually quite embarrassed that I even have to ask this question :-( Thanks!
Advertisement
Quick screen of what exactly it is doing:

Navigation screen
It's not because of the char data type. It's the input stream. cin stands for Character INput, and when you say cin >> direction, you are asking it to fill direction with a char, or character (and direction can only store one character at a time). You entered four characters though, which all get queued up in the input stream. So your loop runs once, grabs the first character, and then when the loop runs again, the input stream is still holding three more characters, so the program gabs the second character, then the third, and then the fourth. Then the input stream is empty and your program resumes as you expect it to.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
cin is a buffered input stream. inside cin, it retrieves "eeee\n"
since you only pull a single char off the front, it just loops untill all the e's have been eaten, one at a time, from the buffer.
Ah yes, I was not thinking about the \n for showing the end of the input buffer....

Leads me to question how to process just that first character then and flush the rest of the data in the direction variable..
You can use ignore() on a stream to dump the buffer contents without processing them. You could also read a line at a time with std::getline() and only process the first character you find in that line.
There are two things going on here: the console is preparing input a line at a time and feeding it to your program (this is a good thing; it makes e.g. backspace work properly), and the stream is reading data on its own schedule. Reading from std::cin does not automatically pause the program; reading from any stream pauses the program whenever the available data (possibly none) could be the start of valid data (zero bytes of data will always be a valid "prefix") but the read-in item is not "finished".

If you always read the console input a line at a time, then things will keep in sync: there will be no data on the stream whenever you make a read request (because it was all processed last time), and you will read all of the data that the console makes available. You can then re-parse that line of input with a std::stringstream, if necessary.

To read a line of input into a std::string, use the free function std::getline:

string input;getline(cin, input);


To re-parse the string, construct a std::stringstream instance from it, and use read operations on that stream just like you would on std::cin or a file stream:

int count;stringstream parser(input);if (parser >> count) {  getline(parser, input); // just for example: now 'input' holds the *rest* of the line.} else {  // The user's line of input didn't start with a number.}// Either way, an entire line of input has been consumed.


The std::stringstream type is provided by <sstream>.

This topic is closed to new replies.

Advertisement