如何用std::cin将字符ú正确存入char数组?解决存储为£的问题
解决std::cin读取ú时存储为£(163)的问题
这个问题本质是编码不匹配导致的——控制台输入使用的字符编码,和你期望存储的编码里,ú对应的字节值不一样。你看到的163是字节的十进制值,在当前编码里它对应£,但你希望这个字节值对应ú,那我们得从编码对齐入手解决。
下面分平台给你具体方案:
Windows平台
方法1:直接修改控制台编码
如果你的目标是让输入的ú直接被读取为字节163(十进制),且控制台显示这个字节时也显示ú,可以修改控制台的代码页为CP850(DOS编码,其中ú的字节值就是163)。
用Windows API在程序启动时设置编码:
#include <windows.h> #include <iostream> int main() { // 设置控制台输入/输出代码页为CP850 SetConsoleCP(850); SetConsoleOutputCP(850); char buf[100]; std::cin >> buf; // 验证存储的字节值和显示效果 for (int i = 0; buf[i] != '\0'; ++i) { // 转成unsigned char避免有符号char的负数问题 unsigned char byte = static_cast<unsigned char>(buf[i]); std::cout << "字符: " << buf[i] << ", 十进制值: " << static_cast<int>(byte) << "\n"; } return 0; }
运行后输入ú,你会看到存储的字节是163,且控制台显示的也是ú。
方法2:编码转换(不修改控制台编码)
如果不想改动控制台默认编码(比如默认是CP1252),可以先读取输入,再把编码从当前控制台编码转换为CP850:
#include <windows.h> #include <iostream> #include <string> int main() { char input_buf[100]; std::cin >> input_buf; // 1. 把CP1252的单字节字符串转成宽字符 int wide_len = MultiByteToWideChar(1252, 0, input_buf, -1, nullptr, 0); wchar_t* wide_str = new wchar_t[wide_len]; MultiByteToWideChar(1252, 0, input_buf, -1, wide_str, wide_len); // 2. 把宽字符转成CP850的单字节字符串 int cp850_len = WideCharToMultiByte(850, 0, wide_str, -1, nullptr, 0, nullptr, nullptr); char* cp850_buf = new char[cp850_len]; WideCharToMultiByte(850, 0, wide_str, -1, cp850_buf, cp850_len, nullptr, nullptr); // 验证结果 std::cout << "转换后字符串: " << cp850_buf << "\n"; for (int i = 0; cp850_buf[i] != '\0'; ++i) { unsigned char byte = static_cast<unsigned char>(cp850_buf[i]); std::cout << "字符: " << cp850_buf[i] << ", 十进制值: " << static_cast<int>(byte) << "\n"; } // 释放内存 delete[] wide_str; delete[] cp850_buf; return 0; }
这样输入的ú(CP1252里是字节250)会被转换成CP850的163,存储到char数组中。
Linux平台
Linux默认用UTF-8编码,ú是两个字节(0xC3 0xBA)。要把它转换成单字节163(对应CP850的ú),可以用iconv库做编码转换:
#include <iostream> #include <cstring> #include <iconv.h> int main() { char input[100]; std::cin >> input; // 初始化编码转换器:从UTF-8转CP850 iconv_t conv_handle = iconv_open("CP850", "UTF-8"); if (conv_handle == (iconv_t)-1) { perror("初始化编码转换器失败"); return 1; } size_t in_len = strlen(input); size_t out_len = 100; char* in_buf = input; char output[100]; char* out_buf = output; // 执行转换 if (iconv(conv_handle, &in_buf, &in_len, &out_buf, &out_len) == (size_t)-1) { perror("编码转换失败"); iconv_close(conv_handle); return 1; } // 添加字符串结束符 *out_buf = '\0'; // 验证结果 std::cout << "转换后字符串: " << output << "\n"; for (int i = 0; output[i] != '\0'; ++i) { unsigned char byte = static_cast<unsigned char>(output[i]); std::cout << "字符: " << output[i] << ", 十进制值: " << static_cast<int>(byte) << "\n"; } iconv_close(conv_handle); return 0; }
编译时需要链接iconv库:
g++ -o char_encoding_fix char_encoding_fix.cpp -liconv
关键注意点
char类型默认是有符号的,所以字节值大于127时会显示为负数,输出时一定要转成unsigned char再转int,才能得到正确的十进制值(比如163而不是-93)。- 你期望的
163对应ú,本质是指定了CP850编码下的字节值,所以所有方案都是围绕让输入/存储的编码对齐到CP850来实现的。
内容的提问来源于stack exchange,提问作者Mikerger
相关产品推荐
相关产品推荐

