简体   繁体   English

cin.getline()奇怪的行为

[英]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). (BaseCore,baseDMA,缺少DMA和hasDMA是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 输入元素#1的数据

Enter the date it was created: 2012.01.01 输入创建日期:2012.01.01

Enter 1 for baseDMA, 2 for lacksDMA, or 3 for hasDMA: 2 输入1表示baseDMA,输入2表示lacksDMA,输入3表示hasDMA:2

Enter the label: lacksDMA 输入标签:lacksDMA

Enter the rating: 15 输入评分:15

Enter the color: blue 输入颜色:蓝色

Date of creation: 2012.01.01 创作日期:2012.01.01

Label: lacksDMA 标签:缺乏DMA

Rating: 15 评分:15

Color: 颜色:

Done. 完成。

It seems the Color member gets assigned the null character. 似乎为Color成员分配了空字符。 This behavior happens inside both the if (kind == '2') and if (kind == '3') statements (with the style member in this case). 这种行为发生在if (kind == '2')if (kind == '3')语句中(在这种情况下使用样式成员)。

If I put a cin.get(); 如果我放一个cin.get(); just before cin.getline() it works fine but I have to press an extra key to make the program ask for input. 就在cin.getline()之前它工作正常但我必须按一个额外的键才能让程序请求输入。

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. 如果输入队列中有一个'\\ n'挂起,cin.getline()将丢弃它并在变量中放入'\\ 0',我可以理解。 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'. 另外,如果我放了一个cin.get(),那么程序不应该等待执行中的额外键击,它应该摆脱额外的'\\ n'。 What am I missing here? 我在这里错过了什么?

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

Unlike, istream::getline() , operator>> leaves the trailing \\n in the stream. istream::getline()operator>>在流中留下尾随\\n It causes the next call to getline inside one of your if statements to get empty input. 它导致在你的一个if语句中调用getline以获得空输入。

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. 当控制流到达for循环结束while (cin.get() != '\\n')语句时,流是空的 - 它正在等待输入,看起来好像你还在输入颜色。

Call cin.ignore() right after and it'll work. cin.ignore()调用cin.ignore()并且它会工作。

Note that this kind of bug is immediately obvious if you put a "debugging cout" right after the input statement for color. 请注意,如果您在输入语句后面放置一个“调试cout”,那么这种错误就会很明显。 There's one more issue with the way you're getting tempRating . 你获得tempRating的方式还有一个问题。 If you enter invalid input, say "xy", the erros flags will be set on cin and the program will enter an infinite loop. 如果输入无效输入,例如“xy”,则会在cin上设置错误标志,程序将进入无限循环。 Always check whether input operations suceeded. 始终检查输入操作是否成功。

If I put a cin.get(); 如果我放一个cin.get(); just before cin.getline() it works fine but I have to press an extra key to make the program ask for input. 就在cin.getline()之前它工作正常但我必须按一个额外的键才能让程序请求输入。

It seems to me that when you don't put the cin.get(), your getline is getting an empty character. 在我看来,当你不放cin.get()时,你的getline会得到一个空字符。 Then, when you put the cin.get, you get that empty character and the your getline works fine.. 然后,当你输入cin.get时,你得到那个空字符,你的getline工作正常..

But you should definitely go in debug to see exactly what's happening! 但是你一定要进行调试,看看究竟发生了什么!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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