如何在C++中使用UTF8字符数组?

16

在C++(VC2010)中,是否可以使用char *处理UTF8编码?

例如,如果我的源文件以UTF8保存,并且我像这样编写:

const char* c = "aäáéöő";

是否有可能将其转换为UTF-8编码? 如果可以,如何使用?

char* c2 = new char[strlen("aäáéöő")];

如何进行动态内存分配以便字符长度可变?


似乎它还没有被实现,或者可能需要一些编译器参数。 - sekmet64
1
不,VS2010实现了C++0x的5个特性:lambda、右值引用、auto/decltype(类型推断)、nullptr。这些特性在C++11标准最终确定之前就已经完成了(上个月)。 - Klaim
啊,是的,Lambda表达式和nullptr指针。不过现在有一些很好的新库。 - Skurmedel
2
@Bo,UTF-8编码保证没有编码与\0匹配。 - Andy Finkenstadt
从技术上讲,UTF-8编码可以包含\0,但仅当文本本身包含\0时才会出现,这对于大多数“文本”来说是没有意义的。 - Mooing Duck
显示剩余5条评论
5个回答

16

窄字符串文字的编码是由实现定义的,因此你需要阅读文档(如果你能找到的话)。一个快速的实验显示,VC++(至少是VC8)和g ++(4.4.2,无论如何)实际上只是从源文件中复制字节;字符串字面量将使用编辑器保存它的任何编码。 这显然违反了标准,但似乎是常见的做法。

C++11有UTF-8字符串文字,允许您编写u8"text",并确保"text"被编码为UTF-8。但我并不真正希望它能够可靠地工作:问题在于,为了做到这一点,编译器必须知道源文件的编码方式。很可能,编译器编写者将继续忽略这个问题,只是复制源文件的字节,并通过记录源文件必须使用UTF-8才能使这些功能起作用来实现符合性。


6
一个工作正常的程序,如果将源文件的编码方案从UTF-8更改为UTF-16,就会变得有bug,这个想法加强了我对C++是纯混乱的印象!请有人告诉我这不是真的。:( - Jeffrey L Whitledge
3
“@Whitledge提到,任何读取文本的程序如果不知道输入的编码方式都会遇到问题,这并不让我感到意外;我认为这是不可避免的。虽然C++标准明确规定了给定序列的输入字符应该发生什么情况(尽管两个最广泛使用的编译器在这方面忽略了标准),但它对编译器如何解释输入的编码方式没有太多影响。(例如,大多数平台不支持UTF-16编码)。” - James Kanze
2
@James Kanze - 显然不知道编码会导致问题。这不是我所说的。听起来像是一个程序可以使用UTF-8或UTF-16编译,但编译后的程序行为取决于编码方式。如果大多数平台都不支持UTF-16,那么这根本不是问题。听起来C++源文件实际上并不是文本文件,而是具有某些类似文本的二进制文件。如果是这样的话,那么“编码”肯定会有所不同,因为它实际上不是文本编码。 - Jeffrey L Whitledge
1
我不确定是否违反了标准。显然,将字符集定义为UTF8的编译器是合规的。将其定义为UTF8或Latin1取决于/charset:开关的编译器也是合规的。将其定义为UTF8或Latin1取决于输入字符集的编译器也是合规的 - 标准在这方面没有太多强制要求,只要有文档说明即可。 - MSalters
2
@Bo Persson - 我之前的期望是源文件的编码和目标平台的编码是不同的概念,字符串字面量将变成字符串数据,无论源编码是什么(只要两者之间有适当的映射关系),都会在指定或暗示的目标编码中。这意味着源代码文件可以在不改变生成的编译二进制文件的情况下从一种编码转换为另一种编码。 - Jeffrey L Whitledge
显示剩余14条评论

4
如果您想将文本放入字符串中,请确保源代码文件采用UTF-8编码。
如果不行,可以尝试使用\u1234,其中1234是代码点值。
您还可以尝试使用 UTF8-CPP
请参考这个答案:在C++源代码中使用Unicode

1

针对VisualStudio 2010 SP1有一个热补丁可以帮助解决问题:http://support.microsoft.com/kb/980263

该热补丁添加了一个编译指示符,用于覆盖Visual Studio对char类型的字符编码控制:

#pragma execution_character_set("utf-8")

没有使用#pragma,char*类型的字面值通常被解释为默认的代码页(通常是1252)。
这些都应该最终被C++0x指定的新字符串字面值前缀修饰符所取代(分别是u8、u和U表示utf-8、utf-16和utf-32),理想情况下将在2010年后的下一个主要版本的Visual Studio中得到支持。

1

可以将文件保存为UTF-8编码,但不要加入BOM签名。

//Save As UTF8 without BOM signature
#include<stdio.h>
#include<windows.h>
int main(){
    SetConsoleOutputCP(65001);
    char *c1 = "aäáéöő";
    char *c2 = new char[strlen("aäáéöő")];
    strcpy(c2,c1);
    printf("%s\n",c1);
    printf("%s\n",c2);
}

结果:

 D:\Debug>program
aäáéöő
aäáéöő

重定向程序的结果是一个真正的UTF8编码文件。 UTF8 file 这是与编译器无关的答案(在Windows上编译)。 (一个类似的问题。)

2
未定义行为代码,因为您在c2中为6个字符分配了足够的内存,而您将7个字符从c1复制到c2。 - neo5003

1
请参阅此 MSDN 文章,其中讨论了如何在不同字符串类型之间进行转换(这应该会给您提供使用它们的示例)。所涵盖的字符串类型包括 char*、wchar_t*、_bstr_t、CComBSTR、CString、basic_string 和 System.String:
请点击如何:在各种字符串类型之间进行转换

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接