如何在不添加空格和换行符的情况下调用qDebug?

66

我正在使用C++/Qt的打印函数qDebug,但有时我希望控制如何添加“,空格和换行符”,而不使用默认的qDebug。

让我们举个简单的例子:

QString var1("some string");
int var2 = 1;
qDebug() << var1 << "=" << var2;
这将会打印什么内容。
"some string" = 1 

但是假设我不喜欢追加的引号和空格,我希望输出看起来像

some string=1 

那么我如何调用 qDebug 函数?


注意:Qt 的 qDebug 函数中有一个叫做 nospace 的函数,但它会删掉空格。 但是 " 仍然会在输出结果中。

如果我使用以下代码:

qDebug().nospace() << var1 << "=" << var2;

我的结果是:

"some string"=1

请注意,我仍然没有找到一种方法来消除结尾的换行符。

/谢谢

8个回答

103

最好先了解 QDebug 的内部工作原理,这样您就可以轻松地修改它以适应您的需要。每当使用 qDebug() 函数时,它都会返回一个 QDebug 对象。默认情况下,QDebug 在使用 operator << 后总是输出一个空格。

QDebug 类内部包含一个 QString。每次使用 operator << 时,都会将其附加到该内部 QString 上。当销毁 QDebug 对象时,会通过 qt_message_output(QtMsgType, char*) 输出该 QString。

默认情况下,qt_message_output 总是在字符串后面打印一个换行符。

普通输出

qDebug() << "Var" << 1;

这将输出Var 1。这是因为qDebug会创建一个QDebug对象,每次调用operator <<后附加一个空格。 因此,结果将是Var + + 1 +

没有空格

您可以使用QDebug::nospace来告诉QDebug不要在每次调用operator <<后附加一个空格。

qDebug().nospace() << "Var" << 1;

这将输出 Var1,因为那个 QDebug 对象不再打印空格。

没有换行符

不在字符串末尾添加 \n 会更加困难。由于 QDebug 在内部只有当它被销毁时才将字符串传递给 qt_message_output,因此您可以延迟该 QDebug 对象的销毁 -

QDebug deb = qDebug();
deb << "One" << "Two";
deb << "Three";

这将打印One Two Three,然后添加一个新行。

如果您不想打印新行,您需要更改qt_message_output的行为。这可以通过安装自定义处理程序来完成。

void customHandler(QtMsgType type, const char* msg) {
    fprintf(stderr, msg);
    fflush(stderr);
}

// Somewhere in your program
qInstallMsgHandler(customHandler);

qDebug() << "One" << "Two";
qDebug().noSpace() << "Three" << "Four";

这将打印出One Two ThreeFour

请注意,这将影响程序中的所有qDebug语句。如果您想删除自定义处理程序,您应该调用qInstallMsgHandler(0)

qDebug(const char* msg, ...)

如其他答案所示,您也可以使用qDebug函数以类似于printf的格式打印字符串。这样,您就可以避免QDebug追加的额外空格。

然而,qDebug在内部仍然使用qt_message_output,因此除非安装自己的处理程序,否则仍将在末尾得到换行符。


55
尝试以下格式:qDebug(“%s =%d”,“string”,1); 在这种情况下,qDebug 使用 printf 格式
附注:适用于您的示例: qDebug(“%s =%d”,var1.toStdString().c_str(),var2);

23
我建议使用qPrintable(var1)代替var1.toStdString().c_str()。两者都可以正常工作,但是qPrintable()看起来更好看。 :) - Robin
2
如果这样做,根据文档,应该使用qUtf8Printable(),因为qDebug和其他Qt日志记录函数期望%s参数为UTF-8。 - ePirat
5
这仍会添加一行新的内容! - Violet Giraffe

29

自Qt 5.4起,您还可以编写:

qDebug().nospace().noquote() << var1;

2
我该如何全局设置这个? - ManuelSchneid3r
@ManuelSchneid3r 你不能直接解决这个问题,但你可以通过 #undef qDebug 的方式来绕过它,并重新定义为 #define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug().noquote().nospace (或者创建自己的宏)。这里的问题是你必须将这个新的宏设置为全局可访问,并且不能跨越可执行文件边界(例如另一个也使用 qDebug 的共享库)。 - cbuchart
有些奇怪,为什么QDebug会在字符串中添加一些东西,我们需要显式地禁用它们... 当我写 qDebug() << str 时,我希望它会像原本的字符串一样打印出来,而不是添加引号、空格或其他内容。 - Nuclear

19

结合上述答案,您可以使用以下方法:

qDebug() << qPrintable(var1);

消除周围的引号。


不涉及问题的“换行符”方面。 - pixelgrease

7

我也遇到了引号问题。解决方法是不要将QString()导入到流中,而是使用QString(...).toStdString().c_str()

我为自己建立了一个小的便利宏,以轻松解决这个问题:

#define Q(string) (string).toStdString().c_str()

现在每次使用QString时,请按照以下方式操作:
qDebug() << Q(var1) << "=" << var2;

2
实际上,也可以使用 qDebug() << qPrintable( var1 ) 来完成这个操作。 - Thirler

4
文件$(QTDIR)/src/corelib/io/qdebug.h包含了几乎所有的调试输出方法定义,其中之一是:
inline QDebug &operator<<(const QString &t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
因此,没有“官方”方法来抑制引号,但您可以更改qdebug.h文件或使用自己的副本或修改和重命名Qdebug类的副本。

2

实例化一个 QDebug 对象并向其输出:

QDebug dbg = qDebug().nospace().noquote();

dbg << var1 << "=" << var2;

返回:

some string=1

不管你想在 dbg 对象中输出什么 -- 直到它超出作用域,才会有换行符。例如:

char var1[] = "some string";
int var2 = 1;

{
    QDebug dbg = qDebug().nospace().noquote();

    dbg << var1 << "=" << var2;

    // keep using "dbg"; there's no newline ('\n') until it destructs
    dbg << "...";
    for (int i = 5; i <=9; ++i)
        dbg << i;
}

输出:

some string=1...56789

0

我不确定,但从文档中看来,从消息处理程序中更改格式似乎是不合适的 - AkiRoss
只有专业人士才知道何时打破规则,如果这是致命的行为或从未合适过,他们首先就不会让它成为可能。 - zkunov
我绝对不同意那种观点... 意味着你可以做并不代表它是正确的或者本来就是打算这样做的。 - AkiRoss
请把下列程序相关内容从英语翻译成中文。仅返回翻译后的文本:示例适当用法见此处:https://dev59.com/k2445IYBdhLWcg3wQoEj. - zkunov
1
顺便说一句,我刚意识到你的意思是使用自己的消息处理程序来去除空格和换行可能有点过于繁琐。我想这取决于代码库的情况,以及你将要使用新格式化的次数等等。但这是一个有效的选择,当我写下这段话时没有人提到过。 - zkunov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接