QString乱谈(2)

  • 长期以来,很多人都清楚,一旦C++源码中直接使用了中文,这样的源码想要跨平台(I18N)会非常困难。

随着:

  • Windows下:MSVC2010成为主流
  • Linux下:GCC升级到4.6

C++中的中文问题 才算有了一个比较优雅的、跨平台的Workaround。

(本文讨论编译器范围:GCC4.6+, MSVC2010sp1+ 。本文属于QString系列,但暂不涉及QString)

C++ 中文问题

要在C++中正确使用中文,必须要了解下面两个概念:

源码字符集(the source character set)

源码文件是使用何种编码保存的

执行字符集(the execution character set)

可执行程序内保存的是何种编码(程序执行时内存中字符串编码)

C++98的问题: 既没有规定源码字符集,也没有规定执行字符集

这个... 如何理解?不妨看个例子

例子

这个要求高么?

  • 一个简单的C++程序,只是希望它能在简体中文Windows、正体中文Windows、英文版Windows、Linux、MAC OS...下的结果一致。

//main.cpp
int main()
{
    char mystr[] = "老老实实的学问,来不得半点马虎";
    return sizeof mystr;
}

可以试着反问自己两个问题

  • 这个源码文件是何种编码保存的?(有确定答案么?)
  • mystr中是什么内容?(有确定答案么?)

对C++来说,这两个都不确定。

  • 固定平台的话,还能忍忍
  • 要跨平台的话,这种东西...

GCC

在GCC下,这两个都可以使用你自己喜好的编码(如果不指定,默认都是UTF8)

-finput-charset=charset
-fexec-charset=charset

除了前两个选项外,还有一个:

-fwide-exec-charset=charset

wide? 不妨先猜一下它是干嘛的

MSVC

MSVC没有类似前面的选项。

源码字符集如何解决?

有BOM么,有则按BOM解释,无则使用本地Locale字符集(随系统设置而变)

执行字符集如何解决?

使用本地Locale字符集(随系统设置而变)

挺霸道哈(当然,源码中可以使用#pragma setlocale("..."),但功能很有限,比如Windows没有utf8的locale,所以...)。

另外,和GCC对应的wide-exec-charset呢?

宽执行字符集如何解决?

不妨先考虑一下

怎么办?

这才两个编译器,看起来就这么复杂了。而C++编译器的数目远大于2.

要想跨平台,必须确保这两个字符集都是“确定”的,而能胜任该任务的字符集,似乎理想的也只能是...

UTF-8方案

  • 如果我们将源码保存成utf8,执行字符集也选为utf8,那么天下将太平了。使用非ASCII字符的源码文件也就可以在不同国家的用户间无障碍流通了 ;-).

源码保存成UTF-8没有什么困难,但是,执行字符集需要是UTF-8。没那么简单

对GCC来说,这个问题很简单(默认的编码选项足够了):

  • 只要源码文件保存成utf8即可(带或不带BOM均可)
  • 早期的gcc不接收带BOM的utf8源码文件,现在,至少在GCC4.6中,这一限制不再存在。

对MSVC来说,这个问题异常复杂:

  • 对MSVC2003来说,只要源码保存成不带BOM的utf8即可
  • 对MSVC2005、(没在SP1基础上装热补丁的)MSVC2008来说。完全没办法
  • 直到MSVC2010sp1,才算提供了一个解决方案。源码保存成带BOM的utf8,utf16,...,然后添加

#pragma execution_character_set("utf-8")

要想跨GCC4.6+和MSVC2010sp1+,我们需要取它们的交集:也就是

  • 源码保存成带BOM的utf8
  • 为MSVC添加#pragma

//main.cpp

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

int main()
{
    char mystr[] = "老老实实的学问,来不得半点马虎";
    return sizeof mystr;
}

C++11

等到MSVC支持C++11的String Literals之时,我们就没必要用那个蹩脚的pragma了,直接

    char mystr[] = u8"老老实实的学问,来不得半点马虎";

即可(尽管现在在GCC下没问题,但要跨平台,估计要等到Visual C++ 12了)。

有个问题?

C++98中不是有个wchar_t么,它不是用来表示unicode字符的么?

Unicode 4.0标准的5.2节是如何说的:

The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compilershould not use wchar_t for storing Unicode text. The wchar_t type is intended forstoring compiler-defined wide characters, which may be Unicode characters in some compilers.

在回头看看GCC的选项

-fwide-exec-charset=charset

尽管GCC为其提供的默认编码是UTF16或UTF32(取决于wchar_t的宽度),但该编码是可以随意设置的。

尽管这个东西不保证跨平台,也很不好玩, 但是,由于在windows下面wchar_t用来表示utf16字符,而且直接对应系统API接口,所以在类型char16_t普及之前,还是很重要的。

C++11执行字符集

前面提到的u8就是C++11为“执行字符集”所做的努力之一。

新明确规定了utf8、utf16和utf32这3种执行字符集。

char*

u8"中文"

char16_t*

u"中文"

char32_t*

U"中文"

