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 T1QString 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;
}
@