【问题标题】:QString formatting will not work qDebugQString 格式化将不起作用 qDebug
【发布时间】:2017-04-20 08:23:26
【问题描述】:

我尽量避免在 QT 程序中混合使用 QStringchar* 类型。我有一个对话函数,它返回QString 内的数据指针,但我得到了非常奇怪的结果。这段代码有什么问题?

编译器和环境 gcc (Debian 4.9.2-10) 4.9.2 通过 qmake 标记:QMAKE_CXXFLAGS += -std=c++11

代码sn-p:

#include <QCoreApplication>
#include <iostream>
#define  PCH(m) ( m.toAscii().data() )

// get the pointer short scripted
const char* CH(QString msg) {
   const char* res = msg.toAscii().data();
   return res;
}

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

    const QString qformat = "%s does not work!";
    const QString qvalue  = "embedding";

    // Works not
    qDebug(CH(qformat), CH(qvalue));   

    // Works
    qDebug(qformat.toAscii().data(), qvalue.toAscii().data());

    // Works too but macro
    qDebug(PCH(qformat), PCH(qvalue));   

    return app.exec();
}

结果

%s does not work! does not work!

embedding does not work!

embedding does not work!

【问题讨论】:

    标签: c++ qt qdebug


    【解决方案1】:

    在这里,您将QString 复制到函数中,并返回指向函数内部已销毁数据的指针。这是已知的未定义行为,因为您正在返回指向垃圾的指针。返回 QString。

    const char* CH(QString msg) {
        const char* res = msg.toAscii().data();
        return res;
    }
    

    【讨论】:

    • 谢谢,很清楚。除了宏还有其他解决方案吗? .. #define CH(m) ( m.toAscii().data() )。 ?
    • 为什么不qDebug() &lt;&lt; m
    • 我喜欢通过预定义的错误代码使用日志功能的 printf 功能。像这样: const QString ERR_UNKOWN_WORK_DIR = "%s: Unkown work directory %s ";
    • @huckfinn 使用QString 内置的格式,然后:arg 和朋友。这正是您正在寻找的。​​span>
    • 如果要使用qDebug()+格式化字符串,使用qPrintable():qDebug("foo %s", qPrintable(someQString));
    【解决方案2】:

    您应该使用qDebug()QString 本身内置的格式化机制。你还应该使用QStringLiteral,而不是依赖默认的字符串转换——毕竟你已经说过你关心这些事情:

    #include <QtCore>
    int main()
    {
        const auto qformat = QStringLiteral("%1 does work!");
        const auto qvalue = QStringLiteral("embedding");
        qDebug() << qformat.arg(qvalue);
        qDebug() << qformat.arg(0x7A01173C2, 0, 16);
    }
    

    现代编译器上使用的QStringLiteral 确实创建 8 位 C 字符串。它在编译时组装a binary internal representation of a QString,并将其存储在可执行文件的只读内存部分中。这是避免字符串编码的运行时成本的唯一方法。

    如果您已经有 UTF8 编码的字符串文字或 UTF8 编码的 C 样式字符串,则通过 QString 进行往返没有任何好处。如果您需要使用 C 风格的字符串/字符串文字,请直接与 qDebug 一起使用:

    #include <QtCore>
    int main() {
        const char format[] = "%s does not work!";
        const char value[] = "embedding";
        qDebug(format, value);
    }
    

    如果您需要传递临时 C 风格的字符串,请使用 QByteArray,但这确实是很多代码,几乎没有什么可显示的 - 它太冗长以至于有一种非常糟糕的代码气味。所以不要这样做:

    #include <QtCore>
    QByteArray CH(const QString &msg) {
       return msg.toLocal8Bit();
    }
    
    int main()
    {
        auto qformat = QStringLiteral("%s does work!");
        auto qvalue = QStringLiteral("embedding");
        qDebug(CH(qformat).constData(), CH(qvalue).constData());
    }
    

    【讨论】:

      猜你喜欢
      • 2019-05-19
      • 2014-05-22
      • 2011-06-14
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多