10

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

我们正在解决我们的问题,但我想知道:是否有一个很好的“指南”来编写专为 8 位字符设计的 C++ 代码,并且在提供 UTF-8 数据时可以正常工作?

我不能指望每个人都阅读整个 Unicode 标准,但如果有更容易理解的内容,我想与团队分享,这样我们就不会再遇到这些问题了。

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

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


以下是建议的清单:

4

8 回答 8

10

在大多数情况下,只需 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 或861。Windows 没有对 UTF-8 的原生显示支持;您必须转换为 UTF-16 并使用 Unicode API。

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

于 2008-09-25T17:54:24.223 回答
3

这看起来像一个全面的快速指南:
http ://www.cl.cam.ac.uk/~mgk25/unicode.html

于 2008-09-25T16:45:07.837 回答
1

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

于 2008-09-25T16:59:05.133 回答
1

UTF-8 的设计完全考虑了您的问题。我要注意的一件事是 ASCII 实际上是 7 位编码,所以如果您的基础设施的任何部分将第 8 位用于其他目的,那可能会很棘手。

于 2008-09-25T17:13:41.463 回答
1

您可能想查看icu。它们可能具有使处理 UTF-8 字符串更容易的功能。

于 2008-09-25T18:11:11.593 回答
0

冰岛语使用 ISO Latin 1,所以 8 位应该足够了。我们需要更多细节来弄清楚发生了什么。

于 2008-09-25T17:05:49.003 回答
0

冰岛语与法语、德语和大多数其他西欧语言一样,可以使用 8 位字符集(Windows 上的 CP1252,*x 上的 ISO 8859-1 aka Latin1)来支持。这是 Unicode 发明之前的标准方法,并且仍然很常见。正如你所说,你有一个约束,你不能重写你的应用程序来使用 wchar,你也不需要。

您不应该对 UTF-8 引起问题感到惊讶。UTF-8 将非 ASCII 字符(例如带重音的拉丁字符、thorn、eth 等)编码为每个两个字节。

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

于 2009-06-29T13:20:02.893 回答
-1

您可能想要使用宽字符(wchar_t 代替 char 和 std::wstring 代替 std::string)。这不会自动解决 100% 的问题,但这是很好的第一步。

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

于 2008-09-25T16:39:12.657 回答