170

I'm using Qt4 and C++ for making some programs in computer graphics. I need to be able to print some variables in my console at run-time, not debugging, but cout doesn't seem to work even if I add the libraries. Is there a way to do this?

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
lesolorzanov
  • 3,147
  • 6
  • 31
  • 48
  • 3
    Can you elaborate on cout not working because that should certainly work. Do you get a compile error. Can you show a code example of cout that isn't working for you? Also explain how you are running the application. Are you running it from a console or from within an IDE and not seeing output to its output window? – Arnold Spence Oct 07 '10 at 22:48
  • Just for completeness: @ArnoldSpence - without libraries, I get `error: ‘cout’ was not declared in this scope`; with iostream, I get `error: no match for ‘operator<](((std::basic_ostream&)(& std::cout)), ...`; using the commands in the answer instead works fine. – sdaau Jun 10 '15 at 14:21
  • It is difficult to offer solutions when the problem statement is simply, "it doesn't work". Please [edit] your question to give a more complete description of what you expected to happen and how that differs from the actual results. See [ask] for hints on what makes a good explanation. – Toby Speight Feb 14 '17 at 13:46
  • In this case, you should explicitly specify that those "variables" are Qt-specific objects (such as `QString`). – user202729 Aug 06 '18 at 10:47

12 Answers12

212

If it is good enough to print to stderr, you can use the following streams originally intended for debugging:

#include<QDebug>

//qInfo is qt5.5+ only.
qInfo() << "C++ Style Info Message";
qInfo( "C Style Info Message" );

qDebug() << "C++ Style Debug Message";
qDebug( "C Style Debug Message" );

qWarning() << "C++ Style Warning Message";
qWarning( "C Style Warning Message" );

qCritical() << "C++ Style Critical Error Message";
qCritical( "C Style Critical Error Message" );

// qFatal does not have a C++ style method.
qFatal( "C Style Fatal Error Message" );

Though as pointed out in the comments, bear in mind qDebug messages are removed if QT_NO_DEBUG_OUTPUT is defined

If you need stdout you could try something like this (as Kyle Strand has pointed out):

QTextStream& qStdOut()
{
    static QTextStream ts( stdout );
    return ts;
}

You could then call as follows:

qStdOut() << "std out!";
Antonio
  • 10,457
  • 6
  • 30
  • 45
Goz
  • 58,120
  • 22
  • 114
  • 192
  • 1
    I asked ,while not debugging, there must be a function that allows me to write messages in console during runtime, not during debugging. – lesolorzanov Oct 07 '10 at 22:19
  • 11
    Despite its name, that function is not related to debugging with a debugger. It is a convenience function that Qt provides for sending output to stderr that can be removed from compilation with a define. So it is an alternative for achieving output to the console at runtime. – Arnold Spence Oct 07 '10 at 23:23
  • Thank you all a lot, I'm using this :). I guess there is no need then for me to write any of the code I used. Thanks! This has been super usefull. – lesolorzanov Oct 14 '10 at 00:54
  • 63
    Please don't use qDebug for all console output. Only use it for true debug prints use qWarning, qCritical and qFatal for errors and warnings. Because qDebug statements can be removed when compiling with QT_NO_DEBUG_OUTPUT to save performance and stop the application from cluttering up the output. – JustMaximumPower Oct 17 '12 at 13:14
  • 1
    QTextStream dooesn't flush the output, so if it used to show dynamic process, it will stall until program closes – Swift - Friday Pie Jul 13 '20 at 17:25
  • So add an appropriate flush statement to the answer? – Matthias Urlichs Aug 01 '20 at 12:55
  • If you add << endl, the stream will also be flushed. This is not the case if you use "\n" – MiB_Coder Sep 18 '20 at 20:29
152

I found this most useful:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
Kuba hasn't forgotten Monica
  • 88,505
  • 13
  • 129
  • 275
