- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试通过改变元音的声调,在 c 中制作一个简单的 - 古希腊语到现代希腊语 - 转换器。例如,用户键入包含字符的希腊文文本:ῶ(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 中,这取决于您的开发环境。 (幸运的是,在 Windows 之外,UTF-8 现在几乎是一个标准 -- and that is a good thing -- 所以像上面这样的代码就可以了。)
在 POSIXy 系统(如 Linux、Android、Mac OS、BSD)上,您可以使用 iconv()
从任何输入字符集转换为 Unicode 的设施,在那里进行转换,最后转换回任何输出字符集。不幸的是,这个问题没有被标记为 posix ,所以这超出了这个特定问题。
上面的例子使用了一个简单的 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。)
关于c - 希腊字符转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47980182/
我是一名优秀的程序员,十分优秀!