c 中如何处理中文字符。学过c 的都知道标准库中的 std::string更像是一个存储着 char的容器,而不是普遍意义上的字符串。而我们的中文字符又无法使用单个 char进行存储。
常见用于中文的的字符编码有 gbk和 utf-8,utf-16等,在windows中文操作系统中,默认字符编码是 gbk使用2个字节存储一个中文字符;而在linux以及macos中使用 utf-8编码。utf-8编码是一个变长的编码:一个ascil字符只需1字节编码;带有变音符号的其他语言文字的字母需要2字节编码;中文以及日韩等一些亚洲文字需要3个字节编码;其他一些极少使用的字符使用4个字节编码。
那c 中的 std::string采用什么编码呢?一般来说,在windows中文环境下,c 源文件的编码通常为gbk; 在linux及macos环境下,默认的为utf-8 编码。在不依赖第三方库处理c 字符串时,一般可以使用 std::string进行读写,输入和输出;当要进行中文处理的时候,将其转为 std::wstring进行。当然,如果你需要进行复杂的字符串处理,可以通过第三方库例如,icu、qt、poco等,这些第三方库提供了很多强大的功能。
下面程序演示了如何进行两者的转化,最后将转换后的 std::wstring使用空格进行分割输出(程序在macos上运行通过,在windows下可能还需要额外工作)。
// 中文字符串使用
#include
#include
#include
#include
#include
#include
#include
export module cstring;
using std::print;
using std::println;
using std::string;
using std::wstring;
using std::vector;
export class solution {
public:
static void run() {
// 定义一个普通字符串,使用现代c 的println函数进行输出
const string s = "你好 jay chou";
println("采用std::string存储的「{}」的长度为{}", s, s.length());
// 将string转为wstring,这里的codecvt_utf8对象用于将utf-8编码的字符串转为宽字符串
std::wstring_convert> converter;
const wstring ws = converter.from_bytes(s.data());
// 由于println函数不支持wstring的输出,这里输出仍然采用char存储的字符串
println("采用std::wstring存储的「{}」的长度为{}", s, ws.length());
// 将本地编码支持设置为系统环境变量默认编码
std::setlocale(lc_all, "");
// 遍历wstring,将宽字符转为utf-8编码的字符,中文是三个字节长度
for (const auto& c: ws) {
char chars[3] = "";
std::wctomb(chars, c);
print("{}\t", chars);
}
println();
// 将字符串按照空格及其标点符号分割,l前缀用于标识宽字符
// 这里使用了现代c 中的range,通过管道运算符实现了字符串分割然后将分割结果转为wstring
auto tokens = ws |
std::views::split(' ') |
std::ranges::to>();
// 这里使用了ranges的for_each函数,配合lambda表达式进行wstring的输出
// 注意cout和print函数都不支持wstring,这里使用wcout进行输出
std::ranges::for_each(tokens, [](const auto& token) {
std::wcout << token << std::endl;
});
}
};
运行之后的结果如下图: