关于C ++中完整unicode的基本问题

时间:2017-08-22 05:08:33

标签: c++ unicode wstring

在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设施真的可以这么糟糕吗?

我确定有人知道我在这里缺少的基本内容......

1 个答案:

答案 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_twchar_t(前缀L为litteral)是依赖于实现的类型,并且从C ++ 11开始,您还有char16_tu16string(前缀u)明确地使用UTF-16或char32_tu32string(前缀U)通过UTF-32获得完全的unicode支持。在U16string中将字符存储在BMP外部的问题是,您丢失了字符串的大小==字符数,这是使用宽字符而不是多字节字符的关键原因。

u32string的一个问题是io库仍然没有32位字符的直接专门化,但是正如转换器所拥有的那样,当您使用std::basic_fstream<char32_t>处理文件时,您可以轻松地使用它们(未经测试但是根据标准应该工作)。但是,cincoutcerr没有标准流,可能需要处理string或{中的原生 {1}},然后在C ++ 14中引入的标准转换器的帮助下转换u16string中的所有内容,如果仅使用C ++ 11,则转换为难的方式。

真正黑暗的一面是,由于本机部分目前依赖于操作系统,您将无法设置完全可移植的方式来处理完整的unicode - 或者至少我不知道。