CapelliC
  • 57,813
  • 4
  • 41
  • 80
  • 15
    I don't know why answer isn't accepted, but it's the most useful for sure. – Semyon Danilov Feb 27 '14 at 18:30
  • 5
    Agreed. stderr is for, well, errors (and debugging). This should be the accepted answer because it's the only one which uses stdout AND qt. – Marshall Eubanks Sep 01 '14 at 06:41
  • 1
    This one worked for me - and seemed like the correct way to output info via cout – Michael Vincent Jan 06 '15 at 10:19
  • 2
    If you incorporate the information from Goz's answer about how to print errors/warnings, along with a bit of information (sadly lacking from Goz's answer but present in the comments below it) about what `qDebug()` etc actually do, this will be by far the superior answer (IMO it's already superior since OP is asking for something to replace `std::cout`, but 40ish voters appear not to agree). – Kyle Strand Mar 09 '15 at 21:00
  • `QTextStream qStdout() { return {stdout}; }` might be a useful way to wrap this, consistent with `qWarning()` etc. And maybe some `static` state to avoid temporary streamage? – Yakk - Adam Nevraumont Mar 10 '15 at 19:18
  • One downside of QTextStream, is it doesn't print out all the Q-Types as easily as QDebug or QInfo, etc. For example: `qDebug() << widget->geometry();` v. `out << widget->geometry().x() << ", " << widget->geometry().y() //....` – phyatt Mar 16 '17 at 19:12
  • And should I instantiate this only once? Or can I do this per pethod? – Tomáš Zato - Reinstate Monica Apr 19 '17 at 21:07
  • @TomášZato: as you like... I would probably declare an inline in a .h (maybe toStdout.h), so would be easy to call – CapelliC Apr 19 '17 at 21:56
  • Note that using << endl will also flush the stream, while "\n" does not. – MiB_Coder Sep 18 '20 at 20:30
  • @MiB_Coder: that's by design in stdlib::streams, no ? Also, right now I don't remember if "\n" does the platform specific translation (at least on Windows, endl should be "\r\n"). – CapelliC Sep 18 '20 at 20:40
  • @CapelliC: As discussed in the other answers, if you write out() << "Hello\n", it will print when out is destroyed (e.g. at the end of the program), while out() << "Hello" << endl will print immediately. The c++ standard on the other hand says: endl is equivalent with "\n". – MiB_Coder Sep 19 '20 at 15:07
37

Writing to stdout

If you want something that, like std::cout, writes to your application's standard output, you can simply do the following (credit to CapelliC):

QTextStream(stdout) << "string to print" << endl;

If you want to avoid creating a temporary QTextStream object, follow Yakk's suggestion in the comments below of creating a function to return a static handle for stdout:

inline QTextStream& qStdout()
{
    static QTextStream r{stdout};
    return r;
}

...

foreach(QString x, strings)
    qStdout() << x << endl;

Remember to flush the stream periodically to ensure the output is actually printed.

Writing to stderr

Note that the above technique can also be used for other outputs. However, there are more readable ways to write to stderr (credit to Goz and the comments below his answer):

qDebug() << "Debug Message";    // CAN BE REMOVED AT COMPILE TIME!
qWarning() << "Warning Message";
qCritical() << "Critical Error Message";
qFatal("Fatal Error Message");  // WILL KILL THE PROGRAM!

qDebug() is closed if QT_NO_DEBUG_OUTPUT is turned on at compile-time.

(Goz notes in a comment that for non-console apps, these can print to a different stream than stderr.)


NOTE: All of the Qt print methods assume that const char* arguments are ISO-8859-1 encoded strings with terminating \0 characters.

Community
  • 1
  • 1
Kyle Strand
  • 14,120
  • 3
  • 59
  • 143
  • 1
    `QTextStream qStdout() { static QTextStream r{stdout}; return r; }`? – Yakk - Adam Nevraumont Mar 10 '15 at 19:18
  • 1
    @Yakk Good suggestion! I'll incorporate into my answer. – Kyle Strand Mar 10 '15 at 19:34
  • qFatal() gets an error when compiling with QT5. a read a post, that it wasn't ment to (be there/work) anyway... don't use it! :) – relascope May 28 '15 at 22:05
  • @relascope I'm not sure what you mean by "gets an error," but the documentation does indicate that it will cause a core dump on Unix, so I've indicated that in the answer. – Kyle Strand May 28 '15 at 22:40
  • /* sorry, didn't find the article anymore but */ qFatal("Hello Fatal"); / is the way to use it (on QT5), it send SIGABRT !!! when compiling */ qFatal() << "Hello Fatal"; / ./qfatal/main.cpp: In function 'int main(int, char**)': ../qfatal/main.cpp:13:12: error: no matching function for call to 'QMessageLogger::fatal()' qFatal() << "Hello Fatal"; [...] qlogging.h:107:10: note: candidate expects 1 argument, 0 provided */ – relascope Jun 01 '15 at 22:33
  • @relascope Ah, I see, the function itself is supposed to take the error message string. I've edited my example; all four lines now compile correctly and behave as expected. – Kyle Strand Jun 01 '15 at 22:38
  • You don't want to be suggesting that people create a new text stream on every iteration of the loop. Even if the text stream had an optimization to make this cheap (it doesn't), it still would have very bad code smell to it. Obviously I just realized that you also comment that it's wrong. Here's what I suggest: I rolled back the edit. Sorry for the noise. – Kuba hasn't forgotten Monica Apr 08 '16 at 13:20
  • @KubaOber No problem. I actually *did* hope (if not assume) that since it's using an already-existing text stream in the constructor, it *would* have an optimization to make this cheap. But either way the "right" way to do this is indeed the function-returning-reference-to-static approach. Thanks for reminding me of this; I'll edit to simplify a bit. – Kyle Strand Apr 08 '16 at 15:46
  • `stdout` is not a text stream, it's a pointer a C file object. Apart from the buffers in `QTextStream`, you're also at the very least constructing and destructing a temporary `QIODevice` every time, too. That's how a `QTextStream` accesses the file: by wrapping it in a `QIODevice` subclass (I forget which one, probably `QFile`). – Kuba hasn't forgotten Monica Apr 08 '16 at 16:54
  • @KubaOber Ah, that also clarifies why `stdout` isn't from a namespace, which I'd been wondering but hadn't looked into. – Kyle Strand Apr 08 '16 at 18:17
  • @KyleStrand The C++98 standard, in [lib.c.files] says that stderr, stdin and stdout are macros and obviously macros can't be in any namespace. From [Jakub Jelinek](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52195#c1). That also tells you why macros are so bad, and unless you absolutely need them, they have no place in modern C++ – Kuba hasn't forgotten Monica Apr 08 '16 at 19:43
  • @KyleStrand E.g. in C++ if you include ``, you can't use any symbols named stdin, stdout, stderr, in *any* namespace :( They behave like keywords, except that the compiler will give you weird diagnostics and/or silently miscompile your code. E.g. on OS X/clang, a public `foo::stdin` symbol becomes `foo::__stdinp`, and any code that might use it will not link iff it happens not to include ``. Global namespace pollution by macros is frightening, frankly said. – Kuba hasn't forgotten Monica Apr 08 '16 at 19:52
  • @KubaOber I actually use them quite a bit, mostly to work around what I perceive as shortcomings in the language. For instance, I have a macro that simply takes the name of a member function and creates a lambda that copy-captures `this` and otherwise duplicates the member function's signature. I find this easier than [remembering the oddities of generic capturing in C++14 for various compilers](http://stackoverflow.com/q/34889310/1858225) and more readable and typesafe than using `std::bind(&ClassName::functionName, this, std::placeholders::_1, .... )`. – Kyle Strand Apr 08 '16 at 20:54
  • @KyleStrand This can be done with a function, no need for a macro :) – Kuba hasn't forgotten Monica Apr 10 '16 at 00:07
  • @KubaOber If nothing else, the function would require the 'this' pointer explicitly as one of its arguments, and I believe you'd need the fully scoped name of the function with ampersand function-pointer syntax as well. That's simply not as nice as a simple macro. – Kyle Strand Apr 10 '16 at 03:02
  • @KubaOber In other words, I find `BIND_MEMBER_TO_THIS(myMemberFunc)` much more readable than `BindMemberToPtr(this, &MyClass::myMemberFunc)`. – Kyle Strand Apr 11 '16 at 16:05
  • @KubaOber Another example that's just come up: I realize that casting away `const` is dangerous and should therefore be explicit, but in the case where a `const` member function calls a non-`const` member function, I find it inelegant and redundant to have to re-specify what class I'm in just to cast away `const`. But the syntax for inferring the type and stripping `const` looks like this: `const_cast::type>::type&>(*this)`. Seriously, there is no reason to type that multiple times. – Kyle Strand Apr 18 '16 at 22:26
  • 1
    @KyleStrand Can't you use a function for that? `template constexpr typename std::remove_const::type>::type& no_const(C* c) { return const_cast::type>::type&>(*c); }` **Use:** `no_const(this).method()`. You could inject that function as a method into the class, and then you wouldn't even need to pass `this`: `Foo& no_const() const { return ::no_const(this); }` *No typos, I promise.* – Kuba hasn't forgotten Monica Apr 19 '16 at 14:36
  • @KubaOber After I wrote that, I realized that indeed the `std::remove_....` functions I'm using are indeed *functions*, so it should be possible to write a template function that could do the rest for me. I'll admit I still think that's way more complicated than it ought to be, but it's certainly not the argument for macros that I thought it was! Thank you. – Kyle Strand Apr 19 '16 at 15:26
  • I naively upvoted this answer before trying and I cannot take that back. But it does not work. When I replace `qStdout` with `QTextStream(stdout)` it works, so static initialization is probably a bad idea. – Tomáš Zato - Reinstate Monica Apr 19 '17 at 21:29
  • @TomášZato I've tested this, so I know it works. When you say it "does not work", do you mean you get a compile error, or you don't get any output? Are you ensuring that the stream is flushed? – Kyle Strand Apr 19 '17 at 22:09
  • It does not generate any output at all. Once I replaced it with `QTextStream` constructor it started working. I do not understand what do you mean by flushing the stream. – Tomáš Zato - Reinstate Monica Apr 19 '17 at 22:16
  • @TomášZato Output is buffered and may not actually print until the stream is *flushed* (which simply means that the application forces all buffered output to be written, and *stops execution* until that has happened). This is done automatically by the `QTextStream` destructor, which may be why you're seeing output when you use the constructor directly to create temporary objects. To flush manually, just call `qStdout().flush()`. – Kyle Strand Apr 19 '17 at 22:24
  • @TomášZato (Buffering/flushing I/O is very standard; you should research it on your own if you still have questions about it.) – Kyle Strand Apr 19 '17 at 22:24
  • @TomášZato I have made an edit that includes a note to `flush` the streams. If you are still having difficulties, feel free to remove your upvote (votes are unlocked when a post is edited). – Kyle Strand Apr 19 '17 at 22:32
  • Is the part about making a function necessary? It seems the source you reference said it was a hypothetical: https://meta.stackoverflow.com/questions/287692/the-nuclear-option-massively-editing-the-accepted-answer/287701#comment167242_287701 I'd like to upvote this answer but I'm hesitant to believe that it's necessary to make a function that returns a static instance. – Mitch Dec 18 '17 at 10:53
  • 1
    @Mitch Hm, reviewing those links and the Qt documentation, you're right; I don't see anything to indicate that there's any real known issue caused by temporary `QTextStream` objects. Edited. – Kyle Strand Dec 18 '17 at 16:29
