问题:将 getchar() 用于变音符号/变音符号(Ö、Ä、Ü、ß)

Problem: using getchar() for Umlauts/Umlaute (Ö, Ä, Ü, ß)

提问人:Dante 提问时间:6/28/2023 更新时间:6/29/2023 访问量:82

问:

我想运行一个简单的程序:

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

int main(void)
{
int c;

printf("Please enter a letter: ");

while ((c = getchar()) !='.')
    printf("The letter is: %c", c);

return 0;
}

但是当我在 printf-function 中编写字符串时,输出如下所示(以“a”作为输入示例):

Please enter a letter: a
The letter is: aBuchstabe:

甚至,当我使用变音符号时,例如“ü”,然后我会得到这个:

Please enter a letter: �
The letter is: �The letter is: �The letter is:

我想,我可以将 getchar() 用于 Umlaute/Umlauts?!似乎 printf() 无法处理它。但我不知道该怎么办。当我使用 putchar() 时,我会得到变音符号。还是不能在 Clang 中使用变音符号/变音符号?我知道,有一组符号是允许用于 C 源代码的。

我做错了什么?

c 变音符号 getchar

评论

0赞 Dirk Eddelbuettel 6/28/2023
你在什么平台上?甚至 Windows 现在也可以执行 utf-8。
0赞 12431234123412341234123 6/28/2023
de.wikipedia.org/wiki/UTF-8
0赞 n. m. could be an AI 6/29/2023
我建议忽略单个字符并对整个字符串进行操作,除非您正在编写需要单个字符的专用应用程序(例如文字游戏)。但是,这表明您甚至无法正确输入变音符号。如果是这种情况,您需要先修复您的设置(操作系统/终端/字体/其他)。Please enter a letter: �

答:

-2赞 KamilCuk 6/28/2023 #1

在处理基本英文字母以外的任何内容时,您必须改用宽字符。很有可能需要超过一个字节 - 它只是不“适合”字符。ü

此外,请检查 EOF。

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>
int main(void) {
    setlocale(LC_ALL, "");
    printf("Please enter a letter: ");
    wint_t c;
    while ((c = getwchar()) != WEOF && c !='.')
        printf("The letter is: %lc\n", c);
    return 0;
}

评论

0赞 JHBonarius 6/28/2023
不是为了什么,对吧?我的意思是是定义的实现,所以在某些平台上可以是 2 个字节。更长的多字节字符不适合。wchar
0赞 Ian Abbott 6/28/2023
@JHBonarius 是的,如果宽度为 16 位(由于历史原因,在 MS Windows 上很常见),并且面向宽的流使用 UTF-16 编码,则只能在单个代码单元中表示 Unicode 平面 0(基本多语言平面 (BMP))字符中的字符。平面 1 到 16 中的字符只能由高低代理项代码单元对表示。wchar_t
1赞 n. m. could be an AI 6/29/2023
“你必须移动到宽字符”不完全是。您可以移动到宽字符。您可以改用多字节字符。您甚至可以使用窄的单字节字符集,如 Latin-1。
0赞 John Bollinger 6/28/2023 #2

基本源字符集和执行字符集不包含任何带变音符号的字母。执行字符集中的任何此类字符都是扩展字符,它们可能是也可能不是多字节字符。如果执行字符集以 UTF-8 编码(非常常见),则所有带有变音符号的字符都将是多字节字符,但这不是唯一的选择。

getchar()读取一个大小的单位,并(成功时)返回它的无符号表示形式。以这种方式读取多字节字符需要多次调用,每个字节一次。您的示例程序没有考虑到这一点,但请考虑以下替代方法:char

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

int main(void) {
    printf("Please enter some letters: ");

    while (1) {
        int c = getchar();

        if (c < 0 || c == '\n') {
            break;
        }
        // Using printf here for parallelism with the original example:
        printf("%c", c);
    }
    putchar('\n');

    return 0;
}

我想你会发现它准确地回响了一行输入,变音符号等等。您会注意到,它使用的 I/O 函数与原始示例相同。

我想,我可以将 getchar() 用于 Umlaute/Umlauts?!

角色处理比新手往往理解的要复杂得多。如果你还没有这样做,你应该阅读 The Absolute Minimum Every Software Developer Absolutely, Positive Must Know About Unicode and Character Sets(没有借口!它有点老了,但它仍然很重要。

无论如何,是的,如果执行字符集完全支持变音符号,则可以使用 to 输入带有变音符号的字符,但不一定以每次调用一个(整个)字符的速率输入。可能需要多次调用才能获取此类字符的所有字节。getchar()getchar()

似乎 printf() 无法处理它。

printf()打印您呈现给它的数据。如果你要求它只打印多字节字符的第一个字节,那么这就是它要做的事情。如果你要求它打印一个多字节字符的所有字节,那么这就是它要做的事情。

当我使用 putchar() 时,我会得到变音符号。

代入 给你的东西更类似于我上面的例子,而不是问题中提出的例子。如果在多字节字符的字节之间插入一堆其他字符 (),则会有很大的不同。putchar(c)printf("The letter is: %c", c)The letter is:

还是不能在 Clang 中使用变音符号/变音符号?

Clang 或任何符合要求的 C 实现中没有任何内容可以阻止将输入字节直接回显到标准输出。这有什么影响取决于外部因素,尤其是终端配置,但不,Clang 没有任何变音符号的固有问题。

我知道,有一组符号是允许用于 C 源代码的。

嗯,有一组字符(基本的源字符集),所有 C 实现都需要在 C 源代码中接受。在实践中,几乎所有的 C 实现都接受更多,并且几乎每个 C 程序都依赖于此。在某些情况下,某些实现甚至会接受 C 源代码中带有变音符号的字符。

C 确实有宽流,它们以 类型的单位运行,以及一组用于在它们上操作的 I/O 函数。这些旨在简化涉及编码值太大而无法处理的字符的 I/O。它们确实在某种程度上做到了,但这对于处理多字节字符来说不是必需的,而且也不一定足够。wchar_tchar