读入char变量后,QTextStream无法使用

时间:2014-03-10 20:07:20

标签: c++ qt

所以这是我正在编写的作业的客户端部分。

#include "coordinate.h"
#include "gpscoord.h"
#include <QString>
#include <QTextStream>
#include <QCoreApplication>

QTextStream cout(stdout);
QTextStream cin(stdin);

int main(int argc, char* argv[])
{
    QCoreApplication app(argc, argv);

    GPSCoord gps;
    int degrees, minutes, seconds;
    char cardinalDirection;

    cout << "\nPlease enter values for the latitude.." << endl;
    cout << "Degrees : " << flush;
    cin >> degrees;
    cout << "Minutes : " << flush;
    cin >> minutes;
    cout << "Seconds : " << flush;
    cin >> seconds;
    cout << "Cardinal Direction : " << flush;
    cin >> cardinalDirection;

    gps.setCoord(degrees, minutes, seconds, cardinalDirection);

    cout << "\nPlease enter values for the longitude.." << endl;
    cout << "Degrees : " << flush;
    cin >> degrees;
    cout << "Minutes : " << flush;
    cin >> minutes;
    cout << "Seconds : " << flush;
    cin >> seconds;
    cout << "Cardinal Direction : " << flush;
    cin >> cardinalDirection;

    gps.setCoord(degrees, minutes, seconds, cardinalDirection);

    cout << "\nGeographic Coordinates\t: " << gps.toString(false) << endl << "Decimal Coordinates\t: " << gps.toString(true) << endl;

    return 0;
}

上半场工作正常。但是只要我输入第一个cardinalDirection的输入,程序就会设置坐标,然后只是一个接一个地打印输出的其余部分,并且不想输入任何内容。这是输出。

Please enter values for the latitude..
Degrees : 25
Minutes : 46
Seconds : 3
Cardinal Direction : S

Please enter values for the longitude..
Degrees : Minutes : Seconds : Cardinal Direction : 
Geographic Coordinates  : 0ø, 0', 0", S ; 25ø, 46', 3", 

Decimal Coordinates : 0 ; 25.775

我错过了一些愚蠢的事吗?无法想象会导致这种情况的原因。

2 个答案:

答案 0 :(得分:2)

Qt有一个错误QTBUG-37394,你的代码也有错误:)

  • 您的错误:当您将单个字符读入charQChar时,您将读取终止任何先前输入的空格。您必须使用ws(stream)来删除流中的现有空格。

  • Qt bug:即使输入流中已经有空白字符,字符读取操作符也会等待非空白数据。

详细

它不起作用的原因是你作为一个角色消费的是上一个行的换行符。

  1. 输入20个arcseconds后,字符缓冲区的内容为:

    { '2', '0', '\n' }
    
  2. 运行cin >> arcseconds后,字符缓冲区为:

    { '\n' }
    
  3. 然后,cin >> cardinalDirection运行,并等待新输入,因为缓冲区中没有任何有趣的东西(这就是Qt错误:它不应该等待)。假设您输入N,字符缓冲区现在是:

    { '\n', 'N', '\n' }
    

    现在,operator>>(char&) 正确地检索缓冲区中的第一个字符,无论它是什么。因此它检索'\n'并成功(这是你的错误:你应该首先摆脱空白)。字符缓冲区现在包含:

    { 'N', '\n' }
    
  4. 问题是现在你读经度了。缓冲区包含非空白数据,以下执行立即cin >> degrees

    正如预期的那样,将N读入整数会失败,并且不会再处理任何输出。

    如果你输入一个数字,比如说1,它就会成功,当你要求学位,分钟,秒,基本方向然后在跳过学位时要求分钟时,你会有好奇的交换。

  5. 修复是强行跳过数据中的空白。 QTextStream::ws()方法的文档有这样一句话:

      

    当逐个字符地读取流时,此功能非常有用。

    #include <QTextStream>
    #include <QCoreApplication>
    
    QTextStream cout(stdout);
    QTextStream cin(stdin);
    
    class GPSCoord {
       QString dir;
    public:
       void setCoord(int, int, int, char d) { dir.append(d); }
       QString toString(bool) const { return dir; }
    };
    
    int main(int argc, char* argv[])
    {
        QCoreApplication app(argc, argv);
        GPSCoord gps;
        int degrees, minutes, seconds;
        char cardinalDirection;
    
        cout << "\nPlease enter values for the latitude.." << endl;
        cout << "Degrees : " << flush;
        cin >> degrees;
        cout << "Minutes : " << flush;
        cin >> minutes;
        cout << "Seconds : " << flush;
        cin >> seconds;
        cout << "Cardinal Direction : " << flush;
        ws(cin) >> cardinalDirection;
    
        gps.setCoord(degrees, minutes, seconds, cardinalDirection);
    
        cout << "\nPlease enter values for the longitude.." << endl;
        cout << "Degrees : " << flush;
        cin >> degrees;
        cout << "Minutes : " << flush;
        cin >> minutes;
        cout << "Seconds : " << flush;
        cin >> seconds;
        cout << "Cardinal Direction : " << flush;
        ws(cin) >> cardinalDirection;
    
        gps.setCoord(degrees, minutes, seconds, cardinalDirection);
    
        cout << "\nGeographic Coordinates\t: " << gps.toString(false) << endl
             << "Decimal Coordinates\t: " << gps.toString(true) << endl;
        return 0;
    }
    

答案 1 :(得分:-1)

cin不喜欢您的char cardinalDirection。当我将声明更改为char cardinalDirection[2];

时,它适用于我

修改 正如Kuba Ober所指出的,这可能导致缓冲区溢出情况。在现有代码中没有真正的输入验证或错误处理,但我应该在我自己的答案中更加彻底。

如果您希望限制为特定数量的字符,则可以执行以下操作:

char cardinalDirection;

...

cout << "Seconds : " << flush;
cin >> seconds;

//read everything from the buffer to clear
//it out - there are still some newlines
//in the buffer from previous input
cin.readLine();

cout << "Cardinal Direction : " << flush;
//read one character from the input and convert it to a char
cardinalDirection = cin.readLine(1)[0].toAscii();

//in case the user entered more than 1 character, clear out the buffer again
//so that the next inputs will work correctly
cin.readLine();

...