作为 C 字符串的非 ASCII 字符集

3

我正在开发一个具有多语言支持的软件。我必须使用单字节字符集,这意味着我不能使用UTF-8编码格式。我的编码格式如下:

  • ENG:ASCII
  • UKR:KOI8-U
  • ARA:ISO8859-6
  • SPA:ISO8859-1

我使用Notepad++作为我的编辑器。当我收到新语言的翻译时,我只需要简单地增加数组大小并将C文件的编码格式更改为新语言的编码格式即可。例如,我的数组针对不同的编码类型如下:

#define MAX_CHAR_PER_LINE 10
enum Langs {
    en,
    uk,
    es,
    ar
    MAX_LANG
};

// ASCII    
const char settingStr[][MAX_LANG][MAX_CHAR_PER_LINE] = {
    //...
    { "SETTINGS", "îáìáûôõ÷áîîñ", "AJUSTES", "ÇÙÏÇÏÇÊ" },
    //...
};

// KOI8-U
const char settingStr[][MAX_LANG][MAX_CHAR_PER_LINE] = {
    //...
    { "SETTINGS", "НАЛАШТУВАННЯ", "AJUSTES", "гыогогй" },
    //...
};    
// ISO8859-6
const char settingStr[][MAX_LANG][MAX_CHAR_PER_LINE] = {
    //...
    { "SETTINGS", "ففََّ", "AJUSTES", "اعدادات" },
    //...
};

当我使用十六进制查看器检查C文件时,我能够确信字符的二进制值符合指定的编码标准。

我的问题是我得到了编译警告:

enter image description here

还有运行时的逻辑错误。

用于在线GDB的示例代码如下:

#include <stdio.h>

const char settingStr[][4][10] = {
    //...
    { "SETTINGS", "ففََّ", "ÇÙÏÇÏÇÊ", "AJUSTES" },
    //...
};

int main() {
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 10; j++)
            printf("0x%02X,", settingStr[0][i][j]);
        printf("\n");
    }    
    return 0;
}

我怀疑 GCC 预处理器无法解析这些字符串。我应该添加某种编译器标志吗?我不想用十六进制值填充数组。


2
这是文本编辑器将字符> 127转换为这些符号,而不是编译器。曾经使用[code pages](https://en.wikipedia.org/wiki/Code_page)来完成此操作。显然,您一次只能激活一个代码页,因此一次只能使用一种语言(可能还有英语)。我还使用Notepad ++,它具有“编码”菜单选项,您应该将其设置为Ansi。但是,在Ansi中拥有这些数组,并使它们在文本编辑器中全部正确读取是不可能的。 - Weather Vane
2
你的即时问题的不良解决方案:不要写 "ñññ",而是写 "\xC3\xC3\xC3"(或其他)。 - pmg
终端很可能是UTF-8,因此请在控制台输出时使用UTF-8(对于其他用途可以使用其他编码)。但为什么不能使用UTF-8呢?这似乎是一个设计问题(没有将字符串视为黑盒),而且所有主要操作系统都已经采用了UTF-8(不包括Windows),或者正在朝着这个方向发展(新的Windows)。计算字符数或一次处理单个字符会带来麻烦。 - Giacomo Catenazzi
你可以考虑使用gettext - Mathieu
1个回答

3
编译器的错误信息有误导性:字符串"ÇÙÏÇÏÇÊ"很可能是以UTF-8编码的(由编辑器或传输过程中其他工具执行),使用了14个字节(加上空终止符)。 编译器指向错误(字符串中的第6个字符),但终端支持UTF-8,而"ÇÙÏÇÏÇÊ"的14个字节只显示为7个字符,导致^~~~~~~输出错位到下一行。 另一个字符串"ففََّ"也很可能被误编码,导致额外的错位。
问题在于你的编辑环境:翻译以UTF-8编码方式返回给你,这是目前事实上的标准,更确切地说,它可能已经被编码两次:原始的ISO8859-6 1字节编码用于阿拉伯语,并且由于错误而重新从ISO8859-1编码为UTF-8。
在同一文件中混合不同的编码并不容易。这对每个人来说都非常困惑:翻译人员、程序员、编译器和用户……
以下是避免这些问题的不同选择:
  • 您应认真考虑设计选择并使用UTF-8。源代码及其所有翻译将在所有语言中都可读取,这更安全、更易于审核。根据运行时环境,这可能会简化或复杂化显示。

  • 您可以为每种翻译单独存储字符串,并使用适当的编码进行编码,并在运行时检索它们。这对翻译人员更友好,但需要对软件进行重大更改。

  • 您可以使用八进制或十六进制转义序列将翻译后的字符串编码为ASCII,以避免重新编码问题。这将避免与远东国家使用的历史编码相关的任何编译器误解。您可以使用小型程序将字符串编码为C源代码。


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