32

Add this to your project file:

CONFIG += console
Kyle Lutz
  • 7,592
  • 2
  • 18
  • 21
  • 5
    There was no information given in the question regarding which build system is being used. This is only relevant when using `qmake`. – Kyle Strand Feb 23 '15 at 19:33
20

What variables do you want to print? If you mean QStrings, those need to be converted to c-Strings. Try:

std::cout << myString.toAscii().data();
Sebastian Negraszus
  • 11,057
  • 7
  • 38
  • 66
11

It also has a syntax similar to prinft, e.g.:

qDebug ("message %d, says: %s",num,str); 

Very handy as well

ulitosCoder
  • 1,733
  • 15
  • 19
8

Go the Project's Properties -> Linker-> System -> SubSystem, then set it to Console(/S).

Jawa
  • 2,312
  • 6
  • 33
  • 36
Son Vu
  • 89
  • 1
  • 1
3

What about including iostream library and precise that cout is an object of std like this :

#include <iostream>

std::cout << "Hello" << std::endl;
1

If you are printing to stderr using the stdio library, a call to fflush(stderr) should flush the buffer and get you real-time logging.

Andrew Prock
  • 6,273
  • 5
  • 36
  • 58
1
#include <QTextStream>
...
qDebug()<<"Bla bla bla";
Amir Touitou
  • 2,024
  • 1
  • 28
  • 24
0

Well, after studying several examples on the Internet describing how to output messages from a GUI in Qt to stdout, I have refined a working stand-alone example on redirecting messages to a console, via qDebug() and installing qInstallMessageHandler(). The console will be showed at the same time as the GUI and can be hidden if deemed necessary. The code is easy to integrate with existing code in your project. Here is the full sample and feel free to use it in any way as you like, as long as you adhere to the License GNU GPL v2. You have to use a form of some sort and a MainWindow I think - otherwise the sample will run, but probably crash when forced to quit. Note: there is no way to quit via a close button or a menu close because I have tested those alternatives and the application will crash eventually every now and then. Without the close button the application will be stable and you can close it down from the main window. Enjoy!

#include "mainwindow.h"
#include <QApplication>

//GNU GPL V2, 2015-02-07
#include <QMessageBox>
#include <windows.h>
#define CONSOLE_COLUMNS 80
#define CONSOLE_ROWS    5000
#define YOURCONSOLETITLE "Your_Console_Title"

typedef struct{

    CONSOLE_SCREEN_BUFFER_INFOEX conScreenBuffInfoEX;

    HANDLE con_screenbuf;
    HWND hwndConsole;
    HMENU consoleMenu ;
    QString consoleTitle;

    QMessageBox mBox;
    QString localMsg;
    QString errorMessage;
    WINBOOL errorCode;

} consoleT;

