我试图通过更改元音的音调来制作一个简单的希腊至现代希腊转换器。例如,用户在希腊语中键入一个字符的文本,该文本会呈现字符:ῶ(Unicode:u 1ff6),因此程序将其转换为:ώ(Unicode:u 1f7d)。希腊语不是由C所吸引的,所以我不知道如何使其起作用。有任何想法吗?
假设您使用理智的操作系统(意思是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,并且取决于您的开发环境时,它们才在Unicode中。(幸运的是,在Windows之外,UTF-8几乎是一个标准的 - 这是一件好事 - 因此像上面的代码一样可行。)
在Posixy系统(例如Linux,Android,Mac OS,BSD)上,您可以使用iconv()
功能从任何输入字符设置转换为Unicode,在此处进行转换,最后转换回任何输出字符集。不幸的是,这个问题不是标记为posix,所以这是这个特定问题之外的。
上面的示例使用简单的开关/案例语句。如果有很多替换对,则可以使用例如。
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
元素的函数),然后使用二进制搜索快速确定是否要更换一个宽字符(如果是这样,则为哪个宽字符)。因为这是a o(log 2 n) n 是对的 n 对并不是问题。(当然,即使是从用户输入或命令行选项中,您也可以在运行时构建替换数组。)
对于Unicode字符,我们可以使用uint32_t map_to[0x110000];
直接将每个代码映射到另一个Unicode代码点,但是由于我们不知道宽字符是否是Unicode,所以我们不能这样做。直到编译时间后,我们才知道宽字符的代码范围。当然,我们可以进行多阶段汇编,其中测试程序生成上面显示的replace[]
数组,并以十进制输出其代码;然后执行某种自动组或聚类,例如位地图或哈希表,以"甚至更快"。
但是,实际上,通常事实证明,I/O(读取和编写数据)比转换本身要花费的时间更多。即使转换是瓶颈,对于大多数人来说,转化率也足够。(例如,当使用GNU实用程序编译C或C 代码时,预处理器首先将源代码转换为UTF-8。)
好吧,这里有一些快速建议。我不会使用c,因为尚未受到unicode的支持。
更好的语言选择是Python,Java,...,任何具有良好Unicode支持的东西。
我会写一个从标准输入读取并写入标准输出的实用程序。这使得从命令行和脚本中易于使用。
我可能会缺少某些东西,但这将是这样(在伪代码中):
while ((inCharacter = getCharacterFromStandardInput) != EOF
{
switch (inCharacter)
{
case 'ῶ': outCharacter = ώ; break
...
}
writeCharacterToStandardOutput(outCharacter)
}
您还需要选择&amp;处理格式:UTF-8/16/32。
就是这样。祝你好运!