为何在C语言中无法打印扩展ASCII字符'Ç'的十进制值?
问题分析与解决方案
核心问题根源
Ubuntu终端默认采用UTF-8编码,当你输入Ç时,系统会将其编码为UTF-8的双字节序列0xC3 0x87(十进制195、135)——这就是你看到两个输出值的原因。而你期望的是单字节扩展ASCII(通常指ISO-8859-1/Latin-1)的数值,这需要先将UTF-8编码的输入转换为单字节的ISO-8859-1编码。
另外,之前修改argv为unsigned char**属于未定义行为,标准C中main的参数类型固定为int argc, char** argv,正确做法是在访问时将char强制转换为unsigned char以避免符号扩展。
符合限制的解决方案
我们可以使用Linux标准的iconv库完成编码转换,同时严格遵循你的代码限制(变量声明与赋值分离、仅使用while循环):
#include <stdio.h> #include <stdlib.h> #include <iconv.h> #include <string.h> int main(int argc, char **argv) { int i; iconv_t cd; char *input_ptr; char *output_ptr; size_t input_len; size_t output_len; char *output_buf; unsigned char *conv_ptr; // 初始化变量 i = 0; cd = (iconv_t)-1; input_ptr = NULL; output_ptr = NULL; input_len = 0; output_len = 0; output_buf = NULL; conv_ptr = NULL; if (argc == 2) { // 打开UTF-8转ISO-8859-1的转换句柄 cd = iconv_open("ISO-8859-1", "UTF-8"); if (cd != (iconv_t)-1) { input_ptr = argv[1]; input_len = strlen(argv[1]); // 输出缓冲区长度设为输入长度(ISO-8859-1每个字符占1字节) output_len = input_len; output_buf = (char*)malloc(output_len + 1); if (output_buf != NULL) { output_ptr = output_buf; // 执行编码转换 iconv(cd, &input_ptr, &input_len, &output_ptr, &output_len); // 添加字符串结束符 *output_ptr = '\0'; // 遍历转换后的字符串,打印每个字节的十进制值 conv_ptr = (unsigned char*)output_buf; while (*conv_ptr != '\0') { printf("%u ", *conv_ptr); conv_ptr++; } printf("\n"); // 释放缓冲区 free(output_buf); } // 关闭转换句柄 iconv_close(cd); } else { perror("iconv_open failed"); } } return 0; }
代码说明
- 编码转换:通过
iconv_open创建UTF-8到ISO-8859-1的转换句柄,将输入的UTF-8字符串转换为单字节的ISO-8859-1编码,确保每个字符对应一个字节。 - 类型处理:将转换后的字符串指针强制转为
unsigned char*,搭配%u格式符打印,避免有符号char导致的负数输出。 - 资源管理:手动分配/释放缓冲区、关闭转换句柄,避免内存泄漏。
- 限制遵循:所有变量先声明后赋值,仅使用
while循环遍历字符串。
编译与运行
在Ubuntu下使用以下命令编译:
gcc -o ascii_printer ascii_printer.c -liconv
运行时输入Ç:
./ascii_printer Ç
会输出199(这是ISO-8859-1中Ç的正确十进制值,你提到的128是ASCII控制字符,属于编码表混淆)。
内容的提问来源于stack exchange,提问作者Rosa Fernandes
相关产品推荐
相关产品推荐

