在C ++中使用完整unicode有哪些适当的工具?
例如,我尝试过:
int main()
{
std::wstring name;
std::wcout << "Enter unicode: " << std::endl;
std::getline(std::wcin, name);
std::wcout << name << std::endl;
return 0;
}
它在输入角色时没有像我期望的那样工作:或者不在Unicode BMP中的其他人。我打印出一条空行。
普通字符串适用于任何高达16位的代码点,wstring,wcin,wcout只是没有工作,因为我期待和一些谷歌搜索没有帮助我看到这可能是错的
编辑(文件I / O也有问题!):
我想知道这是否可以与控制台I / O本身有关,并希望尝试相同的文件I / O作为实验。我查看了api,并提出了这个编译并运行良好的信息:
int main()
{
std::string filename;
std::cout << "Enter file to append to: " << std::endl;
std::getline(std::cin, filename);
std::wifstream file;
std::wstringstream buff;
file.open(filename);
std::wstring txt;
buff << file.rdbuf();
file.close();
txt = buff.str();
std::wcout << txt << std::endl;
return 0;
}
但是当我把它指向我的文件时主要是lorem ipsum和一些非BMP字符时,它会将文件打印到第一个非BMP字符,然后提前停止。现代C ++中的Unicode设施真的可以这么糟糕吗?
我确定有人知道我在这里缺少的基本内容......
答案 0 :(得分:1)
您处于C ++ unicode的灰色区域。 Unicode最初是由7位ASCII字符的扩展开始的,或者是多字节字符到普通的16位字符,后来成为BMP。这些16位字符是由Java等语言和Windows等系统本地采用的。 C和C ++在标准观点上更加保守,认为wchar_t
是实现相关的宽字符集,可以是16或32位宽(甚至更多......)根据要求。好的一面是它是可扩展的,黑暗的一面是,当wchar_t只有16位时,从未明确表示应该如何表示非BMP unicode字符。
然后创建UTF-16以允许那些非BMP字符的标准表示,其缺点是它们需要2个16位字符,并且std::char_traits<wchar_t>::length
将再次出错如果其中一些存在于wstring中。
这就是大多数C ++实现选择wchar_t
基本 IO只会正确处理length
的BMP unicode字符以返回真实字符数的原因
C ++ - ish方法是在需要完全unicode支持时使用基于char32_t
的字符串。事实上,wstring_t
和wchar_t
(前缀L为litteral)是依赖于实现的类型,并且从C ++ 11开始,您还有char16_t
和u16string
(前缀u)明确地使用UTF-16或char32_t
和u32string
(前缀U)通过UTF-32获得完全的unicode支持。在U16string中将字符存储在BMP外部的问题是,您丢失了字符串的大小==字符数,这是使用宽字符而不是多字节字符的关键原因。
u32string的一个问题是io库仍然没有32位字符的直接专门化,但是正如转换器所拥有的那样,当您使用std::basic_fstream<char32_t>
处理文件时,您可以轻松地使用它们(未经测试但是根据标准应该工作)。但是,cin
,cout
和cerr
没有标准流,可能需要处理string
或{中的原生 {1}},然后在C ++ 14中引入的标准转换器的帮助下转换u16string
中的所有内容,如果仅使用C ++ 11,则转换为难的方式。
真正黑暗的一面是,由于本机部分目前依赖于操作系统,您将无法设置完全可移植的方式来处理完整的unicode - 或者至少我不知道。