static consoleT *console;

BOOL WINAPI catchCTRL( DWORD ctrlMsg ){

        if( ctrlMsg == CTRL_C_EVENT ){

            HWND hwndWin = GetConsoleWindow();
               ShowWindow(hwndWin,SW_FORCEMINIMIZE);
        }

    return TRUE;
}

void removeCloseMenu(){

    int i;

    for( i = 0; i < 10; i++){

        console->hwndConsole = FindWindowW( NULL, console->consoleTitle.toStdWString().data());

        if(console->hwndConsole != NULL)
            break;
    }

    if( !(console->errorCode = 0) && (console->hwndConsole == NULL))
            console->errorMessage += QString("\nFindWindowW error: %1 \n").arg(console->errorCode);

    if( !(console->errorCode = 0) &&  !(console->consoleMenu = GetSystemMenu( console->hwndConsole, FALSE )) )
        console->errorMessage += QString("GetSystemMenu error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = DeleteMenu( console->consoleMenu, SC_CLOSE, MF_BYCOMMAND )))
           console->errorMessage += QString("DeleteMenu error: %1 \n").arg(console->errorCode);
}

void initialiseConsole(){

    console->conScreenBuffInfoEX.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    console->consoleMenu = NULL;
    console->consoleTitle = YOURCONSOLETITLE;
    console->con_screenbuf = INVALID_HANDLE_VALUE;
    console->errorCode = 0;
    console->errorMessage = "";
    console->hwndConsole = NULL;
    console->localMsg = "";

    if(!(console->errorCode = FreeConsole()))
        console->errorMessage += QString("\nFreeConsole error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = AllocConsole()))
        console->errorMessage += QString("\nAllocConsole error: %1 \n").arg(console->errorCode);

    if( (console->errorCode = -1) && (INVALID_HANDLE_VALUE ==(console->con_screenbuf = CreateConsoleScreenBuffer( GENERIC_WRITE | GENERIC_READ,0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL))))
        console->errorMessage += QString("\nCreateConsoleScreenBuffer error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = SetConsoleActiveScreenBuffer(console->con_screenbuf)))
        console->errorMessage += QString("\nSetConsoleActiveScreenBuffer error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = GetConsoleScreenBufferInfoEx(console->con_screenbuf, &console->conScreenBuffInfoEX)))
        console->errorMessage += QString("\nGetConsoleScreenBufferInfoEx error: %1 \n").arg(console->errorCode);

    console->conScreenBuffInfoEX.dwSize.X = CONSOLE_COLUMNS;
    console->conScreenBuffInfoEX.dwSize.Y = CONSOLE_ROWS;

    if(!(console->errorCode = SetConsoleScreenBufferInfoEx(console->con_screenbuf, &console->conScreenBuffInfoEX)))
       console->errorMessage += QString("\nSetConsoleScreenBufferInfoEx error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = SetConsoleTitleW(console->consoleTitle.toStdWString().data())))
        console->errorMessage += QString("SetConsoleTitle error: %1 \n").arg(console->errorCode);

    SetConsoleCtrlHandler(NULL, FALSE);
    SetConsoleCtrlHandler(catchCTRL, TRUE);

    removeCloseMenu();

    if(console->errorMessage.length() > 0){
        console->mBox.setText(console->errorMessage);
        console->mBox.show();
    }

}

void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg){


    if((console->con_screenbuf != INVALID_HANDLE_VALUE)){

        switch (type) {

        case QtDebugMsg:
            console->localMsg = console->errorMessage + "Debug: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtWarningMsg:
            console->localMsg = console->errorMessage + "Warning: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length() , NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtCriticalMsg:
            console->localMsg = console->errorMessage + "Critical: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtFatalMsg:
            console->localMsg = console->errorMessage + "Fatal: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            abort();
        }
    }
}



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

    qInstallMessageHandler(messageHandler);

    QApplication a(argc, argv);

    console = new consoleT();
    initialiseConsole();

    qDebug() << "Hello World!";

    MainWindow w;
    w.show();

    return a.exec();
}
0

"build & run" > Default for "Run in terminal" --> Enable

to flush the buffer use this command --> fflush(stdout); you can also use "\n" in printf or cout.

r.shams
  • 1
  • 2