Qt使用MSVC编译器输出中文乱码的问题

在Qt Creator中使用MSVC编译器编译时,程序中的中文字符很容易出现乱码的情况。特写此篇博客分析原因和解决方法。

本文示例采用Qt5.9.6版本和MSVC2015版本。

一  原因分析

    Qt Creator保存的文件(如.cpp .h)默认保存为UTF-8编码(任何平台、任何语言都能使用的跨平台字符集),而MSVC编译器虽然可以正常编译带BOM的UTF-8编码的源文件,但是生成的可执行文件(一般为exe文件)的编码为Windows本地字符集(GBK/GB2312/GB18030,一般情况为GB2312)。所以,在生成的可执行文件中,中文字符是以GB2312编码的,而程序执行到这句代码时,这个中文字符串却是以UTF-8解码的,故而出现乱码的情况。

二  解决方法

    本文提供三种解决方案:QString::fromLocal8Bit()函数、QStringLiteral(tr)宏、指定MSVC编译器执行字符集。下面具体讲解:

 

    1. 使用QString::fromLocal8Bit()函数实现从本地字符集GB到UTF-8的转换。其原型如下:

[static] QString QString::fromLocal8Bit(const char *str, int size = -1);
[static] QString QString::fromLocal8Bit(const QByteArray &str);
//Returns a QString initialized with the first size characters of the 8-bit string str.

    示例:

seriesTan->setName(QString::fromLocal8Bit("Tan曲线"));

 值得注意的是,由于 fromLocal8Bit() 参数仅支持char*和QByteArray类型,因此,不能再使用tr()函数用于翻译字符串。tr()函数返回的是QString类型,其原型如下:

[static] QString QObject::tr(const char *sourceText, const char *disambiguation = Q_NULLPTR, int n = -1);

 

    2. 使用Qt的QStringLiteral(str)宏封装字符串。

#define QStringLiteral(str) \
    ([]() Q_DECL_NOEXCEPT -> QString { \
        enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
        static const QStaticStringData<Size> qstring_literal = { \
            Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
            QT_UNICODE_LITERAL(str) }; \
        QStringDataPtr holder = { qstring_literal.data_ptr() }; \
        const QString qstring_literal_temp(holder); \
        return qstring_literal_temp; \
    }()) \
    /**/

    QstringLiteral(str)宏在编译时将字符串str生成字符串数据,并储存在编译后文件的只读数据段(Read-only data segment)中,程序运行时使用到此字符串时,只需读出此字符串数据即可。

    示例:

seriesSin->setName(QStringLiteral("Sin曲线"));

    值得注意的是,此宏也不能使用tr()函数用于翻译字符串。 

 

3. 指定MSVC编译器执行字符集,强制MSVC编译器采用UTF-8编码生成可执行文件。

    此方法需要在每个使用到中文字符串的头文件或源文件的前部加入如下声明:

#if _MSC_VER >= 1600	// MSVC2015 > 1899,	MSVC_VER = 14.0
#pragma execution_character_set("utf-8")
#endif

    MSVC2010以后的编译器可以使用此方案,目前唯一支持的目标执行集是“utf-8”(引用:execution_character_set Microsoft[引用日期2018-12-16])。值得注意的是,这样可以使用tr()函数用于字符串翻译。

扩展:

    _MSC_VER是微软公司推出的C/C++编译器在ANSI/ISO C99标准之外扩展的宏定义,用来定义当前微软公司自己的编译器的主版本(引用:Predefined Macros Microsoft[引用日期2018-12-16])。

Visual Studio 版本                  _MSC_VER

Visual Studio 6.0                   1200
Visual Studio .NET 2002 (7.0)       1300
Visual Studio .NET 2003 (7.1)       1310
Visual Studio 2005 (8.0)            1400
Visual Studio 2008 (9.0)            1500
Visual Studio 2010 (10.0)           1600
Visual Studio 2012 (11.0)           1700
Visual Studio 2013 (12.0)           1800
Visual Studio 2015 (14.0)           1900
Visual Studio 2017 RTW (15.0)       1910
Visual Studio 2017 version 15.3     1911
Visual Studio 2017 version 15.5     1912
Visual Studio 2017 version 15.6     1913
Visual Studio 2017 version 15.7     1914
Visual Studio 2017 version 15.8     1915
Visual Studio 2017 version 15.9     1916

三  写在最后

    使用 #pragma execution_character_set("utf-8") 强制转换后,就不要再使用前面两种方法了,否则又乱码了,做无用功。

                                                                                                                                            韶光易逝,且争朝夕……

                                                                                                                                        2018年12月16日凌晨于武汉

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值