如何在 C++11 中将 std::string 转换为 std::u32string?
How to convert std::string to std::u32string in C++11?
我正在使用 C++11 中的 Unicode,我现在无法将 std::string 转换为 std::u32string。
我的代码如下:
#include <iostream>
#include <string>
#include <locale>
#include "unicode/unistr.h"
#include "unicode/ustream.h"
int main()
{
constexpr char locale_name[] = "";
setlocale( LC_ALL, locale_name );
std::locale::global(std::locale(locale_name));
std::ios_base::sync_with_stdio(false);
std::wcin.imbue(std::locale());
std::wcout.imbue(std::locale());
std::string str="hello☺";
std::u32string s(str.begin(),str.end());
icu::UnicodeString ustr = icu::UnicodeString::fromUTF32(reinterpret_cast<const UChar32 *>(s.c_str()), s.size());
std::cout << "Unicode string is: " << ustr << std::endl;
std::cout << "Size of unicode string = " << ustr.countChar32() << std::endl;
std::cout << "Individual characters of the string are:" << std::endl;
for(int i=0; i < ustr.countChar32(); i++)
std::cout << icu::UnicodeString(ustr.char32At(i)) << std::endl;
return 0;
}
执行输出是:(这不是预期的)
Unicode string is: hello�������
Size of unicode string = 12
Individual characters of the string are:
h
e
l
l
o
�
�
�
�
�
�
�
如果有任何 ICU 库函数存在,请提出建议
输出有意义。大概您认为您正在定义一个包含 7 个字符的字符串?看看str.size()
。您定义了一个包含 12 个字符的字符串!
即使您能够在程序中键入 "hello☺"
,这个字符串文字也不仅仅包含七个字节。最后两个字符中的每一个都被扩展为多个字节,因为这些字符超出了扩展的 ASCII 范围(0 到 255 或 -128 到 127)。结果是一个 12 字节的字符串文字,它初始化一个 12 个字符的 string
,它又初始化一个 12 个字符的 u32string
。你已经破坏了你想要代表的角色。
示例:字符'☺'
表示为三个字节[=16=]xE2[=16=]x98[=16=]xBA
。如果 char
在您的系统上签名(很可能),这三个字节的值为 -30、-104 和 -70。转换为 char32_t
会将这些值中的每一个提升为 32 位,然后将有符号转换为无符号,从而产生三个值 4294967266
、4294967192
和 4294967226
。您可能想要的是将这些字节连接成单个 char32_t
值 [=23=]x00E298BA
。但是,您的转换不提供(重新)组合字节的机制。
同理,字符''
由四个字节[=25=]xF0[=25=]x9F[=25=]x98[=25=]x86
表示。这些被转换成四个 32 位整数而不是单个值 [=26=]xF09F9886
.
要获得您想要的结果,您需要告诉编译器将您的字符串文字解释为 7 个字符。尝试 s
的以下初始化:
std::u32string s = U"hello☺";
字符串文字上的 U
前缀告诉编译器每个字符代表一个 UTF-32 字符。这会产生所需的 7 个字符的字符串(假设您的编译器和编辑器就字符编码达成一致,我认为这很有可能)。
免费调试要点:当你的输出不是你期望的,检查每个阶段的数据以确保你的输入是如你所愿。
谢谢大家的帮助!
使用这两个链接,我找到了一些相关函数:
How to convert a Unicode code point to characters in C++ using ICU?
我尝试使用 codecvt
函数,但出现错误:
fatal error: codecvt: No such file or directory
#include <codecvt>
^
compilation terminated.
所以,我跳过了那个 & 在进一步搜索中,我发现 mbrtoc32()
函数有效:)
这是工作代码:
#include <iostream>
#include <string>
#include <locale>
#include "unicode/unistr.h"
#include "unicode/ustream.h"
#include <cassert>
#include <cwchar>
#include <uchar.h>
int main()
{
constexpr char locale_name[] = "";
setlocale( LC_ALL, locale_name );
std::locale::global(std::locale(locale_name));
std::ios_base::sync_with_stdio(false);
std::wcin.imbue(std::locale());
std::wcout.imbue(std::locale());
std::string str;
std::cin >> str;
//For example, the input string is "hello☺"
std::mbstate_t state{}; // zero-initialized to initial state
char32_t c32;
const char *ptr = str.c_str(), *end = str.c_str() + str.size() + 1;
icu::UnicodeString ustr;
while(std::size_t rc = mbrtoc32(&c32, ptr, end - ptr, &state))
{
icu::UnicodeString temp((UChar32)c32);
ustr+=temp;
assert(rc != (std::size_t)-3); // no surrogates in UTF-32
if(rc == (std::size_t)-1) break;
if(rc == (std::size_t)-2) break;
ptr+=rc;
}
std::cout << "Unicode string is: " << ustr << std::endl;
std::cout << "Size of unicode string = " << ustr.countChar32() << std::endl;
std::cout << "Individual characters of the string are:" << std::endl;
for(int i=0; i < ustr.countChar32(); i++)
std::cout << icu::UnicodeString(ustr.char32At(i)) << std::endl;
return 0;
}
输入 hello☺
时的输出符合预期:
Unicode string is: hello☺
Size of unicode string = 7
Individual characters of the string are:
h
e
l
l
o
☺
我正在使用 C++11 中的 Unicode,我现在无法将 std::string 转换为 std::u32string。
我的代码如下:
#include <iostream>
#include <string>
#include <locale>
#include "unicode/unistr.h"
#include "unicode/ustream.h"
int main()
{
constexpr char locale_name[] = "";
setlocale( LC_ALL, locale_name );
std::locale::global(std::locale(locale_name));
std::ios_base::sync_with_stdio(false);
std::wcin.imbue(std::locale());
std::wcout.imbue(std::locale());
std::string str="hello☺";
std::u32string s(str.begin(),str.end());
icu::UnicodeString ustr = icu::UnicodeString::fromUTF32(reinterpret_cast<const UChar32 *>(s.c_str()), s.size());
std::cout << "Unicode string is: " << ustr << std::endl;
std::cout << "Size of unicode string = " << ustr.countChar32() << std::endl;
std::cout << "Individual characters of the string are:" << std::endl;
for(int i=0; i < ustr.countChar32(); i++)
std::cout << icu::UnicodeString(ustr.char32At(i)) << std::endl;
return 0;
}
执行输出是:(这不是预期的)
Unicode string is: hello�������
Size of unicode string = 12
Individual characters of the string are:
h
e
l
l
o
�
�
�
�
�
�
�
如果有任何 ICU 库函数存在,请提出建议
输出有意义。大概您认为您正在定义一个包含 7 个字符的字符串?看看str.size()
。您定义了一个包含 12 个字符的字符串!
即使您能够在程序中键入 "hello☺"
,这个字符串文字也不仅仅包含七个字节。最后两个字符中的每一个都被扩展为多个字节,因为这些字符超出了扩展的 ASCII 范围(0 到 255 或 -128 到 127)。结果是一个 12 字节的字符串文字,它初始化一个 12 个字符的 string
,它又初始化一个 12 个字符的 u32string
。你已经破坏了你想要代表的角色。
示例:字符'☺'
表示为三个字节[=16=]xE2[=16=]x98[=16=]xBA
。如果 char
在您的系统上签名(很可能),这三个字节的值为 -30、-104 和 -70。转换为 char32_t
会将这些值中的每一个提升为 32 位,然后将有符号转换为无符号,从而产生三个值 4294967266
、4294967192
和 4294967226
。您可能想要的是将这些字节连接成单个 char32_t
值 [=23=]x00E298BA
。但是,您的转换不提供(重新)组合字节的机制。
同理,字符''
由四个字节[=25=]xF0[=25=]x9F[=25=]x98[=25=]x86
表示。这些被转换成四个 32 位整数而不是单个值 [=26=]xF09F9886
.
要获得您想要的结果,您需要告诉编译器将您的字符串文字解释为 7 个字符。尝试 s
的以下初始化:
std::u32string s = U"hello☺";
字符串文字上的 U
前缀告诉编译器每个字符代表一个 UTF-32 字符。这会产生所需的 7 个字符的字符串(假设您的编译器和编辑器就字符编码达成一致,我认为这很有可能)。
免费调试要点:当你的输出不是你期望的,检查每个阶段的数据以确保你的输入是如你所愿。
谢谢大家的帮助!
使用这两个链接,我找到了一些相关函数:
How to convert a Unicode code point to characters in C++ using ICU?
我尝试使用 codecvt
函数,但出现错误:
fatal error: codecvt: No such file or directory
#include <codecvt>
^
compilation terminated.
所以,我跳过了那个 & 在进一步搜索中,我发现 mbrtoc32()
函数有效:)
这是工作代码:
#include <iostream>
#include <string>
#include <locale>
#include "unicode/unistr.h"
#include "unicode/ustream.h"
#include <cassert>
#include <cwchar>
#include <uchar.h>
int main()
{
constexpr char locale_name[] = "";
setlocale( LC_ALL, locale_name );
std::locale::global(std::locale(locale_name));
std::ios_base::sync_with_stdio(false);
std::wcin.imbue(std::locale());
std::wcout.imbue(std::locale());
std::string str;
std::cin >> str;
//For example, the input string is "hello☺"
std::mbstate_t state{}; // zero-initialized to initial state
char32_t c32;
const char *ptr = str.c_str(), *end = str.c_str() + str.size() + 1;
icu::UnicodeString ustr;
while(std::size_t rc = mbrtoc32(&c32, ptr, end - ptr, &state))
{
icu::UnicodeString temp((UChar32)c32);
ustr+=temp;
assert(rc != (std::size_t)-3); // no surrogates in UTF-32
if(rc == (std::size_t)-1) break;
if(rc == (std::size_t)-2) break;
ptr+=rc;
}
std::cout << "Unicode string is: " << ustr << std::endl;
std::cout << "Size of unicode string = " << ustr.countChar32() << std::endl;
std::cout << "Individual characters of the string are:" << std::endl;
for(int i=0; i < ustr.countChar32(); i++)
std::cout << icu::UnicodeString(ustr.char32At(i)) << std::endl;
return 0;
}
输入 hello☺
时的输出符合预期:
Unicode string is: hello☺
Size of unicode string = 7
Individual characters of the string are:
h
e
l
l
o
☺