getline not asking for input? [duplicate]
Asked Answered
T

3

6

This is probably a very simple problem but forgive me as I am new. Here is my code:

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

int main ()
{ 
   string name;
   int i;
   string mystr;
   float price = 0;

   cout << "Hello World!" << endl;
   cout << "What is your name? ";
   cin >> name;
   cout << "Hello " << name << endl;
   cout << "How old are you? ";
   cin >> i;
   cout << "Wow " << i << endl;

   cout << "How much is that jacket? ";
   getline (cin,mystr);
   stringstream(mystr) >> price;
   cout << price << endl;
   system("pause");

   return 0;
}

The problem is that when asked how much is that jacket? getline does not ask the user for input and just inputs the initial value of "0". Why is this?

Tompion answered 10/7, 2011 at 18:3 Comment(1)
Note: This have been asked many times. Here are some few #3732029 https://mcmap.net/q/67106/-need-help-with-getline-duplicate #4877459Amadeus
D
13

You have to be careful when mixing operator>> with getline. The problem is, when you use operator>>, the user enters their data, then presses the enter key, which puts a newline character into the input buffer. Since operator>> is whitespace delimited, the newline character is not put into the variable, and it stays in the input buffer. Then, when you call getline, a newline character is the only thing it's looking for. Since that's the first thing in the buffer, it finds what it's looking for right away, and never needs to prompt the user.

Fix: If you're going to call getline after you use operator>>, call ignore in between, or do something else to get rid of that newline character, perhaps a dummy call to getline.

Another option, and this is along the lines of what Martin was talking about, is to not use operator>> at all, and only use getline, then convert your strings to whatever datatype you need. This has a side effect of making your code more safe and robust. I would first write a function like this:

int getInt(std::istream & is)
{
    std::string input;
    std::getline(is,input);

    // C++11 version
    return stoi(input); // throws on failure

    // C++98 version
    /*
    std::istringstream iss(input);
    int i;
    if (!(iss >> i)) {
        // handle error somehow
    }
    return i;
    */
}

You can create a similar function for floats, doubles and other things. Then when you need in int, instead of this:

cin >> i;

You do this:

i = getInt(cin);
Dulcia answered 10/7, 2011 at 18:9 Comment(4)
Thank you very much Benjamin! I Understand you completelyTompion
Why didn't I join this site sooner :-/Tompion
Does "return stoi(input)" basically mean if return type is string convert to integer?Tompion
@Kyle: No. It means, "return the return value of stoi(input)". And stoi takes a string(there's no if involved here, it must be a string, otherwise it won't compile), and tries to convert it to an integer.Dulcia
P
3

Its because you have a '\n' left lying on the input stream from a previous call.

cin >> i;  // This reads the number but the '\n' you hit after the number
           // is still on the input.

The easiest way to do interactive user input is to make sure each line is processed independently (as the user will hit enter after each prompt).

As a result always read a line, then process the line (until you get familiar with the streams).

std::string  line;
std::getline(std::cin, line);

std::stringstream linestream(line);

// Now processes linestream.
std::string garbage;
lienstream >> i >> garbage; // You may want to check for garbage after the number.

if (!garbage.empty())
{
    std::cout << "Error\n";
}
Pompadour answered 10/7, 2011 at 18:8 Comment(3)
I don't understand? So what exactly do you suggest I do to get getline to ask for input? Sorry I'm a complete n00bTompion
Thank you both I shall keep this in mind as soon as I understand what I'm doing a bit more.. cheersTompion
I found this very useful [link]augustcouncil.com/~tgibson/tutorial/iotips.html[link]Tompion
A
2

Ignore some characters until line feed is reached.

cin.ignore(256, '\n')
getline (cin,mystr);
Amadeus answered 10/7, 2011 at 18:14 Comment(2)
Could you explain this a little more? Why am I ignoring 256 characters isn't that more than a byte so why 256?Tompion
It is the maximum number of characters to extract or ignore from input stream. You could have a number greater than 256 depending the length of your input. In your case, I assumed 256 to be the maximum length of input characters for the name string.Amadeus

© 2022 - 2024 — McMap. All rights reserved.