pae*_*bal 969
string?wstring?std::string是一个basic_string模板化的char,std::wstring在...上wchar_t.
char 与 wchar_tchar应该持有一个字符,通常是一个8位字符.
wchar_t事情变得棘手:
然而,事情变得棘手:在Linux上,a wchar_t是4个字节,而在Windows上,它是2个字节.
问题是既不直接char也不wchar_t与unicode直接相关.
我们来看一个Linux操作系统:我的Ubuntu系统已经知道了unicode.当我使用char字符串时,它本地编码为UTF-8(即字符串的字符串).以下代码:
#include <cstring>
#include <iostream>
int main(int argc, char* argv[])
{
const char text[] = "olé" ;
std::cout << "sizeof(char) : " << sizeof(char) << std::endl ;
std::cout << "text : " << text << std::endl ;
std::cout << "sizeof(text) : " << sizeof(text) << std::endl ;
std::cout << "strlen(text) : " << strlen(text) << std::endl ;
std::cout << "text(ordinals) :" ;
for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
{
std::cout << " " << static_cast<unsigned int>(
static_cast<unsigned char>(text[i])
);
}
std::cout << std::endl << std::endl ;
// - - -
const wchar_t wtext[] = L"olé" ;
std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ;
//std::cout << "wtext : " << wtext << std::endl ; <- error
std::cout << "wtext : UNABLE TO CONVERT NATIVELY." << std::endl ;
std::wcout << L"wtext : " << wtext << std::endl;
std::cout << "sizeof(wtext) : " << sizeof(wtext) << std::endl ;
std::cout << "wcslen(wtext) : " << wcslen(wtext) << std::endl ;
std::cout << "wtext(ordinals) :" ;
for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
{
std::cout << " " << static_cast<unsigned int>(
static_cast<unsigned short>(wtext[i])
);
}
std::cout << std::endl << std::endl ;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出以下文字:
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
Run Code Online (Sandbox Code Playgroud)
你会看到"olé"文本char真的由四个字符构成:110,108,195 和169(不包括尾随零).(我会让你学习wchar_t代码作为练习)
因此,在使用charLinux时,通常应该最终使用Unicode而不知道它.随着std::string工作char,所以std::string已经unicode准备好了.
请注意std::string,与C字符串API一样,将"olé"字符串视为包含4个字符,而不是3个字符.因此,在截断/播放unicode字符时应该谨慎,因为在UTF-8中禁止使用某些字符组合.
在Windows上,这有点不同.在Unicode出现之前,Win32必须支持许多在全世界生产的char不同字符集/代码页上使用的应用程序.
因此,他们的解决方案很有趣:如果应用程序可以使用char,则使用计算机上的本地字符集/代码页在GUI标签上编码/打印/显示字符串.例如,"olé"在法语本地化的Windows中将是"olé",但在西里尔语本地化的Windows上会有所不同(如果使用Windows-1251,则为"ol" ).因此,"历史应用程序"通常仍然以相同的方式工作.
对于基于Unicode的应用程序,Windows使用wchar_t2字节宽,并以UTF-16编码,UTF-16是以2字节字符进行Unicode编码(或者至少是兼容性最强的UCS-2,几乎是同样的事情IIRC).
使用char的应用程序称为"多字节"(因为每个字形由一个或多个chars组成),而使用wchar_t的应用程序称为"widechar"(因为每个字形由一个或两个组成wchar_t.有关详细信息,请参阅MultiByteToWideChar和WideCharToMultiByte Win32转换API.
因此,如果你在Windows上工作,你非常想使用wchar_t(除非你使用隐藏它的框架,如GTK +或QT ......).事实是,在幕后,Windows使用wchar_t字符串,因此即使是历史应用程序也会char在wchar_t使用API时将其字符串转换为SetWindowText()(低级API函数在Win32 GUI上设置标签).
UTF-32每个字符有4个字节,所以没有太多要添加,只要UTF-8文本和UTF-16文本总是使用比UTF-32文本更少或相同的内存量(通常更少) ).
如果存在内存问题,那么您应该知道,对于大多数西方语言,UTF-8文本将使用比相同UTF-16文本更少的内存.
但是,对于其他语言(中文,日文等),UTF-8使用的内存要么相同,要么略大于UTF-16.
总而言之,UTF-16主要使用每个字符2个和偶尔4个字节(除非你正在处理某种深奥的语言字形(Klingon?Elvish?),而UTF-8将花费1到4个字节.
有关详细信息,请参见http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16.
什么时候我应该使用std :: wstring而不是std :: string?
在Linux上?几乎从不 (§).
在Windows上?几乎总是 (§).
在跨平台代码?取决于你的工具包......
(§):除非您使用工具包/框架另有说法
可以std::string保存包含特殊字符的所有ASCII字符集吗?
注意:A std::string适合保存'二进制'缓冲区,其中a std::wstring不是!
在Linux上?是.
在Windows上?只有特殊字符可用于Windows用户的当前区域设置.
编辑(在Johann Gerell的评论之后):
a std::string足以处理所有char基于字符串的字符串(每个字符串char都是0到255之间的数字).但:
chars不是ASCII.char从0到127将被正确举行char从128到255将有一个意义取决于您的编码(unicode的,非Unicode等),但它就能只要持有所有Unicode字形,因为它们是UTF-8编码.是std::wstring几乎所有流行的C++编译器的支持?
大多数情况下,除了移植到Windows的基于GCC的编译器.
它适用于我的g ++ 4.3.2(在Linux下),我在Win32上使用Unicode API,因为Visual C++ 6.
什么是广泛的角色?
在C/C++上,它是一个wchar_t大于简单char字符类型的字符类型.它应该用于放置其索引(如Unicode字形)大于255(或127,取决于...)的字符.
Pav*_*sky 64
我建议std::wstring在Windows或其他地方避免使用,除非接口需要,或者在Windows API调用附近的任何地方以及作为语法糖的相应编码转换.
我的观点总结在http://utf8everywhere.org,其中我是其合着者.
除非您的应用程序是以API调用为中心的,例如主要是UI应用程序,否则建议将Unicode字符串存储在std :: string中并以UTF-8编码,在API调用附近执行转换.本文中概述的好处超过了转换的明显烦恼,特别是在复杂的应用程序中.对于多平台和库开发来说,这是双倍的.
现在,回答你的问题:
Fru*_*nsi 36
所以,现在每个读者都应该清楚地了解事实和情况.如果没有,那么你必须阅读paercebal非常全面的答案 [顺便说一句:谢谢!].
我的实用结论非常简单:所有C++(和STL)"字符编码"的东西都基本上是破碎和无用的.无论如何归咎于微软,无论如何都无济于事.
我的解决方案,经过深入调查,非常沮丧和相应的经验如下:
接受,你必须自己负责编码和转换的东西(你会发现它的大部分都是微不足道的)
对任何UTF-8编码的字符串使用std :: string(只是一个typedef std::string UTF8String)
接受这样一个UTF8String对象只是一个愚蠢但便宜的容器.永远不要直接访问和/或操纵其中的字符(不搜索,替换等).你可以,但你真的真的,真的不想浪费你的时间为多字节字符串编写文本操作算法!即使其他人已经做过这样的蠢事,也不要这样做!随它去!(嗯,有些情况下有意义......只需使用ICU库).
对于UCS-2编码的字符串使用std :: wstring(typedef std::wstring UCS2String) - 这是一种妥协,并且是对WIN32 API引入的混乱的让步.UCS-2足以满足我们大多数人的需求(稍后会详细介绍......).
每当需要逐个字符访问(读取,操作等)时,都使用UCS2String实例.任何基于字符的处理都应以非多字节表示形式完成.它简单,快速,简单.
添加两个实用程序函数来在UTF-8和UCS-2之间来回转换:
UCS2String ConvertToUCS2( const UTF8String &str );
UTF8String ConvertToUTF8( const UCS2String &str );
Run Code Online (Sandbox Code Playgroud)转换很简单,谷歌应该在这里帮助...
而已.在内存珍贵的地方和所有UTF-8 I/O使用UTF8String.在必须解析和/或操作字符串的任何地方使用UCS2String.您可以随时在这两个表示之间进行转换.
替代方案和改进
转换为单字节字符编码(例如ISO-8859-1)可以借助普通转换表实现,例如const wchar_t tt_iso88951[256] = {0,1,2,...};,用于转换到UCS2和从UCS2转换的适当代码.
如果UCS-2不够,那么切换到UCS-4(typedef std::basic_string<uint32_t> UCS2String)
ICU或其他unicode库?
Joh*_*itb 25
如果要在字符串中存储宽字符.wide取决于实施.如果我没记错的话,Visual C++默认为16位,而GCC默认值取决于目标.它的长度为32位.请注意wchar_t(宽字符类型)与unicode无关.它只是保证它可以存储实现由其语言环境支持的最大字符集的所有成员,并且至少与char一样长.您也可以使用编码来很好地存储 unicode字符串.但它不会理解unicode代码点的含义.所以std::stringutf-8str.size()不会给你字符串中的逻辑字符数量,而只是存储在该字符串/ wstring中的char或wchar_t元素的数量.出于这个原因,gtk/glib C++包装器开发了一个Glib::ustring可以处理utf-8的类.
如果你的wchar_t是32位长,那么你可以utf-32用作unicode编码,你可以使用固定的(utf-32是固定长度)编码来存储和处理unicode字符串.这意味着你的wstring的s.size()函数,然后返回wchar_t的元素适量和逻辑字符.
小智 5
我经常使用std :: string来保存utf-8字符而没有任何问题.我衷心地建议在与使用utf-8作为本机字符串类型的API接口时执行此操作.
例如,在将代码与Tcl解释器连接时,我使用utf-8.
主要的警告是std :: string的长度,不再是字符串中的字符数.
小智 5
好问题!我认为数据编码(有时还涉及字符集)是一种内存表达机制,以便将数据保存到文件或通过网络传输数据,所以我回答这个问题:
1. 我什么时候应该使用 std::wstring 而不是 std::string?
如果编程平台或API函数是单字节的,我们想处理或解析一些Unicode数据,例如从Windows'.REG文件或网络2字节流中读取,我们应该声明std::wstring变量以方便处理它们。例如:wstring ws=L"??a"(6 个八位字节内存:0x4E2D 0x56FD 0x0061),我们可以使用 ws[0] 来获取字符 '?' 和 ws[1] 得到字符 '?' 和 ws[2] 得到字符 'a' 等。
2. std::string 能否保存整个 ASCII 字符集,包括特殊字符?
是的。但是注意:美式ASCII,意思是每个0x00~0xFF octet代表一个字符,包括可打印的文本,如“123abc&*_&”,你说的特殊的,大多打印为'.' 避免混淆编辑器或终端。还有一些国家扩展了他们自己的“ASCII”字符集,例如中文,使用2个八位字节来代表一个字符。
3.所有流行的C++编译器都支持std::wstring吗?
也许,或者大部分。我使用过:VC++6 和 GCC 3.3,是的
4. 什么是“宽字符”?
宽字符主要表示使用 2 个八位字节或 4 个八位字节来容纳所有国家/地区的字符。2 个八位字节 UCS2 是一个代表性的样本,进一步例如英语 'a',它的内存是 0x0061 的 2 个八位字节(相对于 ASCII 'a 的内存是 1 个八位字节 0x61)
| 归档时间: |
|
| 查看次数: |
292303 次 |
| 最近记录: |