在 C++ 中将特殊字符打印到 Windows 控制台

问题描述 投票:0回答:3

经过 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();

非常感谢任何帮助。 谢谢!

c++ console-application extended-ascii
3个回答
4
投票

欢迎体验编码的痛苦:(

#include <iostream>
#include <windows>

int main() {
    SetConsoleCP(437);
    SetConsoleOutputCP(437);
    std::cout << (char)157 << "\n";
}

生成:

Compilation and execution result

问题是您的源文件在 CP437 中不是,因此该字符的值与您尝试打印的字符不同(正如您所指出的,源文件中的值是 165,这是 CP437 中的不同字符) .

https://en.wikipedia.org/wiki/Code_page_437


0
投票

为什么此代码打印 Ñ (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


-1
投票

我在 MSVS Windows 11 上有一个工作代码。 关键是你需要告诉编译器:

  1. 您想要描述/输入一个键入为 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

//执行(输出)字符集在您输入 cmd chcp 65001 时决定,或者如果使用以下命令编译时活动代码页为:1250 时决定:cl.../execution-charset:utf-8...

#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);`
    
© www.soinside.com 2019 - 2024. All rights reserved.