【问题标题】:Remove letter accents from a given text从给定文本中删除字母重音符号
【发布时间】:2012-10-25 15:49:47
【问题描述】:

也许我遗漏了一些明显的东西,但是有没有一种“无痛”的方法可以将给定文本中的重音字母替换为非重音字母?我只能使用标准的 ANSI C 库/头文件,所以我束手无策。到目前为止我尝试过的:

unsigned char currentChar;

(...)

if (currentChar == 'à') { 
    currentChar = 'a'; 
}
else if (currentChar == 'è' || currentChar == 'é') {
    currentChar = 'e'; 
}
else if (...)

但是,这不起作用。检测带有扩展 ASCII 值的重音元音也不是一种选择,因为我注意到它会根据系统区域设置而变化。

有什么提示/建议吗?

(更新)

感谢您的回答,但我并不是真的要求解决这个问题的最佳方法 - 我稍后会考虑。我只是在寻求一种检测重读元音的方法,因为上面的代码只是忽略了它们。

(更新 #2)

好的。让我澄清一下:

#include <stdio.h>

int main(void) {
    int i;
    char vowels[6] = {'à','è','é','ì','ò','ù'};
    for (i = 0; i < 6; i++) {
        switch (vowels[i]) {
            case 'à': vowels[i] = 'a'; break;
            case 'è': vowels[i] = 'e'; break;
            case 'é': vowels[i] = 'e'; break;
            case 'ì': vowels[i] = 'i'; break;
            case 'ò': vowels[i] = 'o'; break;
            case 'ù': vowels[i] = 'u'; break;
        }
     }
     printf("\n");
     for (i = 0; i < 6; i++) {
         printf("%c",vowels[i]);
     }
     printf("\n");
     return 0;
}

此代码仍然打印“àèéìòù”作为其输出。这是我的问题。我很欣赏答案,但是告诉我实现转换映射或开关/案例结构是没有意义的。我会考虑稍后

【问题讨论】:

  • 虽然可能无法解决您的问题,但我至少会使用 switch 而不是很多 if...else if 语句。
  • 什么是 ANSI C? AFAIK,ANSI 与 ISO 标准委员会就 C 的修订保持同步,目前的修订是 C11。你的意思是那个还是 C89?
  • 南希,你是怎么编译的?当我编译你的代码时,我得到很多`警告:多字符字符常量`-即。你的重音字符不是单个字符
  • @WilliamMorris:很好的观察,源代码编码可能是 UTF-8 但编译器不支持它并将字符视为多字节“字符”常量(不比较相等到字符)。

标签: c character-encoding ascii non-ascii-characters


【解决方案1】:

重音字符可能是 UTF-8 字符集或其他编码的一部分。你的程序使用char 类型,通常使用ASCII character set

在 ASCII 字符集中,每个字符由一个字节表示。此字符集不包含重音字符。

其他编码确实包含该字符,但它可能不是由单个字节表示,因此无法由您的代码处理。解决这个问题的方法通常是使用宽字符。

您需要的是wide characters

This question 可能有更笼统的解释。

This question 可能会为您的情况提供解决方案。

这段代码似乎做你想做的事:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main(int argc, char **argv){
    setlocale(LC_CTYPE, "");
    FILE *f = fopen(argv[1], "r");
    if (!f)
        return 1;

    for (wchar_t c; (c = fgetwc(f)) != WEOF;){
        switch (c) {
            case L'à': c=L'a'; break;
            case L'è': c=L'e';break;
            case L'é': c=L'e';break;
            case L'ì': c=L'i';break;
            case L'ò': c=L'o';break;
            case L'ù': c=L'u';break;
            default:    break;
        }
        wprintf(L"%lc", c);
    }

    fclose(f);
    return 0;
}

【讨论】:

  • @NancyB.,我发布了一段代码,似乎可以满足您的需求。
  • 刚刚做了一个快速更正,使其显示为wprintf(L"%c", c);。我已经测试过了,它对我有用。
  • 用那个方法溢出
【解决方案2】:

可能有更简单的方法,一些我没有听说过的现有功能,但就结构而言,这是我的处理方式:

建立一个由重音字符和结果字符组成的字符转换表。然后构建一个简单的循环来扫描表中的每个字符,如果找到,进行更改。

【讨论】:

  • 好的,但我遇到的问题是 - 重读元音根本无法识别。我知道 isalpha() 不处理它们,所以我已经实现了一些明确的检查,但它们似乎无法自己检测到元音。
  • 我建议的结构不需要isalpha() 或任何其他 CRT 代码。请再次阅读我的建议,如果有不明白的部分,请告诉我。
  • @NancyB.: 是的,来自ctype.his*() 不处理它们.. 你可以看看`wchar.h' 例程。
【解决方案3】:

如果你写

if ( currentChar == (unsigned char)('è'))...

考虑到您只使用标准 c 库的限制,您的方法应该有效,我不知道您是如何实现的。

【讨论】:

  • 这可能有效,但只是因为重音字符由两个字节组成,并且强制转换告诉编译器使用这些字节之一)。所以在我的系统上,'à' 由 0xC3 和 0xA0 表示,'è' 是 0xC3、0xA8 等。演员告诉if 只查看值 0xA8。此外,该解决方案可能会在具有相反字节顺序的机器上失败。
【解决方案4】:

让我们试试这个:

char p_RemoveAccent(char C)
{
    #define ACCENT_CHARS    "ÁÀÃÂÇáàãâçÉÊéêÍíÑÓÔÕñóôõÚÜúü"
    #define UNACCENT_CHARS  "AAAACaaaacEEeeIiNOOOnoooUUuu"

    const char *p_Char = memchr(ACCENT_CHARS, C, sizeof(ACCENT_CHARS));

    return (p_Char ? UNACCENT_CHARS[(p_Char - ACCENT_CHARS)] : C);
}

【讨论】:

  • 很好,但 OP 明确指出“.. 我并不是真的要求解决这个问题的最佳方法 - 我稍后会考虑。我只是要求一种方法来 检测重读元音.." -- OPs 源编码隐藏了它们。
  • 不起作用,因为重音字符长于 1 个字节,所以UNACCENT_CHARS[(p_Char - ACCENT_CHARS)] 会打错非重音字符
猜你喜欢
  • 2016-09-01
  • 2012-01-21
  • 2018-11-10
  • 2015-08-30
  • 1970-01-01
  • 2021-09-02
  • 2019-03-31
  • 2010-09-19
相关资源
最近更新 更多