Qt kullanırken konsola nasıl yazdırılır


159

Qt4 ve C ++ bilgisayar grafikleri bazı programlar yapmak için kullanıyorum. Bazı değişkenleri çalışma zamanında konsolumda yazabilmem gerekiyor, hata ayıklama değil, ancak coutkitaplıkları eklesem bile çalışmıyor gibi görünüyor. Bunu yapmanın bir yolu var mı?


3
Çalışmama konusunda biraz ayrıntı verebilir misiniz, çünkü bu kesinlikle işe yaramalı. Derleme hatası alıyor musunuz? Sizin için çalışmayan cout'un bir kod örneğini gösterebilir misiniz? Ayrıca uygulamayı nasıl çalıştırdığınızı da açıklayın. Konsoldan mı yoksa bir IDE içinden mi çalıştırıyorsunuz ve çıkış penceresine çıktı görmüyor musunuz?
Arnold Spence

Sadece bütünlük için: @ArnoldSpence - kütüphaneler olmadan error: ‘cout’ was not declared in this scope; iostream ile anladım error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; cevapta komutları kullanmak yerine iyi çalışıyor.
sdaau

Sorun ifadesi basitçe "işe yaramaz" olduğunda çözüm sunmak zordur. Lütfen ne olmasını beklediğiniz ve bunun gerçek sonuçlardan nasıl farklı olduğu hakkında daha ayrıntılı bir açıklama vermek için sorunuzu düzenleyin . İyi bir açıklama yapan şey hakkında ipuçları için Nasıl Sorulur bölümüne bakın .
Toby Speight

Bu durumda, açıkça bu "değişkenlerin" Qt'a özgü nesneler (örneğin QString) olduğunu belirtmelisiniz .
user202729

Yanıtlar:


203

Yazdırmaya yetecek kadar iyiyse stderr, ilk olarak hata ayıklama için tasarlanmış aşağıdaki akışları kullanabilirsiniz:

#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" );

Yorumlarda belirtildiği gibi QT_NO_DEBUG_OUTPUT, tanımlanmışsa qDebug mesajları kaldırılır.

Stdout'a ihtiyacınız varsa böyle bir şey deneyebilirsiniz (Kyle Strand'ın işaret ettiği gibi):

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

Daha sonra aşağıdaki gibi arayabilirsiniz:

qStdOut() << "std out!";

1
Hata ayıklama olmasa da, hata ayıklama sırasında değil çalışma zamanı sırasında konsolda mesaj yazmama izin veren bir işlev olması gerektiğini sordum.
lesolorzanov

11
Adına rağmen, bu işlev bir hata ayıklayıcı ile hata ayıklama ile ilgili değildir. Qt'nin bir tanımla derlemeden çıkarılabilen stderr'e çıktı göndermek için sağladığı bir kolaylık fonksiyonudur. Bu yüzden çalışma zamanında konsola çıktı elde etmek için bir alternatiftir.
Arnold Spence

Çok teşekkür ederim, kullanıyorum :). Sanırım kullandığım kodlardan herhangi birini yazmam için bir gerek yok. Teşekkürler! Bu çok faydalı oldu.
lesolorzanov

51
#include <QDebug>
ducky

62
Lütfen tüm konsol çıktıları için qDebug kullanmayın. Yalnızca gerçek hata ayıklama baskıları için kullanın qWarning, qCritical ve qFatal hatalar ve uyarılar için kullanın. Çünkü qDebug ifadeleri, performansı kaydetmek ve uygulamanın çıktıyı karmaşasını engellemek için QT_NO_DEBUG_OUTPUT ile derlenirken kaldırılabilir.
JustMaximumPower

150

Bulduğum bu en kullanışlı:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;

14
Cevabın neden kabul edilmediğini bilmiyorum, ama kesinlikle en faydalı olanı.
Semyon Danilov

4
Kabul. stderr, hatalar (ve hata ayıklama) içindir. Bu kabul edilen cevap olmalı çünkü stdout AND qt kullanan tek cevap bu.
Marshall Eubanks

1
Bu benim için çalıştı - ve cout yoluyla bilgi çıkışı için doğru bir yol gibi görünüyordu
Michael Vincent

