简体   繁体   中英

cin.getline() strange behavior

the following is an exercise from a book for practicing some class inheritance. But the problem is in the client, not with the class design. (BaseCore, baseDMA, lacksDMA and hasDMA are the classes BTW).

// usedma.cpp -- polymorphic example (compile with dma.cpp)

#include <iostream>
#include "dma.h" // includes <iostream>

const int ELEMENTS = 1;
const int LENGTH = 30;

int main()
{
    using std::cin;
    using std::cout;

    BaseCore *pArr[ELEMENTS];
    char tempDate[LENGTH];
    char kind;

    for (int i = 0; i < ELEMENTS; i++)
    {
        cout << "\nEntering data for element #" << i + 1 << "\n\n";
        cout << "Enter the date it was created: ";
        cin.getline(tempDate, LENGTH - 1);
        cout << "Enter 1 for baseDMA, 2 for lacksDMA, or 3 for hasDMA: ";
        while (cin >> kind && kind != '1' && kind != '2' && kind != '3')
            cout <<"Wrong data. Please, try again: ";
        while (cin.get() != '\n')
            continue;
        char tempLabel[LENGTH];
        int tempRating;
        cout << "Enter the label: ";
        cin.getline(tempLabel, LENGTH - 1);
        cout << "Enter the rating: ";
        cin >> tempRating;
        if (kind == '1') // baseDMA
            pArr[i] = new baseDMA(tempDate, tempLabel, tempRating);
        if (kind == '2') // lacksDMA
        {
            char tempColor[LENGTH];
            cout << "Enter the color: ";
            cin.getline(tempColor, LENGTH - 1);
            pArr[i] = new lacksDMA(tempDate, tempLabel, tempColor, tempRating);
        }
        if (kind == '3') // hasDMA
        {
            char tempStyle[LENGTH];
            cout << "Enter the style: ";
            cin.getline(tempStyle, LENGTH - 1);
            pArr[i] = new hasDMA(tempDate, tempLabel, tempStyle, tempRating);
        }
        while (cin.get() != '\n')
            continue;
    }

    cout << "\n";
    for (int i = 0; i < ELEMENTS; i++)
    {
        pArr[i]->View();
        cout << "\n";
    }
    cout << "Done.\n";

    std::cin.get();
    return 0;
}

Sample execution:

Entering data for element #1

Enter the date it was created: 2012.01.01

Enter 1 for baseDMA, 2 for lacksDMA, or 3 for hasDMA: 2

Enter the label: lacksDMA

Enter the rating: 15

Enter the color: blue

Date of creation: 2012.01.01

Label: lacksDMA

Rating: 15

Color:

Done.

It seems the Color member gets assigned the null character. This behavior happens inside both the if (kind == '2') and if (kind == '3') statements (with the style member in this case).

If I put a cin.get(); just before cin.getline() it works fine but I have to press an extra key to make the program ask for input.

Why is this happening? If there was a '\\n' pending in the input queue, cin.getline() would discard it and put '\\0' in the variable, I can understand that. But the program asks me for the input for color and let's me enter it normally. Also, if I put a cin.get(), then the program shouldn't be waiting for an extra key stroke in the execution, it just should get rid of that extra '\\n'. What am I missing here?

cout << "Enter the rating: ";
        cin >> tempRating;

Unlike, istream::getline() , operator>> leaves the trailing \\n in the stream. It causes the next call to getline inside one of your if statements to get empty input.

The stream is empty when control flow reaches while (cin.get() != '\\n') statement at the end of for loop - it's waiting for input and it appears as if you're still inputing color.

Call cin.ignore() right after and it'll work.

Note that this kind of bug is immediately obvious if you put a "debugging cout" right after the input statement for color. There's one more issue with the way you're getting tempRating . If you enter invalid input, say "xy", the erros flags will be set on cin and the program will enter an infinite loop. Always check whether input operations suceeded.

If I put a cin.get(); just before cin.getline() it works fine but I have to press an extra key to make the program ask for input.

It seems to me that when you don't put the cin.get(), your getline is getting an empty character. Then, when you put the cin.get, you get that empty character and the your getline works fine..

But you should definitely go in debug to see exactly what's happening!

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