3.2.1.  Streams and Dates

[ fromfile: qtcore.xml id: qstreams ]

In several of our earlier examples, you saw instances of QTextStream, which behave in a similar way to the C++ Standard Library's global iostream objects. When we use them to facilitate interactions with standard input (the keyboard) and output (the screen), we like to give them the familiar names cin, cout, and cerr. We have placed these definitions, along with some other useful functions, into a namespace so that they can be easily #included in any program.

Example 3.1. src/qstd/qstd.h

[ . . . . ]
namespace qstd {

     // declared but not defined:
     extern QTextStream cout;
     extern QTextStream cin;
     extern QTextStream cerr;

     // function declarations:
     bool yes(QString yesNoQuestion);
     bool more(QString prompt);
     int promptInt(int base = 10);
     double promptDouble();
     void promptOutputFile(QFile& outfile);
     void promptInputFile(QFile& infile);
};
[ . . . . ]

<include src="src/qstd/qstd.h" href="src/qstd/qstd.h" id="qstdh" allfiles="1" mode="cpp"/>


Example 3.1 declares the iostream-like QTextStream objects, and Example 3.2 contains the required definitions of these static objects.

Example 3.2. src/qstd/qstd.cpp

[ . . . . ]

QTextStream qstd::cout(stdout, QIODevice::WriteOnly);
QTextStream qstd::cin(stdin, QIODevice::ReadOnly);
QTextStream qstd::cerr(stderr, QIODevice::WriteOnly);

/* Namespace members are like static class members */
bool qstd::yes(QString question) {
    QString ans;
    cout << QString(" %1 [y/n]? ").arg(question);
    cout.flush();
    ans = cin.readLine();
    return (ans.startsWith("Y", Qt::CaseInsensitive));
}

<include src="src/qstd/qstd.cpp" mode="cpp" href="src/qstd/qstd.cpp" id="qstdcpp" segid="streamdefs"/>


QTextStream works with Unicode QString and other Qt types, so we use it instead of iostream in most of our examples henceforth. Example 3.3 uses QTextStream objects and functions from the qstd namespace. It also uses some of the QDate member functions and displays dates in several different formats.

Example 3.3. src/qtio/qtio-demo.cpp

[ . . . . ]
#include <qstd.h>

int main() {
    using namespace qstd;
    QDate d1(2002, 4,1), d2(QDate::currentDate());
    int days;
    cout << "The first date is: " << d1.toString()
            << "\nToday's date is: " 
            << d2.toString("ddd MMMM d, yyyy")<< endl;

    if (d1 <  d2)
        cout << d1.toString("MM/dd/yy") << " is earlier than " 
                << d2.toString("yyyyMMdd") << endl;

    cout << "There are " << d1.daysTo(d2) 
            << " days between "
            << d1.toString("MMM dd, yyyy") << " and " 
            << d2.toString(Qt::ISODate)  << endl;

    cout << "Enter number of days to add to the first date: " 
            <<  flush;
    days = promptInt();
    cout << "The first date was " << d1.toString()
            << "\nThe computed date is " 
            <<  d1.addDays(days).toString() << endl;
    cout << "First date displayed in longer format: "
            << d1.toString("dddd, MMMM dd, yyyy")  << endl;
[ . . . . ]

<include src="src/qtio/qtio-demo.cpp" href="src/qtio/qtio-demo.cpp" mode="cpp" id="qtiodemocpp"/>


You can build and run this program from its directory in the src tree. The project file listed in Example 3.4 finds the qstd header and implementation files by using relative paths.

Example 3.4. src/qtio/qtio.pro

CONFIG += debug console
DEFINES += QT_NOTHREAD_DEBUG

CONFIG -= moc
INCLUDEPATH += . ../qstd
DEPENDPATH += ../qstd

# Input
SOURCES += qtio-demo.cpp qstd.cpp
HEADERS += qstd.h

<include src="src/qtio/qtio.pro" href="src/qtio/qtio.pro" id="qtiopro" mode="text"/>


Here is the output of this program.

The first date is: Mon Apr 1 2002
Today's date is: Wed January 4, 2006
04/01/02 is earlier than 20060104
There are 1374 days between Apr 01, 2002 and 2006-01-04
Enter number of days to add to the first date: : 1234
The first date was Mon Apr 1 2002
The computed date is Wed Aug 17 2005
First date displayed in longer format: Monday, April 01, 2002