wstring.size()在xcode或visual c++中的工作方式不同
wstring.size() works differently in xcode or visual c++
我运行了相同的代码,用于确定宽字符串中的字符数。测试字符串包含ascii、数字和朝鲜语。
#include <iostream>
using namespace std;
template <class T,class trait>
void DumpCharacters(T& a)
{
size_t length = a.size();
for(size_t i=0;i<length;i++)
{
trait n = a[i];
cout<<i<<" => "<<n<<endl;
}
cout<<endl;
}
int main(int argc, char* argv[])
{
wstring u = L"123abc가1나1다";
wcout<<u<<endl;
DumpCharacters<wstring,wchar_t>(u);
string s = "123abc가1나1다";
cout<<s<<endl;
DumpCharacters<string,char>(s);
return 0;
}
显而易见的是,Visual C++2010中的wstring.size()返回字母数(11个字符),而不管它是ascii还是国际字符。然而,它在Mac OS X中的XCode 4.2中返回字符串数据的字节计数(17字节)。
请回复我如何获得宽字符串的字符长度,而不是xcode中的字节数。
---2月12日添加--
我发现wcslen()在xcode中也返回17。它在vc++中返回11。这是经过测试的代码:
const wchar_t *p = L"123abc가1나1다";
size_t plen = wcslen(p);
---2月18日添加--
我发现llvm 3.0导致了错误的长度。将编译器前端从llvm3.0更改为4.2 后,此问题得到了修复
wcslen()在Xcode中的工作方式不同,VC++说明了细节。
如果std::wstring
版本使用17个字符,这是一个错误:它应该只使用11个字符。使用gcc和clang的最新SVN头,它为std::wstring
使用11个字符,为std::string
使用17个字符。我认为这是意料之中的事。
请注意,标准C++库内部对"字符"的概念与使用多字编码时的预期不同(例如,UTF-8用于char
类型的字,UTF-16用于16位的字)。这是描述字符串的章节的第一段(21.1[strings.general]):
本条款描述了用于操作任何非数组POD(3.9)类型的序列的组件。在这个子句中,这种类型被称为类字符类型,类字符类型的对象被称为类似字符的对象或简单的字符。
这基本上意味着,当使用Unicode时,的各种函数不会关注代码点的组成,而是将字符串作为单词序列进行处理。这是严重的影响,例如在生成子字符串时会发生什么,因为这些子字符串可能很容易将多字节字符分开。目前,标准C++库不支持在内部处理多字节编码,因为它假设从编码到字符的转换是在读取数据时完成的(相应地,在写入数据时则是另一种方式)。如果您在内部处理多字节编码的字符串,则需要注意这一点,因为根本不支持。
人们认识到,这种状况实际上是一个问题。对于C++2011,添加了字符类型char32_t
,它应该比wchar_t
更好地支持Unicode字符(因为Unicode使用20位,而wchar_t
只允许支持16位,这是在Unicode承诺最多使用16位的时候在一些平台上做出的选择)。然而,这仍然不能处理组合字符的问题。C++委员会承认这是一个问题,在标准C++库中进行适当的字符处理是件好事,但到目前为止,还没有人提出解决这个问题的全面建议(如果你觉得你想提出这样的建议,但你不知道怎么做,请随时联系我,我会帮助你提交建议)。
XCode 4.2在初始化string s
时,显然使用UTF-8(或类似的东西)作为窄多字节编码来表示程序源代码中的字符串文字"123abc가1나1다"
。该字符串的UTF-8表示恰好有17个字节长。
宽字符表示(存储在u
中)是11个宽字符。有许多方法可以将窄编码转换为宽编码。试试这个:
#include <iostream>
#include <clocale>
#include <cstdlib>
int main()
{
std::wstring u = L"123abc가1나1다";
std::cout << "Wide string containts " << u.size() << " charactersn";
std::string s = "123abc가1나1다";
std::cout << "Narrow string contains " << s.size() << " bytesn";
std::setlocale(LC_ALL, "");
std::cout << "Which can be converted to "
<< std::mbstowcs(NULL, s.c_str(), s.size())
<< " wide characters in the current locale,n";
}
使用.length()
而不是.size()
来获取字符串长度。
std::string和std::wstring是在char和wchar_t上模板化的std::basic_string的typedef。size()成员函数返回字符串中元素的数量-char或wchar_t的数量。"和L"不涉及编码。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 为什么stream::忽略未按预期工作