QTextStream versus iostream (esp. error-handling)



  • Hi there,

    the error-handling in QTextStream is pretty weird.

    Take this example, using only standard C++ library:
    Here I can just query the stream using "operator bool":http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool, and it makes for very nice code.

    @
    #include <iostream>
    #include <sstream>
    #include <string>

    int main()
    {
    using namespace std;

    istringstream iss{" { asdf } " };
    char ch;
    string s;
    do {
        if (iss >> ch) {
            cout << "got " << ch << '\n';
            if (iss >> s) {
                cout << "got " << s << '\n';
                if (iss >> ch) {
                    cout << "got " << ch << '\n';
                    break;
                }
            }
        }
    
        cerr << "~~ got an error\n";
        
    } while (0);
    return 0;
    

    }
    @

    Try writing this nicely with Qt.
    Here's what I have come up with:

    @
    #include <QTextStream>
    #include <QString>

    template<typename T>
    bool get(QTextStream& iss, T& var)
    {
    return (!iss.atEnd() &&
    (iss >> ws, !iss.atEnd()) &&
    (iss >> var, iss.status() == QTextStream::Ok));
    }

    QTextStream cout{stdout, QIODevice::WriteOnly};
    QTextStream cerr{stderr, QIODevice::WriteOnly};

    int main()
    {
    QString str{" { asdf } " };
    QTextStream iss{&str};

    char ch;
    QString s;
    do {
        if (get(iss, ch)) {
            cout << "got " << ch << endl;
            if (get(iss, s)) {
                cout << "got " << s << endl;
                if (get(iss, ch)) {
                    cout << "got " << ch << endl;
                    break;
                }
            }
        }
    
        cerr << "~~ got an error" << endl;
        
    } while (0);
    return 0;
    

    }
    @

    So as far as I can see, I need to create my own function to do error handling. It's the function get(): It checks for eof and stream errors.

    Is there any better way of doing this?

    Thanks.



  • I really like the semantics and behaviour of the standard C++ library.

    Here's how to get QTextStream to work the same way as C++ standard library (this is based on tests, not on detailed analysis: if you find some discrepancy please notify me!):

    @
    template<typename T>
    bool get(QTextStream& iss, T& var)
    {
    return (!iss.atEnd() &&
    (iss >> ws, !iss.atEnd()) &&
    (iss >> var, iss.status() == QTextStream::Ok));
    }

    bool qt_getline(QTextStream& iss, QString& line)
    {
    return (!(iss.atEnd()) &&
    (line = iss.readLine(), (!iss.atEnd() || line.size())));
    }
    @

    Here's some Qt code using those functions:
    @
    #include <QTextStream>
    #include <QTextStream>

    QTextStream cout{stdout, QIODevice::WriteOnly};
    QTextStream cin{stdin, QIODevice::ReadOnly};

    template<typename T>
    bool get(QTextStream& iss, T& var)
    {
    return (!iss.atEnd() &&
    (iss >> ws, !iss.atEnd()) &&
    (iss >> var, iss.status() == QTextStream::Ok));
    }

    bool qt_getline(QTextStream& iss, QString& line)
    {
    return (!(iss.atEnd()) &&
    (line = iss.readLine(), (!iss.atEnd() || line.size())));
    }

    #define T1

    int main()
    {
    #ifdef T1

    QString str;
    while (get(cin, str)) {
    cout << "got: " << str << endl;
    }
    cout << "rem: " << str << endl;

    #elif (defined T2)

    char ch;
    while (get(cin, ch)) {
    cout << "got: " << ch << endl;
    }
    cout << "rem: " << ch << endl;

    #elif (defined T3)

    QString str;
    while (qt_getline(cin, str)) {
    cout << "got: " << str << endl;
    }
    cout << "rem: " << str << endl;

    #endif

    return 0;
    }
    @

    Here's the equivalent code using standard C++ library:
    @
    #include <iostream>
    #include <string>

    #define T1

    int main()
    {
    using namespace std;

    #ifdef T1

    string str;
    while (cin >> str) {
    cout << "got: " << str << endl;
    }
    cout << "rem: " << str << endl;

    #elif (defined T2)

    char ch;
    while (cin >> ch) {
    cout << "got: " << ch << endl;
    }
    cout << "rem: " << ch << endl;

    #elif (defined T3)

    string str;
    while (getline(cin, str)) {
    cout << "got: " << str << endl;
    }
    cout << "rem: " << str << endl;

    #endif

    return 0;
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.