如何在C语言中使用'æ'、'ø'和'å'进行操作

5

我用C语言编写了一个程序,既可以替换字符串中的所有元音字母,也可以将其删除。此外,我希望它能适用于这些字符:'æ'、'ø'和'å'。

我尝试使用strstr()函数,但我没能在不替换包含'æ'、'ø'或'å'字符的行上实现它。

我还阅读了一些关于wchar的文章,但看起来只会让一切变得更加复杂。

该程序运行时作用于以下字符数组:

char vowels[6] = {'a', 'e', 'i', 'o', 'u', 'y'};

我用了这个数组:

char vowels[9] = {'a', 'e', 'i', 'o', 'u', 'y', 'æ', 'ø', 'å'};

但是它会产生以下警告:

警告:多字符字符常量[-Wmultichar]

警告:隐式常量转换中的溢出[-Woverflow]

如果我想用'a'替换每个元音字母,它会将'å'替换为"�a"。

我还尝试过使用'æ'、'ø'和'å'的UTF-8十六进制值

char extended[3] = {"\xc3\xa6", "\xc3\xb8", "\xc3\xa5"};

但是它给出了这个错误:

字符数组初始化程序中有过多的元素

有没有不太复杂的方法让它正常工作?


请说明您正在使用的标准版本,以及是否尝试使用C11,并且您的编译器使用哪种源/目标字符编码。请注意,例如UTF-8(gcc的默认值)具有可变长度的字符,因此char将不足以在单个char变量中保存除ASCII以外的任何内容。 - too honest for this site
我该如何查找我正在使用的版本? 我还没有尝试过C11,并且我不知道该怎么做。我使用以下行进行编译:
gcc -Wall -g -o filename filename.c
- Martin Johansen
1
尝试使用以下代码:char extended[3][3] = {"\xc3\xa6", "\xc3\xb8", "\xc3\xa5"}; - MikeCAT
1
这些字符无法适应于 char。您必须使用 wchar_tchar16_tchar32_t。更多信息请参见 Joel on Software 的《每个软件开发人员绝对必须了解的最小限度:Unicode 和字符集(别再找借口了!)》 - phuclv
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Basile Starynkevitch
显示剩余5条评论
2个回答

4
有两种方法可以使该字符可用。第一种是使用代码页,这将允许您使用扩展ASCII字符(值为128-255),但代码页是系统和区域设置相关的,所以通常不是一个好主意。
更好的选择是使用Unicode。在Unicode中,典型的情况是使用宽字符字面量,就像在这个帖子中一样
wchar_t str[] = L"αγρω";

你的代码的关键问题是你试图比较ASCII和UTF8,这可能会有问题。解决方法很简单:将所有文字和字符串转换为宽字符UTF8等效物。除非你有转换函数来帮助,否则你需要使用通用编码而不是混合编码。

1
我通过在代码中进行以下替换来使其工作:char -> wchar_t,strcpy() -> wcscpy(),strlen() -> wcslen(),printf("%s", str) -> printf("%ls", str)。我只缺少getline()的替换。 - Martin Johansen
1
没有所谓的“扩展ASCII字符”。 “代码页”是特定于某个操作系统系列的。 将ASCII与UTF8进行比较绝对没有任何问题,因为UTF8专门设计为与ASCII兼容。 - n. m.
@n.m. 我不同意。https://zh.wikipedia.org/wiki/%E6%89%A9%E5%B1%95ASCII 扩展ASCII(或高ASCII)是包括标准七位ASCII字符以及其他字符的八位或更大字符编码。有时对该术语的使用受到批评,因为它可能被错误地解释为ASCII标准已经更新以包括超过128个字符,或者该术语明确地标识了单一编码,这两种说法都是不正确的。 - Cloud
1
我相信在Linux上使用UTF-8的char比使用wchar_t更好。 - Basile Starynkevitch
Basile,如果有像“æ”、“ø”或“å”这样的字母,你该如何使其正常工作? - Martin Johansen
显示剩余11条评论

4

学习有关UTF-8的知识(包括它与Unicode的关系),并使用一些UTF-8库:来自GTK的libunistringutfcppGlibICU等......

