<本文PDF文档下载>std::locale
通过前面两节的知识,我们知道了在C/C++中,字符(串)和宽字符(串)之间的转换不是简单的,固定的数学关系,宽窄转换依赖于本地化策略集(locale)。换句话说,一个程序在运行之前并不知道系统的本地化策略集是什么,程序只有在运行之后才通过locale获得当时的本地化策略集。
C有自己的locale函数,我们这里直接介绍C++的locale类。
先讨论locale的构造函数:
locale() throw();
这个构造函数是获得当前程序的locale,用法如下:
std::locale app_loc = std::locale();
或者(这是构造对象的两种表示方式,后同)
std::locale app_loc;
另外一个构造函数是:
explicit locale(const char* name);
这个构造函数以name的名字创建新的locale。重要的locale对象有:
std::locale sys_loc(""); //获得当前系统环境的locale
std::locale C_loc("C"); 或者 std::locale C_loc = std::locale::classic(); //获得C定义locale
std::locale old_loc = std::locale::global(new_loc); //将new_loc设置为当前全局locale,并将原来的locale返回给old_loc
除了这些,其它的name具体名字依赖于C++编译器和操作系统,比如Linux下gcc中文系统的locale名字为"zh_CN.UTF-8",中文Windows可以用"chs"(更加完整的名字可以用name()函数查看)。
mbstowcs()和wcstombs()
这两个C运行时库函数依赖于全局locale进行转换,所以,使用前必须先设置全局locale。
std::locale已经包含在<iostream>中了,再加上我们需要用到的C++字符串,所以包含<string>。
我们先看窄到宽的转换函数:
const std::wstring s2ws(const std::string& s)
{
std::locale old_loc =
std::locale::global(std::locale(""));
const char* src_str = s.c_str();
const size_t buffer_size = s.size() + 1;
wchar_t* dst_wstr = new wchar_t[buffer_size];
wmemset(dst_wstr, 0, buffer_size);
mbstowcs(dst_wstr, src_str, buffer_size);
std::wstring result = dst_wstr;
delete []dst_wstr;
std::locale::global(old_loc);
return result;
}
我们将全局locale设置为系统locale,并保存原来的全局locale在old_loc中。
在制定转换空间缓存大小的时候,考虑如下:char是用1个或多个对象,也就是1个或者多个字节来表示各种符号:比如,GB2312用1个字节表示数字和字母,2个字节表示汉字;UTF-8用一个字节表示数字和字母,3个字节表示汉字,4个字节表示一些很少用到的符号,比如音乐中G大调符号等。wchar_t是用1个对象(2字节或者4字节)来表示各种符号。因此,表示同样的字符串,宽字符串的大小(也就是wchar_t对象的数量)总是小于或者等于窄字符串大小(char对象数量)的。+1是为了在最后预留一个值为0的对象,以便让C风格的char或者wchar_t字符串自动截断——这当然是宽串大小等于窄串大小的时候才会用上的,大部分时候,字符串早在前面某个转换完毕的位置就被0值对象所截断了。
最后我们将全局locale设置回原来的old_loc。
窄串到宽串的转换函数:
const std::string ws2s(const std::wstring& ws)
{
std::locale old_loc =
std::locale::global(std::locale(""));
const wchar_t* src_wstr = ws.c_str();
size_t buffer_size = ws.size() * 4 + 1;
char* dst_str = new char[buffer_size];
memset(dst_str, 0, buffer_size);
wcstombs(dst_str ,src_wstr, buffer_size);
std::string result = dst_str;
delete []dst_str;
std::locale::global(old_loc);
return result;
}
这里考虑转换空间缓存大小的策略正好相反,在最极端的情况下,所有的wchar_t都需要4个char来表示,所以最大的可能就是4倍加1。
这两个函数在VC和gcc中都能正常运行(MinGW因为前面说到的原因不支持宽字符的正常使用),在VC中会给出不安全的警告,这是告诉给那些弄不清宽窄转换实质的人的警告,对于了解到目前这些知识的你我来说,这就是啰嗦了。
posted on 2010-06-26 11:17
lf426 阅读(2957)
评论(1) 编辑 收藏 引用 所属分类:
语言基础、数据结构与算法