0

I have this loop in my program tha reads a phone number as a string:

while (loop) {
    cout << "Telefone (0 para sair):" << endl;
    string phone;
    getline(cin, phone);

    // .. some logic
    while (loop2) {
        // .. more logic
        getline(cin, option);
        // .. more logic
    }
}

when the loop finishes the logic and returns to the begining, it doesn't ask for the phone again. It just goes through the logic again. Any ideas?

If I had used cin >> phone instead, it doesn't catch phone numbers with blank spaces.

0x499602D2
  • 87,005
  • 36
  • 149
  • 233
ddz
  • 525
  • 3
  • 13
  • Does that unshown logic include `cin >> something`? – chris Feb 19 '14 at 21:23
  • Please spend a day or three on this website looking for similar problems; this issue has been debated thousands of times. – Kerrek SB Feb 19 '14 at 21:23
  • @chris I'll complete one more portion of the loop. – ddz Feb 19 '14 at 21:24
  • Isn't getline called std::cin.getline(std::string,size) – Nowayz Feb 19 '14 at 21:25
  • 2
    @Nowayz, I don't see any problems with it apart from maybe the implied using directive. – chris Feb 19 '14 at 21:26
  • 2
    @LuizEduardoF., What would really help is a [minimal, but complete example](http://stackoverflow.com/help/mcve). At this point, we can only guess. – chris Feb 19 '14 at 21:27
  • 2
    @Nowayz No, that's the member function `std::istream::getline()`, not the global `std::getline()`. – 0x499602D2 Feb 19 '14 at 21:28
  • I guess that would work nevermind, I'm just getting confused by the question in general. Of course its not asking for the phone again if loop2 never evaluates to false – Nowayz Feb 19 '14 at 21:28
  • 2
    What are the loop conditions? You might want to use getline or another function which returns a stream as the loop condition. – IllusiveBrian Feb 19 '14 at 21:30
  • Are there two questions here? One about how to include spaces in the getline and another about why its not asking for the phone number again? – Nowayz Feb 19 '14 at 21:31
  • 1
    @Nowayz, No, there's just one. The OP stated that if `getline` was not used, the input could not contain spaces, so `getline` must be used. It's sort of like an attempted solution, but seems like more of a thought-about solution that wasn't worth trying. – chris Feb 19 '14 at 21:32
  • I still can't remotely comprehend what he's asking with "when the loop finishes the logic and returns to the begining, it doesn't ask for the phone again. It just goes through the logic again, any ideas?" assuming that his solution with getline worked fine – Nowayz Feb 19 '14 at 21:35
  • @LuizEduardoF. If you wanted an alternate solution you could just use a char* buffer and call gets instead.. If you're just asking why using cin >> phone doesn't work it's because that's just the way it's designed. It splits input up between spaces – Nowayz Feb 19 '14 at 21:36
  • 1
    @Nowayz, It sounds a lot like one of those "I use `getline`, but it just gets skipped over" questions, which is why I asked about the other logic. Anyway, the `gets` is a non-solution. It will most likely suffer the same problem and it's being removed as of C++14 because of how horrible a function it is. The reason for `cin >> phone` not working is presumably a desire to include spaces in the input when reading instead of stopping at them. – chris Feb 19 '14 at 21:36
  • In the first step, the program does everything ok. But when loop2 becomes false and it go back to while(loop){} to ask a new phone number, it shows: `Telefone (0 para sair):` `Client not recognized. New Client:`. The program doesn't ask a new phone number and that's the question here. – ddz Feb 19 '14 at 21:39
  • Horrible solution for a horribly written question. He could just link the clib statically, lol. – Nowayz Feb 19 '14 at 21:39
  • 1
    @LuizEduardoF., That sounds *exactly* like what would happen if there's a `cin >> something;` in that logic you haven't shown, or if the stream is failing (e.g., if it reached EOF). – chris Feb 19 '14 at 21:40
  • 1
    possible duplicate of [Why does std::getline() skip input after a formatted extraction?](http://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – 0x499602D2 Feb 19 '14 at 22:11

2 Answers2

2

Your claim that the following loop doesn't ask for phone input is highly indicative that std::getline() failed to produce characters because of leading whitespace. My suspicion is that you performed some formatted extraction in your real code that left a newline in the stream. The unformatted extractor std::getline() delimits input upon the aquisition of the newline character, which is the reason you're experiencing this behavior.

Invariably, the solution to this problem is the clear the leading whitespace. This is done using the manipulator std::ws:

std::getline(std::cin >> std::ws, phone);
//           ^^^^^^^^^^^^^^^^^^^

Note: I talk about this in detail in my answer here.

You should also be checking if your input suceeded. This means enclosing the extraction within an if statement so you can ascertain if it successfully produced characters:

if (std::getline(std::cin >> std::ws, phone))
{
    // ...
}
Community
  • 1
  • 1
0x499602D2
  • 87,005
  • 36
  • 149
  • 233
0

Perhaps you need to use a cin.clear() or a cin.ignore() before trying to input again.

More explanation:

That's just from my experience, but according to jrok in this thread: getline() does not work if used after some inputs

"The extraction operations leave the trailing '\n' character in the stream. On the other hand, istream::getline() discards it. So when you call getline after an extraction operator, '\n' is the first character it encounters and it stops reading right there. Put this after before getline call extraction: cin.ignore()"

Community
  • 1
  • 1
Charles Clayton
  • 13,212
  • 10
  • 73
  • 114
  • Perhaps you can explain why? – 0x499602D2 Feb 19 '14 at 21:29
  • That's just from my experience, but according to jrok in this thread: http://stackoverflow.com/questions/12691316/getline-does-not-work-if-used-after-some-inputs, "The extraction operations leave the trailing '\n' character in the stream. On the other hand, istream::getline() discards it. So when you call getline after an extraction operator, '\n' is the first character it encounters and it stops reading right there. Put this after before getline call extraction: cin.ignore()" – Charles Clayton Feb 19 '14 at 21:39
  • I meant to explain why in your answer. This only gives the solution, not the explanation. Your comment is good, you can add that in to your answer. – 0x499602D2 Feb 19 '14 at 21:53