你需要了解你正在使用的字符编码

我强烈推荐在所有情况下使用UTF-8(这是大多数Linux系统和几乎所有互联网和Web服务器的默认设置;请阅读locale(7)utf8(7))。请阅读utf8everywhere....

我不建议使用wchar_t,其宽度、范围和符号是实现特定的(你不能确定Unicode是否适合wchar_t;据传在Windows上不适用)。此外,将UTF-8输入转换为Unicode/UCS4可能需要很长时间,超过了处理UTF-8的能力...

请注意,在UTF-8中,一个字符可以用多个字节编码。例如,法语重音符号ê(小写e circonflexe)被编码为两个字节0xc3, 0xaa,而俄语小写字母yeryы被编码为两个字节0xd1, 0x8b,它们都被认为是元音,但都不适合一个char(在你我的机器上,这是一个8位字节)。 元音的概念很复杂(例如,在俄语、阿拉伯语、日语、希伯来语、切罗基语、印地语等中,什么是元音?),因此您的问题可能没有简单的解决方案(因为UTF-8有组合字符)。

您确定æœ是字母或元音吗?(顺便说一下,在Unicode中,åœæ被归类为字母和小写字母)。我在法国小学里学到它们是连字号(而且法语词典也没有将它们列为字母,因此œuf在词典中代替了oeuf,意思是)。但我不是这方面的专家。请参见strcoll(3)

在Linux中,由于UTF-8是默认编码(并且在最近的发行版上越来越难以获得其他编码),我不建议使用,而是使用UTF-8 (因此使用处理多字节编码的UTF-8函数),例如(使用Glib UTF8&Unicode函数):
 unsigned count_norvegian_lowercase_vowels(const char*s) {
   assert (s != NULL);
  // s should be a not-too-big string 
  // (its `strlen` should be less than UINT_MAX)
  // s is assumed to be UTF-8 encoded, and should be valid UTF-8:
    if (!g_utf8_validate(s, -1, NULL)) {
      fprintf(stderr, "invalid UTF-8 string %s\n", s);
      exit(EXIT_FAILURE);
    };
    unsigned count = 0;
    char* next= NULL; 
    char* pc= NULL;
    for (pc = s; *pc != '\0' && ((next=g_utf8_next_char(pc)), *pc); pc=next) {
      g_unichar u = g_utf8_get_char(pc);
      // comments from OP make me believe these are the only Norvegian vowels.
      if (u=='a' || u=='e' || u=='i' || u=='o' || u=='u' || u=='y'
          || u==(g_unichar)0xa6 //æ U+00E6 LATIN SMALL LETTER AE
          || u==(g_unichar)0xf8  //ø U+00F8 LATIN SMALL LETTER O WITH STROKE
          || u==(g_unichar)0xe5 //å U+00E5 LATIN SMALL LETTER A WITH RING ABOVE
       /* notice that for me  ы & ê are also vowels but œ is a ligature ... */
      )
        count++;
    };
    return count;
  }

我不确定我的函数名称是否正确;但您在评论中告诉我,挪威语(我不知道)的元音字符并不比我的函数计数更多。
我故意没有在文字字符串或宽字符文字中放置UTF-8(仅在注释中)。还有其他过时的字符编码(请阅读EBCDICKOI8),您可能希望交叉编译代码。

标题上写着。 - Martin Johansen
标题或问题中没有提到挪威语。语言中的元音比你想象的要多得多。ы和ê显然是元音,但你错误地认为它们不是。至于希伯来语、阿拉伯语、日语或切罗基语中的元音,我不敢说,但我知道这是一个棘手的问题。 - Basile Starynkevitch
如何在C语言中使用æ、ø和å进行操作。也许标题不太好。 - Martin Johansen
1
@BasileStarynkevitch。这其实很简单。这些字母中没有一个是元音字母。元音字母是发音。字母与复杂的发音相关联,通常不存在一对一的映射关系。 - n. m.
@BasileStarynkevitch 是的,在小学里他们往往会教授这种方法。但并非普遍如此。这是一种简化的方法,对某些语言相对有效,而对其他语言则不太适用。 - n. m.
显示剩余3条评论

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