可是C++11并没有规定源码字符集

const char* mystr=u8"中文";

C++标准对编译器说,我不管这个文件的具体编码是什么,但你必须给我生成对应utf8编码的字节流。

编译器似乎有点傻了吧?不知道源文件的编码,我如何转换

于是:

MSVC说:源码文件必须有BOM,不然我就认为你是本地locale的编码

GCC说:我认为你就是utf8编码,除非通过命令行通知我其他编码

在C++11标准下,对源码编码 简单的处理办法还是,使用带BOM的UTF8保存。

参考


<think> 首先,用户的问题是关于判断两个QString对象是否相等的方法。用户提到了"QStringQString2",但"QString2"可能只是一个占位符,指的是另一个QString对象。我需要基于提供的引用和系统指令来回答。 回顾系统指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户的问题是基于引用内容,所以我需要引用这些引用源。引用包括: - [^1]: 讨论了QString判断2个字符是否相同的方法,包括使用==和compare()。 - [^2]: 类似[^1],但多了判断是否包含某个字符串的部分。 - [^3]: 提到一个失误,判断QString字符串是否相等时结果永远是真,暗示可能有问题。 - [^4]: 展示如何使用compare()方法判断QString是否相等,包括忽略大小写的比较。 用户查询的核心是判断两个QString对象是否相等的方法。从引用中,我看到两种主要方法: 1. 使用==运算符。 2. 使用compare()方法,返回0表示相等。 在[^3]中,提到了一个失误,可能是compare()方法使用不当导致的。我需要确保回答正确无误。 总结判断QString相等的标准方法: - 使用operator==:例如,if (str1 == str2) { ... } - 使用compare()方法:例如,if (str1.compare(str2) == 0) { ... } 在[^4]中,还提到了忽略大小写的比较,可以通过传递Qt::CaseInsensitive参数给compare()方法。 用户指定"不是用户真正的需求",但我应该基于引用回答问题。引用[^3]中的失误可能源于使用了QString::compare的错误方式,比如比较两个字符串字面量而不是对象。 结构化回答: - 介绍主题。 - 解释两种方法。 - 提供代码示例。 - 讨论注意事项,比如大小写敏感性。 - 添加引用标识。 最后,生成相关问题。 回答结构: 1. 简明扼要地介绍如何判断QString相等。 2. 使用代码示例。 3. 自然地添加引用。 4. 生成相关问题。 确保使用中文回答。 生成相关问题: - 诸如如何忽略大小写进行比较?常见的错误是什么?等。 相关问题示例: 1. 如何在QString比较中忽略大小写? 2. 使用compare()方法时常见的错误是什么? 3. QString还有其他字符串操作方法吗? 写出回答。 </think> ### QString判断两个字符串是否相等的方法 在Qt框架中,QString类提供了多种方法来判断两个字符串是否相等。以下是基于引用内容的标准方法总结,包括代码示例和注意事项。判断主要通过两种方式实现:使用`==`运算符或`compare()`方法,两者均支持大小写敏感性的控制。 #### 1. 使用`==`运算符 这是最直观的方法,直接比较两个QString对象的值。如果相等,则返回`true`。 ```cpp QString str1 = "hello"; QString str2 = "hello"; if (str1 == str2) { qDebug() << "字符串相等"; // 输出此结果 } else { qDebug() << "字符串不相等"; } ``` - **优点**:语法简洁,易于阅读。 - **注意**:默认是大小写敏感的,即`"Admin"`和`"admin"`会被视为不相等[^1][^2]。 #### 2. 使用`compare()`方法 `compare()`方法返回一个整数,如果返回值为0,则表示两个字符串相等。此方法允许指定大小写敏感性参数。 ```cpp QString str1 = "hello"; QString str3 = "world"; if (str1.compare(str3) == 0) { qDebug() << "字符串相等"; } else { qDebug() << "字符串不相等"; // 输出此结果 } ``` - **大小写敏感控制**: - `Qt::CaseSensitive`(默认):区分大小写。 - `Qt::CaseInsensitive`:忽略大小写。 ```cpp QString name1 = "Admin"; QString name2 = "admin"; if (name1.compare(name2, Qt::CaseInsensitive) == 0) { qDebug() << "忽略大小写后相等"; // 输出此结果 } ``` - **优点**:更灵活,适合需要自定义比较规则的场景[^1][^2][^4]。 - **常见错误**:如果误用`QString::compare`参数(如比较字符串字面量而非对象),可能导致逻辑错误。例如,确保参数是QString对象,而非直接使用字面量进行比较[^3]。 #### 注意事项 - **性能**:`==`运算符通常更高效,适合简单比较;`compare()`提供额外功能,但开销略高。 - **Unicode支持**:QString基于Unicode,确保正确处理多语言字符。 - **错误预防**:避免在`compare()`中混淆参数顺序或忘记检查返回值是否为0,否则可能导致永久真值的错误[^3]。 通过以上方法,您可以高效且可靠地判断QString字符串是否相等。更多细节可参考Qt官方文档。
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值