C++ 如何编写UTF-8安全的代码?

C++ 如何编写UTF-8安全的代码?,c++,unicode,utf-8,globalization,C++,Unicode,Utf 8,Globalization,我们有一套为ASCII字符集开发的应用程序。现在,我们正试图在冰岛安装它,但遇到了一些问题,冰岛人的角色被搞砸了 我们正在研究我们的问题,但我想知道:在那里有一个好的“指南”来编写C++代码,它是为8位字符设计的,当UTF-8数据被赋予时它会正常工作? 我不能期望每个人都阅读整个Unicode标准,但是如果有更容易理解的内容,我想与团队分享,这样我们就不会再次遇到这些问题 此时,重新编写所有应用程序以使用wchar\u t或其他字符串表示法是不可行的。我还将注意到,这些应用程序通过网络与使用8位

我们有一套为ASCII字符集开发的应用程序。现在,我们正试图在冰岛安装它,但遇到了一些问题,冰岛人的角色被搞砸了

我们正在研究我们的问题,但我想知道:在那里有一个好的“指南”来编写C++代码,它是为8位字符设计的,当UTF-8数据被赋予时它会正常工作? 我不能期望每个人都阅读整个Unicode标准,但是如果有更容易理解的内容,我想与团队分享,这样我们就不会再次遇到这些问题


此时,重新编写所有应用程序以使用wchar\u t或其他字符串表示法是不可行的。我还将注意到,这些应用程序通过网络与使用8位字符的服务器和设备进行通信,因此即使我们在内部使用Unicode,在边界处的翻译仍然会有问题。在大多数情况下,这些应用程序只是传递数据;除了从一个地方复制到另一个地方,他们不会以任何方式“处理”文本

使用的操作系统是Windows和Linux。我们使用std::string和普通的旧C字符串。(不要让我为任何设计决策辩护。我只是想帮你解决这个烂摊子。)


以下是建议内容的列表:


您可能希望使用宽字符(wchar\u t代替char,std::wstring代替std::string)。这不会自动解决100%的问题,但这是很好的第一步


还可以使用支持Unicode的字符串函数(请参阅文档)。如果有东西操纵宽字符或字符串,它通常知道它们是宽的。

这看起来像是一个全面的快速指南:

请注意,完整的unicode不适合16位字符;所以要么使用32位字符,要么使用可变宽度编码(UTF-8是最流行的)。

冰岛语使用ISO拉丁语1,所以8位就足够了。我们需要更多的细节来了解发生了什么。

UTF-8的设计正是为了解决您的问题。我需要注意的一点是,ASCII实际上是一种7位编码,因此,如果您的基础设施的任何部分将第8位用于其他目的,这可能会很棘手。

在大多数情况下,只需保持8位干净即可。但是,您必须知道,任何非ASCII字符都会跨多个字节拆分,因此,如果要显示的文本是换行或截断文本,则必须考虑到这一点

UTF-8的优点是,您始终可以知道自己在多字节字符中的位置:如果设置了位7,位6重置(字节为0x80-0xBF),则这是一个尾随字节,而如果设置了位7和6,位5重置(0xC0-0xDF),则这是一个有一个尾随字节的前导字节;如果设置了7、6和5,并重置了4(0xE0-0xEF),则它是一个带两个尾随字节的前导字节,依此类推。在最高有效位设置的连续位数是组成字符的字节总数。即:

110x xxxx=两字节字符
1110 xxxx=三字节字符
1111 0xxx=四字节字符

冰岛字母表全部包含在ISO 8859-1和Windows-1252中。如果这是一个控制台模式的应用程序,请注意控制台使用IBM代码页,因此(取决于系统语言环境)它可能会显示在437、850或437中。Windows不支持UTF-8的本机显示;您必须转换为UTF-16并使用Unicode API


如果是控制台模式应用程序,则调用SetConsoleCP和SetConsoleOutputCP(指定代码页1252)将有助于解决您的问题。不幸的是,选择的控制台字体必须是支持代码页的字体,我看不到设置字体的方法。标准位图字体仅支持系统默认OEM代码页。

您可能需要签出。它们可能具有使使用UTF-8字符串更容易的功能。

冰岛语,如法语、德语和西欧的大多数其他语言,可以使用8位字符集(Windows上的CP1252,ISO 8859-1又名Latin1,x上的ISO 8859-1)来支持。这是Unicode发明之前的标准方法,现在仍然很普遍。正如你所说,你有一个限制,你不能重写你的应用程序使用wchar,你不需要

UTF-8造成问题,你不应该感到惊讶;UTF-8将非ASCII字符(例如重音拉丁字符、thorn、eth等)编码为每个字符两个字节

唯一可以给出的一般建议非常简单(理论上): (1) 决定系统中要支持的字符集(Unicode、Latin1、CP1252等) (2) 如果向您提供的数据以其他方式编码(如UTF-8),则在系统边界处将其转换为您的标准(如CP1252)
(3) 如果您需要提供以其他方式编码的数据,

重新编写所有应用程序以使用不同的字符表示是不可行的。您能否向我们确认您的应用程序的操作系统?你在为Windows编程吗?您是否大量使用std::string或更低级的C标题?如果您喜欢答案,请向上投票-没有理由吝啬。只有30分钟,而且您已经要求增加代表次数了?:)不苛求——毕竟我说了“请”;>)现在我要说谢谢。是的,这就是为什么我们对UTF-8导致的问题感到惊讶。我们没有对第八位做任何特殊的处理,但似乎我们在一些地方做了一些事情,导致文本以某种方式被误解或修改。请注意,ASCII是每个字符1字节。UTF-8是每个字符的多字节(当不是ASCII时,所以Iclandic计数)。因此,任何假定每个字符有1个字节的方法都不起作用。e、 我没有要求任何人帮我找出问题所在。我正在寻找处理UTF-8的一般指南和“最佳实践”。UTF-8使用3个字节来表示汉字