简体   繁体   中英

cin and switch odd behaviour

So I'm having some problems when using cin and switch statements. First, the program prompts for an int :

cout << "How many registers would you like to use?: ";
cin >> kassor;

Later on, the user is asked to make a choice:

    cout << endl << "Press \"S\" to run the queue simulator and/or make a timestep." << endl;
    cout << "Press \"Q\" to quit." << endl << endl;
    cout << "Choice: ";
    cin >> choice;

    switch (choice)
    {
        case 's':
        case 'S':
        {
            cout << "test";
            nya = newCustomers();
            break;
        }
        case 'q':
        case 'Q':
        {
            return 0;
        }
    }

Here, the 'q' option works fine, but the 's' option does not. It 'hangs', as if still waiting for input. I have tried various cin.ignore() and such, but to no avail.

What puzzles me is that

switch (choice)
{
    case 's':
    case 'S':
    {
        cout << "test";
        nya = newCustomers();
        break;

Gives nothing, but the following:

switch (choice)
    {
        case 's':
        case 'S':
        {
            cout << "test";
            cin.ignore(1024, '\n');
            nya = newCustomers();
            break;

outputs 'test'.

My main question here is: Is the problem cin or something in the case: s ?

Thank's in advance :

It looks like the function newCustomers is getting hung up on a stray character or two after the input to choice . That would explain why the ignore call "fixes" the problem, and it's the solution suggested in the comment by @TheBuzzSaw.

To see this more clearly, change

cout << "test";

to

cout << "test\n";

or to

cout << "test" << std::endl;

On some systems the console is line-buffered, so you won't see any output until the program writes a newline. Inserting endl flushes the output buffer, so you should see the message even if subsequent code hangs. Or change it to:

cerr << "test\n";

cerr is more aggressive about flushing buffers, precisely because it's used for error output that you don't want to miss.

Short Answer: I believe cin is failing somewhere or it is the cause of unexpected behavior I cannot pinpoint it without more code.

Edit: I cannot post a comment on your post, so I figured I would post here. The "hanging" could be an infinite loop. If you are doing something like what I am doing and looping to get input and fail to clear the error bits cin will constantly fail. If you are not cout'ing something each time you ask for input it could just be quietly sitting there looping through that input-gathering function. Put breakpoints in all of your loops and step through with the debugger to verify none of your loops are infinite looping.

Try adding a std::cin.clear(); before the .ignore() in your second test case. See if that stops your hanging.

Explanation:

cin can fail. This can cause weird behavior. A common way for it to fail is if you are reading into an integer and you get character input. Once cin fails it sets a fail bit and from then on, cin does not behave like you would expect.

I would recommend not using a bare cin >> choice, because it can fail and you wont know it. I would abstract this out to a method that gets the proper input you want.

I personally keep a tiny utility library(.h) and .cpp around to include in projects where I am using common functionality I have already coded.

I have a readIntBetween() function which accepts 2 integers and reads from standard input an integer between those two numbers. If the user does not provide the right input (integer over or under bounds, or input containing a character) I ask them to re-enter the input.

In this function I make sure to clear the fail bits when I have detected a failure, and I ignore something like 200 characters to "flush" it out.

Here is the code to my readIntBetween function. I hope it helps you diagnose your error and fix it:

int readIntBetween(int lower, int upper, std::string prompt)
{
    bool goodVal = false;
    int value = -1;
    do
    {
        std::cout << prompt ;
        std::cin >> value;

        if ( value >= lower && value <= upper)//check to make sure the value is in between upper and lower
            goodVal = true;
        else
        {
            if(std::cin.fail())
            {
                std::cout << "\tError - invalid format for integer number" << std::endl;

                //clear all status bit including fail bit
                std::cin.clear();

                //flush input buffer to discard invalid input
                std::cin.ignore(1000, '\n');

            }
            else
            std::cout << "Value is not valid, must be between " << lower<<" and "<<upper<<"."<<std::endl;
        }



    }while(!goodVal);
    return value;
}

If your cin is being used inside a loop, I recommend a different approach.

char buffer[64];
cin.getline(buffer, 64);

char choice = buffer[0];

switch (choice)
{
    ...
}

It is possible your cin is not being reset, and any extraneous characters are being fed into the subsequent requests for input. Grab more input and only process its first character.

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