如何将像“\ u94b1”这样的字符串转换为C ++中的一个真实字符?

时间:2016-06-01 07:12:35

标签: c++ unicode

我们知道在字符串文字中,“\ u94b1”将转换为字符,在本例中为中文单词“钱”。但是,如果它在字符串中字面上是6个字符,说'\','u','9','4','b','1',我怎么能手动将它转换为字符?

例如:

string s1;
string s2 = "\u94b1";
cin >> s1;            //here I input \u94b1
cout << s1 << endl;   //here output \u94b1
cout << s2 << endl;   //and here output 钱

我想转换s1,以便cout << s1 << endl;也会输出

有什么建议吗?

3 个答案:

答案 0 :(得分:4)

事实上转换有点复杂。

string s2 = "\u94b1";

实际上相当于:

char cs2 = { 0xe9, 0x92, 0xb1, 0}; string s2 = cs2;

这意味着您正在初始化组成钱的UTF8表示的3个字符 - 您只需检查s2.c_str()以确保这一点。

所以要处理6个原始字符&#39; \#39; u&#39;,&#39; 9&#39;,&#39; 4&#39;,&#39 ; b&#39;,&#39; 1&#39;,您必须首先从string s1 = "\\u94b1";中提取wchar_t(您在阅读时获得的内容)。它很简单,只需跳过两个第一个字符并将其读作十六进制:

unsigned int ui;
std::istringstream is(s1.c_str() + 2);
is >> hex >> ui;

ui现在是0x94b1

现在,只要您拥有符合C ++ 11标准的系统,就可以使用std::convert_utf8转换它:

wchar_t wc = ui;
std::codecvt_utf8<wchar_t> conv;
const wchar_t *wnext;
char *next;
char cbuf[4] = {0}; // initialize the buffer to 0 to have a terminating null
std::mbstate_t state;
conv.out(state, &wc, &wc + 1, wnext, cbuf, cbuf+4, next);

cbuf现在包含在utf8中代表钱的3个字符和一个终止空值,你最终可以做到:

string s3 = cbuf;
cout << s3 << endl;

答案 1 :(得分:2)

您可以通过编写检查字符串是否包含反斜杠,字母u和四个十六进制数字的代码来执行此操作,并将其转换为Unicode代码点。然后你的std :: string实现可能假定为UTF-8,因此你将该代码点转换为1,2或3个UTF-8字节。

对于额外点,弄清楚如何在基本平面之外输入代码点。

答案 2 :(得分:1)

使用utfcpp(仅限标题),您可以执行以下操作:

#include </usr/include/utf8.h>

#include <cstdint>
#include <iostream>

std::string replace_utf8_escape_sequences(const std::string& str) {
    std::string result;
    std::string::size_type first = 0;
    std::string::size_type last = 0;
    while(true) {
        // Find an escape position
        last = str.find("\\u", last);
        if(last == std::string::npos) {
            result.append(str.begin() + first, str.end());
            break;
        }

        // Extract a 4 digit hexadecimal
        const char* hex = str.data() + last + 2;
        char* hex_end;
        std::uint_fast32_t code = std::strtoul(hex, &hex_end, 16);
        std::string::size_type hex_size = hex_end - hex;

        // Append the leading and converted string
        if(hex_size != 4) last = last + 2 + hex_size;
        else {
            result.append(str.begin() + first, str.begin() + last);
            try {
                utf8::utf16to8(&code, &code + 1, std::back_inserter(result));
            }
            catch(const utf8::exception&) {
                // Error Handling
                result.clear();
                break;
            }
            first = last = last + 2 + 4;
        }
    }
    return result;
}

int main()
{
    std::string source = "What is the meaning of '\\u94b1'  '\\u94b1' '\\u94b1' '\\u94b1' ?";
    std::string target = replace_utf8_escape_sequences(source);
    std::cout << "Conversion from \"" << source << "\" to \"" << target << "\"\n";
}