经过 2 个小时的搜索和尝试各种方法后,我正在绞尽脑汁地尝试将特殊的 ASCII 字符打印到控制台! (C++)
typedef unsigned char UCHAR;
int main()
{
UCHAR c = '¥';
cout << c;
return 0;
}
为什么此代码打印 Ñ (209) 而不是 ¥ (165)???
我已经尝试过:
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
但无论我传递给它哪个值,似乎都没有做任何事情。
还有人建议需要通过注册表更改控制台的字体。但这太荒谬了。我不希望我的最终用户仅仅为了运行我的程序而开始更改注册表值...
真正奇怪的是,如果我将所有 ascii 字符打印到文件中(使用 ofstream),它们会在记事本和 Visual Studio 编辑器(2012 专业版)中正确显示。
ofstream file("ASCII.txt");;
if (file.is_open())
{
UCHAR c = 0;
for (int i = 0; i < 256; i++)
{
c++;
file << c << "\t|\t" << (int)c << endl;
}
}
file.close();
非常感谢任何帮助。 谢谢!
欢迎体验编码的痛苦:(
#include <iostream>
#include <windows>
int main() {
SetConsoleCP(437);
SetConsoleOutputCP(437);
std::cout << (char)157 << "\n";
}
生成:
问题是您的源文件在 CP437 中不是,因此该字符的值与您尝试打印的字符不同(正如您所指出的,源文件中的值是 165,这是 CP437 中的不同字符) .
为什么此代码打印 Ñ (209) 而不是 ¥ (165)???
它不起作用,因为您的某些源代码、文字和控制台编码不匹配。
要在 C++23 中正确显示 Unicode 字符(请注意,
¥
不是 ASCII),您可以使用 std::print
:
#include <print>
int main () {
std::print("¥");
}
在
std::print
广泛使用之前,您可以使用开源 {fmt} 库,它基于 (godbolt):
#include <fmt/core.h>
int main () {
fmt::print("¥");
}
只需确保您的文字编码为 UTF-8,这通常是大多数平台上的默认编码,并且在 Windows/MSVC 上通过
/utf-8
启用。
这比使用 CP437 等遗留代码页更可靠,因为它不依赖于您并不总是控制的全局状态。您也不需要使用不可移植的 API 来更改控制台代码页。
免责声明:我是 {fmt} 和 C++23 的作者
std::print
。
我在 MSVS Windows 11 上有一个工作代码。 关键是你需要告诉编译器:
您想要描述/输入一个键入为 u8"\uxxx ..." 的字符 或 u8"😀" ,(复制/粘贴),或 u8"\U0001F600" 编码为 UTF-8。 为此,您需要在开发人员命令行中输入: chcp 65001 输入 您将看到:活动代码页:65001。 或者,您可以按原样使用代码页, 您在 cmd 上输入 chcp,您可能会看到: 活动代码页:1250 但你需要编译: cl /W4 /EHsc /source-charset:utf-8 mbs_extended.cpp mbs_extended.cpp 这样你的代码 u8"\uxxx ..." 或 u8"😀" ,(复制/粘贴)或 u8"\U0001F600" ,将被转换为 char 序列,该序列将被转换为 UTF-8 中的数字/代码,存储在 提供了字符 。 当打印该字符时,因为您使用了 chcp 65001 Enter,所以输出将被转换为所需的 unicode 字符。 你可以玩一下上面的代码,仔细阅读注释。
在此处输入代码`//cl /W4 /EHsc /source-charset:utf-8 /execution-charset:utf-8, 如果在 chcp 输入后,活动代码页为:1250 -> 这会将 chcp 活动代码更改为: 65001 // 当您在开发人员命令行中键入 chcp Enter 时,您的输出可以是:活动代码页:1250 或其他。 // 如果输入 chcp 65001 输入您将得到 Active code page: 65001 // 因此,如果在 cmd 中首先输入:chcp 65001,则可以使用以下行进行编译: //cl /W4 /EHsc /source-charset:utf-8 mbs_extended.cpp mbs_extended.cpp
#include <iostream>
#include <windows.h>
using namespace std;
int main ()
{
// SetConsoleOutputCP(CP_UTF8);
// If you compile with: cl /W4 /EHsc /source-charset:utf-8 mbs_extended.cpp mbs_extended.cpp and Active code page: 1250, -> Uncomment line before, and surprise:
// At the end of Program,
// Active code page: 1250
const char *text = u8"This text is in UTF-8. ¡Olé! 佻\n";
std::cout << text;
char *s = u8"\u2193"; //universal code name for: ↓
// might be possible to use char8_t specially designed for UTF-8 if compile with /std:c++20 or latest
printf("\nSymbol: %s\n", s);
printf(" length: %zu\n", strlen(s));
size_t sz0 = strlen(s);
cout << "Arrow hexcode: ";
for(int i = 0; i < sz0; i++)
{
printf("%X ", (unsigned char) s[i] );
}
cout << endl;
char *s1 = u8"😀";
printf("\nSymbol: %s\n", s1);
size_t sz = strlen(s1);
printf(" length: %zu\n", strlen(s1));
cout << "Smiley hexcode: ";
for(int i = 0; i < sz; i++)
{
printf("%X ", (unsigned char) s1[i] );
}
cout << endl;
char *s2 = u8"\U0001F600"; //universal code name for: 😀 See the difference between: u8"\U0001F600" and u8"\u2193" (UTF-32 vs UTF-16), (8 vs 4)
// /source-charset:utf-8 and the Prefix u8
printf("\nSymbol: %s\n", s2);
size_t sz1 = strlen(s2);
printf(" length: %zu\n", strlen(s2));
cout << "Smiley hexcode: ";
for(int i = 0; i < sz1; i++)
{
printf("%X ", (unsigned char) s2[i] );
}
cout << endl;
return 0;
}
// If you uncomment SetConsoleOutputCP(CP_UTF8); , Remember, Active code page was: 1250 and you did'nt modify with chcp in cmd line.
// So either chcp 65001 in cmd line either SetConsoleOutputCP(CP_UTF8), either cl.../execution-charset:utf-8
// After program finish execution,
// Active code page: 65001 (UTF-8),
//(multi byte string), (one or more 2 or 3 bytes, for characters)
// This is the work of SetConsoleOutputCP(CP_UTF8);`