我无法理解std::string和std::wstring之间的区别。我知道wstring支持宽字符,比如Unicode字符。我有以下问题:
std::wstring over std::stringstd::string能容纳整个ASCII字符集,包括特殊字符吗?std::wstring编译器都支持C++吗?发布于 2008-12-31 12:47:29
string?wstring
std::string是char上的basic_string模板,std::wstring是wchar_t上的模板。
char对wchar_t
char应该保存一个字符,通常是8位字符.wchar_t应该有一个宽字符,然后,事情变得棘手起来:在Linux上,wchar_t是4字节,而在wchar_t上是2字节。
那么Unicode呢?
问题是,char和wchar_t都没有直接绑定到unicode。
在Linux上?
让我们来看看Linux操作系统:我的Ubuntu系统已经知道unicode了。当我使用char字符串时,它是本机用UTF-8编码的(即字符的Unicode字符串)。以下代码:
#include <cstring>
#include <iostream>
int main()
{
const char text[] = "olé";
std::cout << "sizeof(char) : " << sizeof(char) << "\n";
std::cout << "text : " << text << "\n";
std::cout << "sizeof(text) : " << sizeof(text) << "\n";
std::cout << "strlen(text) : " << strlen(text) << "\n";
std::cout << "text(ordinals) :";
for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
{
unsigned char c = static_cast<unsigned_char>(text[i]);
std::cout << " " << static_cast<unsigned int>(c);
}
std::cout << "\n\n";
// - - -
const wchar_t wtext[] = L"olé" ;
std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << "\n";
//std::cout << "wtext : " << wtext << "\n"; <- error
std::cout << "wtext : UNABLE TO CONVERT NATIVELY." << "\n";
std::wcout << L"wtext : " << wtext << "\n";
std::cout << "sizeof(wtext) : " << sizeof(wtext) << "\n";
std::cout << "wcslen(wtext) : " << wcslen(wtext) << "\n";
std::cout << "wtext(ordinals) :";
for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
{
unsigned short wc = static_cast<unsigned short>(wtext[i]);
std::cout << " " << static_cast<unsigned int>(wc);
}
std::cout << "\n\n";
}输出以下案文:
sizeof(char) : 1
text : olé
sizeof(text) : 5
strlen(text) : 4
text(ordinals) : 111 108 195 169
sizeof(wchar_t) : 4
wtext : UNABLE TO CONVERT NATIVELY.
wtext : ol�
sizeof(wtext) : 16
wcslen(wtext) : 3
wtext(ordinals) : 111 108 233您将看到char中的"olé“文本实际上是由四个字符构成的: 110、108、195和169 (不包括尾随0)。(作为练习,我将让您学习wchar_t代码)
因此,当在Linux上使用char时,您通常会在不知情的情况下使用Unicode。由于std::string与char一起工作,所以std::string已经可以使用unicode了。
请注意,与C string一样,std::string将考虑"olé“字符串包含4个字符,而不是3个字符。因此,您在截断/使用unicode字符时应该谨慎,因为在UTF-8中禁止某些字符的组合。
在Windows上?
在Windows上,这有点不同。在Unicode出现之前,Win32必须支持许多使用char和在世界各地生产的不同字符集/代码页上工作的应用程序。
因此,他们的解决方案是一个有趣的解决方案:如果应用程序使用char工作,那么字符字符串就会被编码/打印/显示在GUI标签上,使用机器上的本地字符集/代码页,这在很长一段时间内不可能是UTF-8。例如,在法语本地化的Windows中,"olé“应该是"olé”,但是在西里尔语的本地化窗口上(如果使用Windows-1251,则是“olй”)。因此,“历史应用程序”通常仍将以同样的方式工作。
对于基于Unicode的应用程序,Windows使用2字节宽的wchar_t,并以乌特夫-16编码,后者是用2字节字符编码的(或者至少是UCS-2,它只是缺少代理对,因此没有BMP之外的字符(>= 64K))。
使用char的应用程序被称为“多字节”(因为每个字形由一个或多个char组成),而使用wchar_t的应用程序被称为"widechar“(因为每个字形由一个或两个wchar_t组成)。有关更多信息,请参见MultiByteToWideChar和WideCharToMultiByte Win32转换API。
因此,如果您在Windows上工作,非常希望使用wchar_t (除非您使用一个框架来隐藏它,比如GTK或QT )。事实上,Windows在幕后使用wchar_t字符串,因此即使是历史应用程序在使用API (如SetWindowText() (低级API函数)在Win32 GUI上设置标签时,也会在wchar_t中转换它们的SetWindowText()字符串)。
记忆问题?
UTF-32是每个字符4个字节,所以没有什么可添加的,如果一个UTF-8文本和UTF-16文本使用的内存总是比UTF-32文本少或相同的话(通常更少)。
如果存在记忆问题,那么您应该知道,与大多数西方语言相比,UTF-8文本使用的内存将比相同的UTF-16更少。
然而,对于其他语言(中文、日语等),所使用的内存要么相同,要么比UTF-16略大一些。
总之,UTF-16通常每个字符使用2字节,有时使用4个字节(除非你在处理某种深奥的语言符号(克林贡?),而UTF-8将花费1到4个字节.
有关更多信息,请参见乌特夫-16。
结论
std::string 能容纳所有包含特殊字符的字符集吗?
注意:std::string适用于保存“二进制”缓冲区,而std::wstring不是!
在Linux上?是。在Windows上?仅适用于Windows用户当前区域设置的特殊字符。
编辑(在 std::string的注释之后,std::string将足以处理所有char-based字符串(每个char都是从0到255之间的数字)。但是:1. ASCII is supposed to go from 0 to 127. Higher `char`s are NOT ASCII.
2. a `char` from 0 to 127 will be held correctly
3. a `char` from 128 to 255 will have a signification depending on your encoding (unicode, non-unicode, etc.), but it will be able to hold all Unicode glyphs as long as they are encoded in UTF-8.std::wstring编译器都支持???
大多数情况下,除了GCC的编译器被移植到Windows之外。它在我的g++ 4.3.2上工作(在Linux下),并且我在Win32上使用了Unicode,自从C++ 6之后。wchar_t,比简单的char字符类型要大。它应该用于将索引(如Unicode符号)大于255 (或127,取决于.)的字符放入其中。发布于 2009-12-29 16:14:55
我建议避免在Windows或其他地方使用std::wstring,除非在接口需要时,或者在Windows调用附近的任何地方,并将各自的编码转换作为语法糖。
我的观点被总结在http://utf8everywhere.org中,我是其中的一位作者.
除非您的应用程序以API调用为中心,例如,主要是UI应用程序,否则建议将Unicode字符串存储在std::string中,并以UTF-8编码,在API调用附近执行转换。本文概述的好处超过了转换的明显烦恼,特别是在复杂的应用程序中。这对于多平台和图书馆的发展来说是双重的。
现在,回答你们的问题:
发布于 2011-11-07 06:07:09
所以,现在在座的每一位读者都应该对事实、情况有一个清晰的了解。如果不是,那么您必须阅读paercebal的非常全面的回答顺便说:谢谢!
我的实用主义结论非常简单:所有的C++ (和STL)“字符编码”的东西基本上都是坏的和无用的。把责任推到微软身上,反正也于事无补。
我的解决办法,经过深入的调查,很多挫折和相应的经验如下:
typedef std::string UTF8String)typedef std::wstring UCS2String) --这是对WIN32 API引入的混乱的妥协和让步)。UCS-2对大多数人来说已经足够了(稍后会有更多的介绍.)。转换很简单,谷歌应该在这里有所帮助.
就这样。在内存宝贵的地方使用UTF8String,对于所有UTF-8I/O,在必须解析和/或操作字符串的地方使用UCS2String。您可以随时在这两种表示之间进行转换。
替代品和改进
const wchar_t tt_iso88951[256] = {0,1,2,...}; )和适当的代码转换到和从UCS2来实现。typedef std::basic_string<uint32_t> UCS2String)。ICU或其他unicode库?
先进的东西。
https://stackoverflow.com/questions/402283
复制相似问题