我使用 Qt4和 c + + 来制作一些计算机图形学的程序。我需要能够在运行时在控制台中打印一些变量,而不是调试,但是即使我添加了这些库,cout似乎也不起作用。有办法吗?
cout
如果足以打印到 stderr,可以使用下列原本用于调试的流:
stderr
#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" );
尽管如注释中所指出的,但请记住,如果定义了 QT_NO_DEBUG_OUTPUT,则会删除 qDebug 消息
QT_NO_DEBUG_OUTPUT
如果你需要 stdout,你可以试试这样的东西(正如 Kyle Strand 指出的) :
QTextStream& qStdOut() { static QTextStream ts( stdout ); return ts; }
然后你可以这样呼叫:
qStdOut() << "std out!";
你想打印什么变量? 如果你指的是 QString,那么这些变量需要转换成 c-String。试试:
std::cout << myString.toAscii().data();
将此添加到您的项目文件:
CONFIG += console
我发现 这个最有用:
#include <QTextStream> QTextStream out(stdout); foreach(QString x, strings) out << x << endl;
它还有一个类似于 prinft 的语法,例如:
qDebug ("message %d, says: %s",num,str);
也很方便
转到项目的 Properties -> Linker-> System -> SubSystem,然后设置为 Console(/S)。
Properties -> Linker-> System -> SubSystem
Console(/S)
如果使用 stdio 库打印到 stderr,那么对 fflush(stderr)的调用应该刷新缓冲区并获得实时日志记录。
fflush(stderr)
在研究了几个互联网上描述如何在 Qt 中将 GUI 中的消息输出到 stdout 的例子之后,我完善了一个可以独立工作的例子,通过 qDebug ()和安装 qInstallMessageHandler ()将消息重定向到控制台。控制台将显示在同一时间作为 GUI,并可以隐藏,如果认为必要的。该代码很容易与项目中的现有代码集成。下面是完整的示例,您可以随意以任何方式使用它,只要您遵守许可 GNU GPL v2。我认为您必须使用某种形式和 MainWindow-否则示例将运行,但是当被迫退出时可能会崩溃。注意: 没有办法退出通过一个关闭按钮或菜单关闭,因为我已经测试了这些替代方案,应用程序最终将崩溃不时。没有关闭按钮,应用程序将是稳定的,你可以从主窗口关闭它。好好享受吧!
#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(); }
stdout
如果您想要像 std::cout那样将数据写入应用程序的标准输出,您可以简单地执行 以下(归功于 CapelliC) :
std::cout
QTextStream(stdout) << "string to print" << endl;
如果您想避免创建临时 QTextStream对象,请遵循 Yakk 在下面的注释中提出的建议,创建一个函数来返回 stdout的 static句柄:
QTextStream
static
inline QTextStream& qStdout() { static QTextStream r{stdout}; return r; } ... foreach(QString x, strings) qStdout() << x << endl;
请定期将 记录到 flush流中,以确保实际打印输出。
flush
注意,上述技术也可以用于其他输出。然而,还有更多可读的方式写到 stderr(都是高兹的功劳和下面的评论他的答案) :
qDebug() << "Debug Message"; // CAN BE REMOVED AT COMPILE TIME! qWarning() << "Warning Message"; qCritical() << "Critical Error Message"; qFatal("Fatal Error Message"); // WILL KILL THE PROGRAM!
如果在编译时打开 QT_NO_DEBUG_OUTPUT,则 qDebug()关闭。
qDebug()
(Goz 在评论中指出,对于非控制台应用程序,它们可以打印到与 stderr不同的流。)
注意: 所有 Qt 打印方法 假设 const char*参数都是带有终止 \0字符的 ISO-8859-1编码字符串。
const char*
\0
如何包含 Iostream 图书馆并精确地说 Cout是 性病的一个对象,如下所示:
#include <iostream> std::cout << "Hello" << std::endl;
「建立及运行」 > 「在终端运行」的预设值-> 启用
使用以下命令刷新缓冲区—— > fflush (stdout) ; 你也可以在 printf或者 cout中使用“ n”。
printf