Как преобразовать строку типа "u94b1 " в один реальный символ на C++?
мы знаем, что в строковом литерале "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 ответов
на самом деле преобразование немного сложнее.
string s2 = "\u94b1";
фактически является эквивалентом:
char cs2 = { 0xe9, 0x92, 0xb1, 0}; string s2 = cs2;
это означает, что вы инициализируете его 3 символа, которые составляют представление UTF8 钱-you char just examine s2.c_str()
чтобы убедиться в этом.
Итак, чтобы обработать 6 необработанных символов'\', 'u', '9', '4', 'b', '1', Вы должны сначала извлечь wchar_t из string s1 = "\u94b1";
(что вы получаете, когда вы читаете это). Это легко, просто пропустите Два первых символа и прочитайте его как шестнадцатеричный:
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
теперь содержит 3 символа, представляющих 钱 в utf8 и завершающий null, и Вы, наконец, можете сделать:
string s3 = cbuf;
cout << s3 << endl;
вы делаете это, написав код, который проверяет, содержит ли строка обратную косую черту, букву u и четыре шестнадцатеричные цифры, и преобразует это в кодовую точку Unicode. Тогда ваша реализация std:: string, вероятно, предполагает UTF-8, поэтому вы переводите эту кодовую точку в 1, 2 или 3 байта UTF-8.
для дополнительных точек выясните, как вводить кодовые точки за пределами базовой плоскости.
С 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";
}