简体   繁体   中英

Safe operation to clear the empty input buffer in C++

I was looking at this post and few other. What happens if ignore() is called when input buffer is already empty? I observed in below code that if ignore() is called when buffer is already empty, it will not work and waits for some character to be entered first.

int main(void)
{
    char myStr[50];
    cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
    cout<<"Enter the String\n";
    cin>>myStr;
    // After reading remove unwanted characters from the buffer
    // so that next read is not affected
    cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
}

cin.clear() after ignore() creates further problem if the buffer is already empty it looks. I guess clearing the buffer after cin() is safe. But what if I do not know the status of input buffer and I clear even when it is already empty? Do I have to check first if input buffer is empty using cin.fail() or something similar if any?

Secondly, cin itself may not be safe as space is not allowed. So getline() is suggested by some SO posts as given here . But does getline() also requires clearing input buffer or is it safe always? Does the code below work without any trouble (it works now, but now sure if it is safe code).

void getString(string& str)
{
    do
    {
        cout<<"Enter the String: ";
        getline(std::cin,str);
    }  while (str.empty());
}

Other SO references: Ref 3

Breaking down main :

int main(void)
{
    char myStr[50];
    cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');

A bad idea, but you noticed that already. There must be a newline in the stream or you sit and wait for one. If the user's not expecting this behaviour you can expect to wait a long time and have a frustrated user. That's a bad scene.

    cout<<"Enter the String\n";
    cin>>myStr;

Also a bad idea, but for a different reason. >> doesn't know it should stop at 49 characters to prevent overflowing myStr . Bad things happen at that 50th character.

    // After reading remove unwanted characters from the buffer
    // so that next read is not affected
    cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');

This one is safe. >> won't consume the newline, or any other whitespace and in order for the stream to hand over the data from the console someone must have hit enter and provided a newline.

}

A general rule of thumb is to not ignore unless you have reason to ignore , and if you have reason, ignore right away. Do not wait until before the next stream operation to ignore , be cause what if this operation is the first? Or the previous operation did not leave anything to ignore ?. ignore after the operation that left what you want ignore d in the stream. So

std::string getfirstword()
{
    std::string firstword;
    if (std::cin >> firstword)
    {
        cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
        return firstword;
    }
    return ""; // or perhaps
    // throw std::runtime_error("There is no first word.");
    // is more appropriate. Your call.
}

is good, but

std::string getfirstword()
{
    cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
    std::string firstword;
    if (std::cin >> firstword)
    {
        return firstword;
    }
    return "";
}

is an offence in the eyes of all that is holy. Don't do it.

As for getline , it gets a line. All of it up to the end of the file or the end of the line, whichever comes first. It also eats the end of the line for you so you don't have to worry about a stray newline harshing your mellow later.

If you only want part of the line, you will have to break it down. Typical usage for this is something along the lines of

std::string line;
if (std::getline(std::cin,line))
{
    std::istringstream istr(line);
    std::string firstword;
    if (istr >> firstword)
    {
        // do something with firstword
    }
    else
    {
        // there is no firstword. Do something else.
    }
}

getline reads everything up to and including the newline. It's no longer in the stream, so I'd consider this safe. You don't have to worry about garbage hanging around on the end of the line. You may have to worry about the next line, though.

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