简体   繁体   中英

C++ cout in while loop prints twice

I adapted this code from Programming: Principles and Practice in C++ by Bjarne Stroustrup in an attempt to check that the input given was valid:

#include <iostream>
using namespace std;

int main()
{
    cout << "Please enter your first name and age: ";
    string first_name = "???";
    int age = -1;
    cin >> first_name >> age;

    while (!cin) {
        cin.clear();
        cout << "Sorry, can you enter that again? ";
        cin >> first_name >> age;
    }

    cout << "Hello, "<<first_name<<"! (age "<<age<<")\n";
    return 0;
}  

This works as expected, except that the words "Sorry, can you enter that again? " are being printed twice, once before the second input and once after.

Anyone know why this might be happening? Thanks.

It's not enough to clear the fail bit, you also have to clear any remaining characters in the input buffer. Furthermore, the code looks more convoluted than necessary. The following works:

std::string name;
int age;

std::cout << "Please enter your name & age: ";

while (not (std::cin >> name >> age)) {
    std::cout << "Sorry, can you enter that again? ";
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

std::cout << "Hello " << name << " (" << age << ")\n";

Oh yeah, and don't forget to flush the output stream, I don't think this will be done automatically for you.

That said, the standard input/output streams are, well, streams , so they aren't really suitable for interactive input anyway. You should use a proper library for that, such as readline or ncurses .

To illustrate why this is important, imagine the user enters “ foo42 ” and presses return. You'd expect the program to now say “Sorry, can you enter that again?” but it doesn't. Rather, it docilely waits for the user to enter a second token. That's certainly not what you'd expect from a usability perspective.

It depends on what you input!

  • Input "Tim 29" : Works, "Hello Tim(29)".

  • Input "Tim Tom 29" : Works, one repetition, "Hello Tom(29)".

  • Input "Tim Tom Tina 29" : Works, two repetitions, "Hello Tina(29)".

I'm assuming that you're trying the third one. The first failure is Tom , who isn't a number. Resetting the error state is fine, but it doesn't get rid of Tom . We still need one more failed attempt just to consume him (failing on Tina , who at that point isn't a number). Only then are we ready for Tina .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM