Sign in to follow this  
Austin0v

Program ignoring getline function.

Recommended Posts

Austin0v    122
I was able to get this program to recognize the getline by adding ignore but I don't understand why adding that works and why it doesn't work if you don't have it. Could someone please explain? Thank you!
// input and output practice

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

#define SPACE "\n\n\n\n"

int main ()
{
	
	int i;
	string name;

	cout << "Please enter a number: ";
	cin >> i;
	cout << "You entered the number " << i << endl;
	cout << "If you times that by 2 you get " << i*2 << endl;
	

        // problem area
        cout << "What is your name? ";
	cin.ignore(256, '\n');
	getline(cin, name);
	cout << "\nhello " << name << " you're awesome!";


	cout << SPACE;
	system("pause");
	return(0);

}


Share this post


Link to post
Share on other sites
SiCrane    11839
When you use cin >> i it consumes the number characters in the stream and leaves the carriage return after the number. So if you call getline() immediately it consumes the carriage return and looks like it ignores the getline(). By adding the ignore you remove the carriage return from the stream before getline() is called.

Share this post


Link to post
Share on other sites
Austin0v    122
Quote:
Original post by SiCrane
When you use cin >> i it consumes the number characters in the stream and leaves the carriage return after the number. So if you call getline() immediately it consumes the carriage return and looks like it ignores the getline(). By adding the ignore you remove the carriage return from the stream before getline() is called.


Thanks, that makes some sense. But, now I have another question, is it improper practice to code that how I did?

Share this post


Link to post
Share on other sites
SiCrane    11839
Well, the way you have it now you don't do any error detection and you're making an assumption discarding 256 characters will get you to the next line. For example, try feeding your program "Moo" as the number and watch what happens. Or 5 a space and then a few hundred 5's after that before you hit enter.

Share this post


Link to post
Share on other sites
Zahlman    1682
While we're on the topic of "poor practice": don't pause your programs artificially at the end (run it properly instead - from the command line or via a batch file), and use const identifiers for constants rather than #define hackery. Also, main() (as a special case!) doesn't require an explicit return value, and return values don't require parentheses around them (return is a keyword, not a function).

Share this post


Link to post
Share on other sites
Cornstalks    7030
Quote:
Original post by Zahlman
While we're on the topic of "poor practice": don't pause your programs artificially at the end (run it properly instead - from the command line or via a batch file)

Hope I'm not hijacking this thread by asking this, but why do people recommend against using system("pause")? When I write little test applications (generally they're less than 50 lines), I find it convenient to simply use system("pause") and then tell my IDE to run the program rather than creating a batch file or hunting down my new .exe in a command prompt. So what's wrong with system("pause") in a simple, little test application?

Share this post


Link to post
Share on other sites
dmatter    4844
Quote:
Original post by MikeTacular
Hope I'm not hijacking this thread by asking this, but why do people recommend against using system("pause")?
It's non-standard and it's massively overkill to tell the operating system to pause your program rather than simply have the program wait for the user to press a key: std::cin.get();

You wouldn't want a 'real' program to halt at the end anyway - most all applications you use don't do that.

Quote:
So what's wrong with system("pause") in a simple, little test application?
Nothing. Just keep in mind that it's both non-standard C++ and unprofessional in a polished project.

Share this post


Link to post
Share on other sites
Brother Bob    10344
Quote:
Original post by dmatter
Quote:
Original post by MikeTacular
Hope I'm not hijacking this thread by asking this, but why do people recommend against using system("pause")?
It's non-standard and it's massively overkill to tell the operating system to pause your program rather than simply have the program wait for the user to press a key: std::cin.get();

Or just run the program properly from the IDE. In Visual Studio for example, use Run Without Debugging, Ctrl+F5.

Share this post


