【问题标题】:Greek Character Conversion希腊字符转换
【发布时间】:2017-12-26 14:50:18
【问题描述】:

我正在尝试通过改变元音的音调来用 c 语言制作一个简单的古希腊语到现代希腊语的转换器。例如,用户键入包含字符的希腊文文本:ῶ(unicode:U+1FF6),因此程序将其转换为:ώ(unicode:U+1F7D)。 c 不支持希腊语,所以我不知道如何使它工作。有任何想法吗?

【问题讨论】:

  • StackOverflow 不是编程服务。显示代码以及卡在哪里。
  • 我认为 StackOverflow 不仅仅是一个在线调试器。我没有要求为我编写代码,我只是要求提示以帮助我继续。我直接写了我的问题,而不是让你在我的代码的不正确部分搜索错误。
  • 发布更多你的想法/问题 - 否则这太宽泛了。如果只能替换一个元音,if() 可以正常工作。如果有数十或数百个案例考虑,则应使用其他方法。 C 支持 Unicode。

标签: c unicode character


【解决方案1】:

假设您使用正常的操作系统(意思是,不是 Windows),使用 C99/C11 语言环境和宽字符支持很容易实现。考虑 filter.c

#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
#include <stdio.h>

wint_t convert(const wint_t  wc)
{
    switch (wc) {
    case L'ῶ': return L'ώ';
    default:   return wc;
    }
}

int main(void)
{
    wint_t  wc;

    if (!setlocale(LC_ALL, "")) {
        fprintf(stderr, "Current locale is unsupported.\n");
        return EXIT_FAILURE;
    }
    if (fwide(stdin, 1) <= 0) {
        fprintf(stderr, "Standard input does not support wide characters.\n");
        return EXIT_FAILURE;
    }
    if (fwide(stdout, 1) <= 0) {
        fprintf(stderr, "Standard output does not support wide characters.\n");
        return EXIT_FAILURE;
    }

    while ((wc = fgetwc(stdin)) != WEOF)
        fputwc(convert(wc), stdout);

    return EXIT_SUCCESS;
}

上述程序读取标准输入,将每个转换为,并输出结果。

注意宽字符串和字符都有L前缀; L'ῶ' 是一个宽字符常量。如果执行字符集(编译代码的字符集)是 Unicode,则这些仅在 Unicode 中,这取决于您的开发环境。 (幸运的是,在 Windows 之外,UTF-8 现在几乎是一种标准——and that is a good thing——所以像上面这样的代码就可以了。)

在 POSIXy 系统(如 Linux、Android、Mac OS、BSD)上,您可以使用 iconv() 工具将任何输入字符集转换为 Unicode,在此处进行转换,最后再转换回任何输出字符集.不幸的是,该问题未标记为,因此不在此特定问题范围内。

上面的例子使用了一个简单的 switch/case 语句。如果有很多替换对,可以使用例如

typedef struct {
    wint_t  from;
    wint_t  to;
} widepair;

static widepair  replace[] = {
    { L'ῶ', L'ώ' },
    /* Others? */
};
#define  NUM_REPLACE  (sizeof replace / sizeof replace[0])

在运行时,对replace[] 进行排序(使用qsort() 和一个比较from 元素的函数),并使用二分搜索快速确定是否要替换宽字符(如果是,替换为哪个宽字符)。因为这是一个 O(log2N) 操作,其中 N 是对的数量,它利用缓存没问题,甚至是数千个替换这种方式对不是问题。 (当然,您也可以在运行时构建替换数组,甚至通过用户输入或命令行选项。)

对于 Unicode 字符,我们可以使用uint32_t map_to[0x110000]; 将每个代码点直接映射到另一个 Unicode 代码点,但是因为我们不知道宽字符是否是 Unicode,所以我们不能这样做;直到编译时我们才知道宽字符的代码范围。当然,我们也可以进行多阶段编译,测试程序生成如上所示的replace[]数组,并以十进制输出它们的代码;然后进行某种自动分组或聚类,例如位图或哈希表,以“更快”完成。

但是,在实践中,I/O(读取和写入数据)通常比转换本身花费更多的实际时间。即使转化是瓶颈,转化率对大多数人来说也足够了。 (例如,使用 GNU 实用程序编译 C 或 C++ 代码时,预处理器首先在内部将源代码转换为 UTF-8。)

【讨论】:

    【解决方案2】:

    好的,这里有一些快速建议。我不会使用 C because Unicode is not wel supported (yet)

    更好的语言选择是 Python、Java 等,任何具有良好 Unicode 支持的语言。

    我会编写一个从标准输入读取并写入标准输出的实用程序。这使得在命令行和脚本中使用起来很容易。

    我可能遗漏了一些东西,但它会是这样的(在伪代码中):

    while ((inCharacter = getCharacterFromStandardInput) != EOF
    {
        switch (inCharacter)
        {
            case 'ῶ': outCharacter = ώ; break
            ...
        }
    
        writeCharacterToStandardOutput(outCharacter)
    }
    

    您还需要选择和处理格式:UTF-8/16/32。

    就是这样。祝你好运!

    【讨论】:

    • Unicode 代码点在 UTF-8 和 UTF-16 中具有可变长度。它们不能表示为单字节 char,除了 UTF-8 的一小部分。此外,C 是一种低级语言,可以轻松处理 Unicode,即使是比 Unicode 更早的 C 版本。但如果没有任何其他信息,您选择另一种语言的建议可能最合适。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 2013-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多