查看unicode standard,他们建议使用普通char
来存储UTF-8编码的字符串。这是否与C ++和基本std::string
一样正常工作,或者存在UTF-8编码可能产生问题的情况?
例如,在计算长度时,它可能与字节数不同 - 这应该如何处理?阅读标准,我可能很好地使用char
数组进行存储,但我仍然需要自己编写像strlen
等函数来处理编码文本,导致到目前为止正如我所理解的那样,标准例程只能是ASCII,或者是期望宽文字(16位或更多),这是unicode标准不推荐的。到目前为止,我发现有关编码内容的最佳来源是Joel's on Software上的帖子,但它没有解释我们可怜的C ++开发人员应该使用的内容:)
答案 0 :(得分:5)
有一个名为“UTF8-CPP”的库,它允许您将UTF-8字符串存储在标准的std :: string对象中,并提供枚举和操作utf-8字符的附加函数。
我还没有测试过,所以我不知道它的价值,但我正在考虑自己使用它。
答案 1 :(得分:3)
ICU library(C,C ++,Java)的例子:
#include <iostream>
#include <unicode/unistr.h> // using ICU library
int main(int argc, char *argv[]) {
// constructing a Unicode string
UnicodeString ustr1("Привет"); // using platform's default codepage
// calculating the length in characters, should be 6
int ulen1=ustr1.length();
// extracting encoded characters from a string
int const bufsize=25;
char encoded[bufsize];
ustr1.extract(0,ulen1,encoded,bufsize,"UTF-8"); // forced UTF-8 encoding
// printing the result
std::cout << "Length of " << encoded << " is " << ulen1 << "\n";
return 0;
}
建设像
$ g++ -licuuc -o icu-example{,.cc}
运行
$ ./icu-example
Length of Привет is 6
适用于Linux的GCC 4.3.2和libicu 3.8.1。请注意,无论系统区域是什么,它都以UTF-8打印。如果你的不是UTF-8,你将无法正确看到它。
答案 2 :(得分:2)
这取决于你想用UTF8字符串做什么。如果你感兴趣的只是读入和读出UTF8字符串,那么只要你设置了正确的语言环境,它就会起作用。我们已经做了一段时间了。我们有几个服务器进程对字符串不做任何事情。用户在Java中设置字符串并以UTF8形式到达,我们在标准c str缓冲区中处理它们。然后,我们将数据发送回Java,将其转换回来。
如果你想要UTF8字符的长度,那么你需要能够为你处理翻译的函数。
但你可以推出自己的例子utf8-strlen
答案 3 :(得分:2)
strlen计算第一个\ 0之前的非空字符数。在UTF-8中,该计数是一个合理的数字(使用的字节数),但计数不是字符数(一个UTF-8字符通常是1-4个字符)。 basic_string不存储\ 0,但它也保留字节数。
strcpy或basic_string copy ctor复制所有字节而不太仔细。
由于UTF_8的编码方式,查找子字符串工作正常。字符的第一个字节的允许值不同于第二个到第4个字节(前者永远不会以10xxxxxx开头,后者总是以后者开始)
获取子字符串很棘手 - 您如何指定位置?如果通过搜索ASCII文本标记(例如[和])找到了开始和结束,则没有问题。你只需要获得中间的字节,这也是一个有效的UTF8字符串。你不能对位置,甚至是相对偏移进行编码。即使+1字符的相对偏移也很难;这是多少字节?你最终会编写像SkipOneChar这样的函数。
答案 4 :(得分:1)
我们解决了什么:将UTF8存储在std :: string中。除了计算长度之外,您现在可以执行大多数操作。当您需要这样的操作时,使用UTF8-&gt; std :: wstring转换函数(例如boost :: from_utf8)转换为std :: wstring。
答案 5 :(得分:0)
来自UTF-8 and Unicode FAQ: C support for Unicode:
#include <stdio.h>
#include <locale.h>
int main()
{
if (!setlocale(LC_CTYPE, "")) {
fprintf(stderr, "Can't set the specified locale! "
"Check LANG, LC_CTYPE, LC_ALL.\n");
return 1;
}
printf("%ls\n", L"Schöne Grüße");
return 0;
}
同样来自here:
好消息是,如果你使用
wchar_t*
字符串和系列 与它们相关的功能,如 你是wprintf
,wcslen
和wcslcat
处理Unicode值。在里面 在C ++世界中,您可以使用std::wstring
来实现 提供友好的界面。我唯一的 投诉是这些是32位(4 字节)字符,所以它们是内存 所有语言的猪。的原因 这个选择是它保证每一个 可以表示可能的角色 一个值。
PS。这可能是特定于Linux的。有一个ICU库来处理复杂的事情。