std::cin Peculiar Behavior

Started by
3 comments, last by Zahlman 17 years, 6 months ago
I wrote these pieces of code into a console program in VC++2005:

char* getStrInput()
{
	char* result = NULL;
	char buffer[80];
	cin.getline( buffer, 80 );
	result = new char[strlen(buffer)+1];
	strcpy(result, buffer);
	return result;
}

void getRecordDesc( Record* record )
{
	cout << "First name: ";
	record->first = getStrInput();
	cout << "Last name:  ";
	record->last = getStrInput();
	cout << "Title:      ";
	record->title = getStrInput();

	cout << "Salary:     ";
	cin >> record->salary;
}

The strange thing is that if I don't precede a getRecordDesc() call with a cin.get(), the following is displayed:

First name: Last name:  
cursor here-------------^
The code here that actually (practically) executes before the getRecordDesc() is a single cin >> (char)somevariable... PS: this is part of a homework, yes... However we are learning about dynamic memory allocation and linked lists, so it is not relevant to what am asking about. Please help
[ my blog ]
Advertisement
I'd say it has to do with those char*'s. Some string that's not null-terminated or such so the cout function continues writing what's next in memory untill it encounters a 0 character. Pointers can be a source of problems so use them with care. In this case, the C++ styled approach would be to use a std::string instead (char pointers are sometimes referred to as C-styled strings).

In fact, I just dealt with an almost identical situation. The old image loading code I wrote for my game used char*'s. When I adapted to a new folder structure, suddenly the game would only load the first 2 or 3 images... using strings solved the problem.
Create-ivity - a game development blog Mouseover for more information.
What a horrible way to learn about dynamic memory allocation. Also, questions like this really belong in For Beginners.

Anyway.

Operations on streams have no concept of "real time". When you read from cin, the characters you get are any characters that haven't already been read. If everything that the user has input has already been processed, then the program will wait (the read call will "block") until there is more data available.

In addition, the console input is line-buffered, which means that data only "becomes available" a line at a time.

In your case, what is likely happening is that you first perform some kind of read which leaves a newline ('\n') behind (since every time the user inputs a line, there is a newline character at the end of that line). Then, when getRecordDesc() is called, it outputs the prompt, and calls getStrInput(). getStrInput() in turn calls cin.getline(), and since there *is* a line of text available (that is to say, there is a '\n' in the not-yet-processed queue, so there is a line which consists of all the characters ahead of that - all 0 of them - plus the newline itself), that (empty) line is read in as the "first line". Then the next prompt is displayed right away, on the same line (because nothing happened which would cause the terminal to skip to the next line).

Possible solutions:

- Always grab input a line at a time, and "re-parse" it with std::stringstream objects.

- Skip any unprocessed stuff with cin.ignore(), cin.sync() etc. Look up the documentation for this stuff; it's important to understand what's going on.
The problem was solved like this:
// PREchar choice;cin >> choice; // get a single characterwhile( cin.peek() != '\n' )   cin.get();cin.get(); // get new-line character


Is there anything else to know

-------
This is not the way we're learning about linked-lists. It is only a part of a bigger program that I'm writing for the assignment. The record is the node; not that we are learning these concepts using characters (yuck!)
[ my blog ]
In that case, why not use std::string to represent text? :P

(You can read into a std::string by using the free function std::getline : e.g. std::getline(cin, mystring); )

This topic is closed to new replies.

Advertisement