颜色化 ANSI 转义码使用 选择图形呈现 (SGR) 序列,其格式为 CSI n m
,其中 CSI
(代表控制序列引导符)序列只是转义字符后跟一个开方括号,n
是某个参数,而 m
是字面上的 "m" 字符。
麻烦的部分实际上只是在C++字符串字面值中获取转义字符。您可以查看https://en.cppreference.com/w/cpp/language/escape了解有关C++中字符串转义的信息。简而言之,您可以使用八进制形式,例如\nnn
,或十六进制形式,例如\xn...
。 ASCII中的ESC字符的值为27,在八进制中为33,在十六进制中为1b。因此,您可以使用"\033[...m"
或"\x1b[...m"
。
例如:
"\033[31mred \033[33myellow \033[32mgreen \033[36mcyan \033[34mblue \033[35mmagenta"
"\x1b[31mred \x1b[33myellow \x1b[32mgreen \x1b[36mcyan \x1b[34mblue \x1b[35mmagenta"
(趣闻:Bash 使用类似的字符串转义序列,因此您可以在 Bash shell 中使用
echo -e
命令输出上述字符串文字,它也会起作用)
对于 C++20,在我的一个项目的头文件中,我使用以下代码片段来定义一些更易读的常量:
#include <string_view>
struct SgrPair final {
std::string_view on;
std::string_view off;
};
#if USE_ANSI_ESC
#define SGR(NAME, ON_STR, OFF_STR) inline constexpr SgrPair NAME { .on {(ON_STR)}, .off {(OFF_STR)} };
#else
#define SGR(NAME, ON_STR, OFF_STR) inline constexpr SgrPair NAME { .on {""}, .off {""} };
#endif
SGR(dim, "\033[2m", "\033[22m")
SGR(red, "\033[31m", "\033[39m")
#undef SGR
在上面的代码片段中,进行编译的用户可以选择是否将
USE_ANSI_ESC
宏定义为真值。
另请参见
ANSI颜色转义序列列表和
https://www.ecma-international.org/publications-and-standards/standards/ecma-48/。
Windows痛苦和折磨有趣
如果您的程序在类似cmd的Windows控制台上打印,则需要在程序中编写一些内容以在该控制台中启用ANSI转义代码(请参见 https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences):
#ifdef _WIN32
#include <windows.h>
#endif
int main() {
#ifdef _WIN32
DWORD con_mode;
GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &con_mode);
con_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), con_mode);
}
其他答案已经提到了这一点,但我添加了一些预处理包装,使其更容易在非Windows平台上编译而无需更改代码。
"Textcolor"是Turbo C/C++编译器的一个函数。请参见
Turbo C/C++ Compiler 2.0文档第384页。另请参见:
conio.h不包含textcolor()吗?。
\xNN
表示法为字符串定义ESC
的字符代码,其中NN
是符号的十六进制代码(0x1B
== 27 十进制)。此外,您还可以将字符串分成几个部分以使代码更清晰(请注意,编译器会将字符串字面量"..."
合并在一起):`printf ("\x1B" "[%dm" "HELLO!\n", 32);`
另请参见 @Baltasarq 的回答和下面的评论。 - ded32