在C语言中,如何将一个整数打印为128-255字符?

3

我仍在使用 C 语言进行实验,以了解其工作原理。

我在打印扩展 ASCII 表(128-255)中的字符时遇到了问题。如果我使用 printf("Â")(例如),它会打印出 Â(一切正常)。然而,如果我给变量赋值,例如 a = 194,然后打印该变量 printf("%c",a),它会打印出 � 而不是 Â。

顺便说一下,对于 32-127 的字符,它可以正常工作(例如,35 打印出 #)。

如何从整数(十进制或二进制)打印出 128-255 范围内的字符?

我使用的是 GCC 11.3 在 Ubuntu 20.04.1 LTS 上。


7
没有标准的“扩展ASCII表”。你的终端可能使用UTF-8编码,该编码对非ASCII字符使用多个字节。 - interjay
7
没有标准的“扩展ASCII表”。你的终端可能使用UTF-8编码,该编码对非ASCII字符使用多个字节。 - interjay
这不是重复的吗? - Peter Mortensen
打印在什么上下文中?在终端窗口中吗?哪个终端? - Peter Mortensen
打印是在什么情况下?在一个终端窗口中吗?哪个终端窗口? - Peter Mortensen
显示剩余2条评论
3个回答

4
很可能你的编译器和终端都使用UTF-8来编码非ASCII字符。
字符集和编码是一个广泛的主题,有许多不同且不兼容的约定和实现。在传统的单字节编码(如ISO8859-1和Windows-1252)中,"Â"确实被编码为194。它也是Unicode标准中的字符编号,该标准有超过100,000个不同的代码点,用于表示世界上几乎所有的语言和符号集。
有不同的方式来表示这些字符的字节序列,其中最常见的是UTF-8,在99%的网页中使用。ASCII字符在32-127范围内表示为单个字节,而具有更大代码点的字符则使用2到4个字节,一个前导字节在C2F4范围内,以及1到3个尾随字节在80BF范围内。Â被编码为C3 82,这意味着"Â"实际上是一个由两个字节组成的字符串,与"\xC3\x82"相同。
您可以使用以下代码进行验证:
#include <stdio.h>
#include <string.h>

int main(void) {
    const char *s = "Â";
    int len = strlen(s);
    printf("%s: len=%d, bytes=", s, len);
    for (int i = 0; i < len; i++) {
        printf("%02hhX%c", s[i], " \n"[i == len - 1]);
    }
    return 0;
}

输出应该是Â: len=2, bytes=C3 82
要将非ASCII字符转换为UTF-8序列以输出流,请使用来自<locale.h>和宽字符输出的区域设置函数。
    setlocale(LC_ALL, "en_US.UTF-8");
    printf("%lc\n", 194);

输出:

Â

如果终端中的区域设置正确配置,则可以使用 setlocale(LC_ALL, ""); 选择默认区域设置。

3
正如@interjay所指出的,以及维基百科上所写的:
“扩展ASCII”没有正式的定义,有时甚至会受到批评,因为它可能被错误地解释为美国国家标准学会(ANSI)已经更新了其ANSI X3.4-1986标准以包括更多字符,或者该术语标识了一个单一明确的编码,但实际情况并非如此。 维基百科:扩展ASCII
此外,当你将 printf("Â"); 作为字符串使用时,你可以打印出 Â。因为你的编译器和终端都会将其解释为 Unicode 字符。你可以通过编译以下代码来验证:
#include <stdio.h>

int main() {
    char c = 'Â'; // set single character variable to be Â

    printf("%c", c); // print the variable

    return 0;
}

在我的系统上,我的编译器给了我这个警告:
extended_ascii.c: In function ‘main’:
extended_ascii.c:4:18: warning: multi-character character constant [-Wmultichar]
    4 |         char c = 'Â'; // set single character variable to be Â
      |                  ^~~
extended_ascii.c:4:18: warning: overflow in conversion frominttochar’ changes value from50050to-126’ [-Woverflow]

这表明Â确实是一个Unicode多字节字符。
你也可以尝试运行这段代码来检查Â会被扩展成什么:
#include <stdio.h>

int main() {
    char c[] = "Â"; // set a string variable to be Â

    for(int i = 0; c[i] != '\0'; i++) { // loop through each character
        printf("%d ", c[i]); // print integer value of each character
    }

    return 0;
}

而且,它的输出是:
-61 -126

所以,你的Â是一个多字节字符,扩展到那些值。如果你尝试分别打印每个字符,你会再次看到��。因此,当它们一起打印时,终端会将其解释为一个Unicode字符并打印出期望的结果。
顺便说一句,我在互联网上也找到了这个:
在Windows-1252字符集中,ASCII码194由字符Â表示...
请注意使用了“Windows-1252字符集”这个词。虽然我对这个字符集一无所知,但导致194无法打印为Â的最有可能原因是您的终端不支持该字符集。

0
我在打印扩展ASCII表(128-255)中的字符时遇到了问题。
抱歉,但实际上没有所谓的“扩展ASCII表”,ASCII只从0到127(总共128个字符)。你提出的问题实际上取决于字符集以及C对该字符集的支持是否在国际化库中。
首先,你需要确定一个输出设备支持的字符集(这是你打印字符的终端——虚拟或真实的),然后将所有内容编码为该字符集,你就会看到预期的输出。

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