Link to post
Share on other sites
Austin0v    122
Quote:
Original post by SiCrane
Well, the way you have it now you don't do any error detection and you're making an assumption discarding 256 characters will get you to the next line. For example, try feeding your program "Moo" as the number and watch what happens. Or 5 a space and then a few hundred 5's after that before you hit enter.


Just curious, what's the proper way to use the ignore function with proper error detection?

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by Austin0v
Quote:
Original post by SiCrane
Well, the way you have it now you don't do any error detection and you're making an assumption discarding 256 characters will get you to the next line. For example, try feeding your program "Moo" as the number and watch what happens. Or 5 a space and then a few hundred 5's after that before you hit enter.


Just curious, what's the proper way to use the ignore function with proper error detection?


Don't. Instead, use the following "buffering" strategy.

Read each line of input into a string. That way you will never have to 'ignore' anything, since you always read everything that's currently available on std::cin.

Then, use the std::stringstream object to attempt to pull data out of the string (your "buffer"). If it doesn't work (because the input data was invalid), you can simply try again, and you don't have to reset anything. The next time through the loop, you get a brand new stringstream object, with the next line of user input.

You can simplify things for yourself a little bit by making a templated function to get the line, read in from it into a value, and return whether or not it was successful.


// input and output practice

#include <iostream>
#include <string>
#include <sstream> // where std::stringstream lives.
using namespace std;

template <typename T>
bool getValue(istream& is, T& result) {
string line;
getline(is, line);
return std::stringstream(line) >> result;
}

int main() {
int i;
string name;

do {
cout << "Please enter a number: ";
} while (!getValue(cin, i));
cout << "You entered the number " << i << endl;
// minor English lesson here :)
cout << "If you multiply that by 2 you get " << i*2 << endl;

cout << "What is your name? ";
getline(cin, name); // the input data is always in string format ;)
cout << "\nhello " << name << " you're awesome!";
}




Edit: Er, of course. Behold as I completely fail at being a ninja and editing it in. =)

[Edited by - Zahlman on August 19, 2008 9:49:59 PM]

Share this post


Link to post
Share on other sites
Austin0v    122
Thank you so much for all your help. Now in my never ending quest to know every aspect of everything, why is it that the buffer isn't ignored in the first place without having to ignore it or without having to have a function to extract only the data you need? Is there a reason that all the data is stored in that buffer?

Share this post


Link to post
Share on other sites
SiCrane    11839
Basically, the formatted extraction operators and the getline() function represent two fundamentally different ways of interacting with a stream. The formatted extraction operators work by stripping out all whitespace and then processing what's left as the desired type. So two successive formatted extractions will behave like you would expect. Ex: this code will read and output two integers if the data is either "5\n6\n" or "5 6\n" or even "\t5 \t\n6\n".

int i, j;
std::cin >> i;
std::cout << i << "\n";

std::cin >> j;
std::cout << j << "\n";

getline(), however, works by taking everything in the stream up to the next new line and dumping it into the buffer and ripping out the newline. So do you see the difference? Formatted extraction removes all whitespace before the extracted data. Whereas getline() removes only a newline after the extracted data.

Share this post


Link to post
Share on other sites
Austin0v    122
Quote:
Original post by SiCrane
Basically, the formatted extraction operators and the getline() function represent two fundamentally different ways of interacting with a stream. The formatted extraction operators work by stripping out all whitespace and then processing what's left as the desired type. So two successive formatted extractions will behave like you would expect. Ex: this code will read and output two integers if the data is either "5\n6\n" or "5 6\n" or even "\t5 \t\n6\n".

int i, j;
std::cin >> i;
std::cout << i << "\n";

std::cin >> j;
std::cout << j << "\n";

getline(), however, works by taking everything in the stream up to the next new line and dumping it into the buffer and ripping out the newline. So do you see the difference? Formatted extraction removes all whitespace before the extracted data. Whereas getline() removes only a newline after the extracted data.


Ok, I understand now, what are some examples of practical uses of using one or the other?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this