我正在学习C++中的Unicode,但是我很难让它正常工作。我尝试将单个字符视为uint64_t。如果我只需要打印字符,那么它可以正常工作,但问题在于我需要将它们转换为大写字母。我可以将大写字母存储在数组中,并且只需使用与小写字母相同的索引,但我正在寻找更优雅的解决方案。我发现了这个类似的问题,但大多数答案都使用了宽字符,这不是我能使用的东西。这是我的尝试:
#include <iostream>
#include <locale>
#include <string>
#include <cstdint>
#include <algorithm>
// hacky solution to store a multibyte character in a uint64_t
#define E(c) ((((uint64_t) 0 | (uint32_t) c[0]) << 32) | (uint32_t) c[1])
typedef std::string::value_type char_t;
char_t upcase(char_t ch) {
return std::use_facet<std::ctype<char_t>>(std::locale()).toupper(ch);
}
std::string toupper(const std::string &src) {
std::string result;
std::transform(src.begin(), src.end(), std::back_inserter(result), upcase);
return result;
}
const uint64_t VOWS_EXTRA[]
{
E("å") , E("ä"), E("ö"), E("ij"), E("ø"), E("æ")
};
int main(void) {
char name[5];
std::locale::global(std::locale("sv_SE.UTF8"));
name[0] = (VOWS_EXTRA[3] >> 32) & ~((uint32_t)0);
name[1] = VOWS_EXTRA[3] & ~((uint32_t)0);
name[2] = '\0';
std::cout << toupper(name) << std::endl;
}
我希望这段代码能够打印出字符
IJ
,但实际上它打印出了与一开始相同的字符(ij
)。
(编辑:好的,我在这里阅读了更多关于标准C++对Unicode的支持。看起来最好的选择是使用ICU或Boost.locale来完成此任务。由于C++将std::string视为二进制数据块,因此似乎不容易正确地将Unicode字母大写。我认为,我的uint64_t hacky解决方案并没有比C++标准库更有用,甚至可能更糟。我会很感激一个使用ICU实现上述行为的示例。)
std::locale::global(std::locale("sv_SE.UTF8"))
在Windows上是不兼容的,除非你使用非常特殊的编译器。微软的运行时不支持UTF-8语言环境。请参阅setlocale
的文档。 - Cheers and hth. - Alfu"Oh, it's that easy?"
。主要问题是基本字符类型仍然是“char”。 - Cheers and hth. - Alf