2
Goz'un hataların / uyarıların nasıl yazdırılacağı hakkındaki cevabından bilgileri, Goz'un cevabından ne yazık ki eksik ama aşağıdaki yorumlarda bulabilirsiniz) qDebug(), vb. (IMO zaten OP'nin yerini alacak bir şey istediğinden daha üstündür std::cout, ancak 40 seçmen kabul etmiyor gibi görünüyor).
Kyle Strand

QTextStream qStdout() { return {stdout}; }ile tutarlı sar için kullanışlı bir yol, olabilir qWarning()vs. Ve belki biraz staticgeçici streamage önlemek için devlet?
Yakk - Adam Nevraumont

36

Yazıyor stdout

std::coutUygulamanızın standart çıktısına yazan bir şey istiyorsanız , aşağıdakileri yapabilirsiniz ( CapelliC'ye kredi ):

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

Geçici bir QTextStreamnesne oluşturmaktan kaçınmak istiyorsanız , aşağıdaki yorumlarda Yakk'ın, statictanıtıcı döndürmek için bir işlev oluşturma konusundaki önerisini izleyin stdout:

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

...

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

Unutmayın için flushperiyodik olarak çıktı aslında yazdırılır sağlamak için dere.

Yazıyor stderr

Yukarıdaki tekniğin diğer çıktılar için de kullanılabileceğini unutmayın. Ancak, daha okunabilir yollar var stderr( Goz'a ve cevabının altındaki yorumlar).

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()eğer kapalıysa QT_NO_DEBUG_OUTPUTderleme sırasında açıktır.

(Bir yorumda Goz, konsol dışı uygulamalar için bunların farklı bir akışa yazdırabileceğini belirtiyor stderr.)


NOT: Tüm Qt yazdırma yöntemleri , const char*bağımsız değişkenlerin sonlandırma \0karakterlerine sahip ISO-8859-1 kodlu dizeler olduğunu varsayar .


1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont

1
@Yakk İyi öneri! Cevabımı dahil edeceğim.
Kyle Strand

qFatal (), QT5 ile derlenirken bir hata alır. bir okuma okumak, yine de (orada / iş) söz değildi ... onu kullanmayın! :)
22'de relascope

1
@KyleStrand Bunun için bir işlev kullanamaz mısınız? template <typename C> constexpr typename std::remove_const<typename std::remove_reference<C>::type>::type& no_const(C* c) { return const_cast<typename std::remove_const<typename std::remove_reference<C>::type>::type&>(*c); } Kullanın: no_const(this).method() . Bu işlevi sınıfa bir yöntem olarak enjekte edebilirsiniz ve sonra geçmenize bile gerek kalmayacaktı this: Foo& no_const() const { return ::no_const(this); } Yazım hatası yok, söz veriyorum.
Monica'yı

1
@Mitch Hm, bu bağlantıları ve Qt belgelerini inceleyerek haklısınız; Geçici QTextStreamnesnelerin neden olduğu bilinen gerçek bir sorun olduğunu gösteren hiçbir şey görmüyorum . Düzenlenen.
Kyle Strand

32

Bunu proje dosyanıza ekleyin:

CONFIG += console

5
Hangi yapı sisteminin kullanıldığına ilişkin soruda bilgi verilmemiştir. Bu sadece kullanırken geçerlidir qmake.
Kyle Strand

19

Hangi değişkenleri yazdırmak istiyorsunuz? QStrings'i kastediyorsanız, bunların c-String'lere dönüştürülmesi gerekir. Deneyin:

std::cout << myString.toAscii().data();

8
@CoderaPurpa Eklemeniz gerekiyor#include <iostream>
Sebastian Negraszus

myString.toUtf8().data()ascii aralığının dışındaki Karakterleri yazdırdığı için daha iyidir. Örneğin Çince karakterler
peterchaula

8

Ayrıca prinft benzeri bir sözdizimi vardır, örneğin:

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

Çok kullanışlı


8

Projenin projesine gidin Properties -> Linker-> System -> SubSystem, sonra olarak ayarlayın Console(/S).


1
Bu (Kyle Lutz'un cevabı gibi) yapı sistemine özgüdür.
Kyle Strand

3

Dahil olmak üzere yaklaşık ne iostream kitaplığı olduğunu ve kesin cout bir amacı std böyle:

#include <iostream>

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

1

Stdio kütüphanesini kullanarak stderr'a yazdırıyorsanız, bir çağrıyı fflush(stderr)arabelleği temizlemeli ve gerçek zamanlı günlük kaydı almalısınız.



0

Peki, Qt içindeki bir GUI'den stdout'a iletilerin nasıl gönderileceğini açıklayan birkaç örnek inceledikten sonra, mesajları qDebug () aracılığıyla bir konsola yönlendirmek ve qInstallMessageHandler () ile yüklemek için tek başına çalışan bir örnek geliştirdim. Konsol GUI ile aynı anda gösterilecek ve gerekli görülürse gizlenebilir. Kod, projenizdeki mevcut kodla kolayca entegre edilebilir. İşte tam örnek ve Lisans GNU GPL v2'ye bağlı kaldığınız sürece istediğiniz gibi kullanmaktan çekinmeyin. Sanırım bir tür bir form ve bir MainWindow kullanmak zorundasınız - aksi takdirde örnek çalışacak, ancak çıkmak zorunda kaldığında muhtemelen çökecektir. Not: Bir kapatma düğmesi veya bir menü kapatma yoluyla çıkmanın bir yolu yoktur, çünkü bu alternatifleri test ettim ve uygulama her seferinde çökecektir. Kapat düğmesi olmadan uygulama kararlı olur ve ana pencereden kapatabilirsiniz. Zevk almak!

#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"> "Terminalde çalıştır" için varsayılan -> Etkinleştir

arabelleği temizlemek için şu komutu kullanın -> fflush (stdout); printfveya içinde "\ n" kullanabilirsiniz cout.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.