欢迎光临
我们一直在努力

C/C++控制台文字颜色设置全攻略

C/C++控制台文字颜色设置全攻略

前言

写了这么多年控制台程序,是不是早就看腻了那千篇一律的黑底白字?其实让控制台输出带上颜色并没有想象中那么复杂。今天就来聊聊C/C++里各种改颜色的方法,顺便把坑都给你排一遍。

需要说明的是:标准C/C++本身没有“颜色”这个概念。所有颜色控制本质上都是调用操作系统提供的接口,或者向终端输出特定的控制字符。所以不同平台的方法是完全不同的。

一、system(“color”) —— 最简单粗暴的方法

这是很多新手最先接触到的方法,因为代码量最少。

用法

#include <windows.h> // 或 <stdlib.h>

int main() {
system("color 0A"); // 背景黑色(0),文字淡绿色(A)
printf("Hello World!\\n");
return 0;
}

color后面跟两个十六进制字符(0-F):第一个是背景色,第二个是文字颜色。

颜色代号对照表:

代号颜色代号颜色
0 黑色 8 灰色
1 蓝色 9 淡蓝色
2 绿色 A 淡绿色
3 湖蓝色 B 淡浅绿色
4 红色 C 淡红色
5 紫色 D 淡紫色
6 黄色 E 淡黄色
7 白色 F 亮白色

致命缺点

system("color")一旦调用,整个控制台的颜色都会被改变,无法做到只让某一行文字变色。而且它本质上是调用系统命令,有性能开销,在一些在线评测环境中甚至可能被禁用。

适合场景:快速测试、小工具、不在乎“一行一种颜色”的情况。

二、SetConsoleTextAttribute —— Windows下最靠谱的方法

Windows控制台原生支持文字颜色控制,SetConsoleTextAttribute是Windows API中专门干这个活的函数。它不需要第三方库,不依赖ANSI转义,在Windows 7及以上版本都能用。

基本用法

#include <windows.h>
#include <iostream>

int main() {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); // 获取控制台输出句柄

// 设置文字为亮红色
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
std::cout << "这段文字是亮红色" << std::endl;

// 重置为默认白色(三原色全开)
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
std::cout << "回到白色" << std::endl;

return 0;
}

颜色常量说明

SetConsoleTextAttribute的颜色值是通过位掩码组合实现的:

前景色(文字颜色):

  • FOREGROUND_RED — 红色
  • FOREGROUND_GREEN — 绿色
  • FOREGROUND_BLUE — 蓝色
  • FOREGROUND_INTENSITY — 高亮(使颜色变亮)

背景色(对应常量):

  • BACKGROUND_RED
  • BACKGROUND_GREEN
  • BACKGROUND_BLUE
  • BACKGROUND_INTENSITY

组合方式就是按位或(|)。例如:

  • FOREGROUND_RED | FOREGROUND_INTENSITY → 亮红色
  • FOREGROUND_RED | FOREGROUND_GREEN → 黄色(红+绿)
  • FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE → 白色

注意事项

  • 必须先获取有效句柄,不能硬写0或NULL。建议检查返回值:

    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE) return;

  • 颜色不会自动继承。每次输出前都要重新设置,否则后续所有输出都会保持之前的颜色。所以记得在需要的时候重置。

  • 只适用于Windows。在Linux/macOS上这段代码根本编译不过。

  • 封装成函数

    实际开发中一般会封装一下:

    #include <windows.h>
    #include <iostream>

    void setColor(WORD color) {
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut != INVALID_HANDLE_VALUE) {
    SetConsoleTextAttribute(hOut, color);
    }
    }

    int main() {
    setColor(FOREGROUND_RED | FOREGROUND_INTENSITY);
    std::cout << "红色错误信息" << std::endl;

    setColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
    std::cout << "绿色成功信息" << std::endl;

    setColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); // 重置白色
    return 0;
    }

    三、ANSI转义码 —— 跨平台的终极方案

    ANSI转义码是一套起源于上世纪70年代的终端控制标准,通过特殊的字符序列来控制文本样式、颜色和光标位置。

    在Linux、macOS以及现代终端中,这是最主流的方式。Windows从10版本1511开始也原生支持了,只是默认没开启。

    基本语法

    在C/C++中,用\\033(八进制)或\\x1b(十六进制)表示转义字符的开头。

    基本颜色控制:

    std::cout << "\\033[31m" << "红色文字" << "\\033[0m" << std::endl;
    // ^^^^^^ ^^^^^^^^ ^^^^^^
    // 开始红色 文字内容 重置所有样式

    格式说明: \\033[ + 参数 + m

    常用参数:

    参数作用参数作用
    0 重置所有样式 1 粗体/高亮
    4 下划线 7 反色
    30-37 前景色(黑红绿黄蓝紫青白) 40-47 背景色
    90-97 亮前景色 100-107 亮背景色

    具体颜色对应:

    • 30/40 — 黑色
    • 31/41 — 红色
    • 32/42 — 绿色
    • 33/43 — 黄色
    • 34/44 — 蓝色
    • 35/45 — 紫色
    • 36/46 — 青色
    • 37/47 — 白色

    示例:

    std::cout << "\\033[32m绿色文字\\033[0m" << std::endl;
    std::cout << "\\033[1;33m亮黄色加粗\\033[0m" << std::endl; // 多个参数用分号分隔
    std::cout << "\\033[41;37m白字红底\\033[0m" << std::endl;

    256色模式

    除了基本的16色,ANSI还支持256色甚至RGB真彩色。

    256色语法:

    // 前景色:\\033[38;5;{颜色代码}m
    // 背景色:\\033[48;5;{颜色代码}m
    std::cout << "\\033[38;5;196m亮红色\\033[0m" << std::endl; // 196是亮红
    std::cout << "\\033[38;5;46m亮绿色\\033[0m" << std::endl; // 46是亮绿

    256色的范围:

    • 0-15:系统标准16色
    • 16-231:216色立方(RGB各6级)
    • 232-255:24级灰度

    Windows下启用ANSI支持

    这是最大的坑。 旧版Windows控制台(cmd.exe)默认不解析ANSI转义码。直接输出\\033[31m你会看到满屏的←[31m乱码。

    解决方法:手动启用虚拟终端处理模式。

    #include <windows.h>
    #include <iostream>

    int main() {
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD dwMode = 0;
    GetConsoleMode(hOut, &dwMode);
    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    SetConsoleMode(hOut, dwMode);

    // 现在可以愉快地使用ANSI了
    std::cout << "\\033[32m绿色\\033[0m" << std::endl;
    return 0;
    }

    注意:这个设置只对当前进程有效,子进程不会继承。而且Windows 7/8完全不支持。

    Linux/macOS下直接使用

    在Linux和macOS上,终端原生支持ANSI转义码,不需要任何额外配置。

    但有一个小细节:如果程序输出被重定向到文件,或者运行在非终端环境(如CI/CD管道),转义码会变成一堆乱码混在日志里。建议用isatty()检测一下:

    #include <unistd.h>

    if (isatty(STDOUT_FILENO)) {
    printf("\\x1b[32m[OK]\\x1b[0m 一切正常\\n");
    } else {
    printf("[OK] 一切正常\\n"); // 非终端环境不加颜色
    }

    四、完整代码汇总

    下面是一份整合了三种方法的完整示例代码,Windows下优先用SetConsoleTextAttribute,Linux/macOS自动切换到ANSI:

    /**
    * C/C++ 控制台颜色设置 – 完整示例
    * 编译: g++ -std=c++11 console_color.cpp -o console_color
    * 支持: Windows (SetConsoleTextAttribute) / Linux/macOS (ANSI)
    */

    #include <iostream>
    #include <string>

    #ifdef _WIN32
    #include <windows.h>
    #else
    #include <unistd.h>
    #endif

    // ———- 颜色枚举(统一接口) ———-
    enum ConsoleColor {
    BLACK = 0,
    RED,
    GREEN,
    YELLOW,
    BLUE,
    MAGENTA,
    CYAN,
    WHITE,
    BRIGHT_RED,
    BRIGHT_GREEN,
    BRIGHT_YELLOW,
    BRIGHT_BLUE,
    BRIGHT_MAGENTA,
    BRIGHT_CYAN,
    BRIGHT_WHITE
    };

    // ———- Windows 实现 ———-
    #ifdef _WIN32

    WORD getWinColor(ConsoleColor color) {
    switch (color) {
    case BLACK: return 0;
    case RED: return FOREGROUND_RED;
    case GREEN: return FOREGROUND_GREEN;
    case YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
    case BLUE: return FOREGROUND_BLUE;
    case MAGENTA: return FOREGROUND_RED | FOREGROUND_BLUE;
    case CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE;
    case WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
    case BRIGHT_RED: return FOREGROUND_RED | FOREGROUND_INTENSITY;
    case BRIGHT_GREEN: return FOREGROUND_GREEN | FOREGROUND_INTENSITY;
    case BRIGHT_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
    case BRIGHT_BLUE: return FOREGROUND_BLUE | FOREGROUND_INTENSITY;
    case BRIGHT_MAGENTA:return FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
    case BRIGHT_CYAN: return FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
    case BRIGHT_WHITE: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
    default: return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
    }
    }

    void setConsoleColor(ConsoleColor color) {
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut != INVALID_HANDLE_VALUE) {
    SetConsoleTextAttribute(hOut, getWinColor(color));
    }
    }

    // ———- Unix/Linux/macOS 实现 ———-
    #else

    const char* getAnsiColor(ConsoleColor color) {
    switch (color) {
    case BLACK: return "\\033[30m";
    case RED: return "\\033[31m";
    case GREEN: return "\\033[32m";
    case YELLOW: return "\\033[33m";
    case BLUE: return "\\033[34m";
    case MAGENTA: return "\\033[35m";
    case CYAN: return "\\033[36m";
    case WHITE: return "\\033[37m";
    case BRIGHT_RED: return "\\033[91m";
    case BRIGHT_GREEN: return "\\033[92m";
    case BRIGHT_YELLOW: return "\\033[93m";
    case BRIGHT_BLUE: return "\\033[94m";
    case BRIGHT_MAGENTA:return "\\033[95m";
    case BRIGHT_CYAN: return "\\033[96m";
    case BRIGHT_WHITE: return "\\033[97m";
    default: return "\\033[0m";
    }
    }

    void setConsoleColor(ConsoleColor color) {
    // 检测是否为终端环境,避免污染重定向输出
    if (isatty(STDOUT_FILENO)) {
    std::cout << getAnsiColor(color);
    }
    }

    #endif

    // ———- 重置颜色 ———-
    void resetColor() {
    #ifdef _WIN32
    setConsoleColor(WHITE);
    #else
    if (isatty(STDOUT_FILENO)) {
    std::cout << "\\033[0m";
    }
    #endif
    }

    // ———- 彩色输出函数 ———-
    void colorPrint(const std::string& text, ConsoleColor color) {
    setConsoleColor(color);
    std::cout << text;
    resetColor();
    }

    // ———- 主函数测试 ———-
    int main() {
    std::cout << "========== 控制台颜色测试 ==========" << std::endl;

    colorPrint("红色文字\\n", RED);
    colorPrint("绿色文字\\n", GREEN);
    colorPrint("黄色文字\\n", YELLOW);
    colorPrint("蓝色文字\\n", BLUE);
    colorPrint("紫色文字\\n", MAGENTA);
    colorPrint("青色文字\\n", CYAN);

    std::cout << "\\n========== 亮色测试 ==========" << std::endl;

    colorPrint("亮红色\\n", BRIGHT_RED);
    colorPrint("亮绿色\\n", BRIGHT_GREEN);
    colorPrint("亮黄色\\n", BRIGHT_YELLOW);
    colorPrint("亮蓝色\\n", BRIGHT_BLUE);

    std::cout << "\\n========== 混合输出 ==========" << std::endl;

    setConsoleColor(RED);
    std::cout << "错误";
    resetColor();
    std::cout << ": 文件未找到" << std::endl;

    setConsoleColor(GREEN);
    std::cout << "成功";
    resetColor();
    std::cout << ": 编译完成" << std::endl;

    setConsoleColor(YELLOW);
    std::cout << "警告";
    resetColor();
    std::cout << ": 使用了已弃用的API" << std::endl;

    return 0;
    }

    五、各方法对比

    对比项system("color")SetConsoleTextAttributeANSI转义码
    跨平台性 ❌ 仅Windows ❌ 仅Windows ✅ Linux/macOS/Windows 10+
    是否需要额外头文件 <windows.h>或<stdlib.h> <windows.h> 无(标准C++即可)
    能否单独控制某行 ❌ 整个控制台统一变色 ✅ 可精确控制每行 ✅ 可精确控制每行
    性能开销 较大(调用外部命令) 小(直接API调用) 小(直接输出字符)
    学习难度 ⭐ 极低 ⭐⭐ 低 ⭐⭐⭐ 中等
    Windows 7兼容 ❌ 不支持
    Windows 10+兼容 ✅(需手动启用VT模式)
    支持颜色数量 16色 16色 256色 / 真彩色
    是否支持样式(粗体/下划线)
    推荐场景 快速测试、Demo Windows正式项目 跨平台项目、现代终端

    六、常见问题与避坑指南

    Q1:为什么我的ANSI转义码在Windows下无效?

    因为旧版cmd默认不解析ANSI。要么手动调用SetConsoleMode开启VT模式,要么换用Windows Terminal。如果不想折腾,直接用SetConsoleTextAttribute。

    Q2:SetConsoleTextAttribute设置颜色后,后面的输出全变色了?

    因为这个API改变的是控制台句柄的属性,会一直生效直到你再次修改。每次输出完记得重置:

    SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);

    Q3:在Linux下用ANSI,但输出被重定向到文件时出现了乱码?

    因为转义码被当作文本写进文件了。用isatty()判断一下当前是否是终端,不是的话就别输出颜色。

    Q4:system("color")和SetConsoleTextAttribute能混用吗?

    可以,但不推荐。system("color")会改变整个控制台的默认颜色,而SetConsoleTextAttribute是在这个基础上再做调整。混用容易造成混乱,选一种统一使用就好。

    Q5:多线程环境下颜色控制安全吗?

    不安全。 颜色状态是全局的,多个线程同时输出时可能互相覆盖。真要线程安全,要么加锁,要么用线程局部缓冲。不过一般小项目不用太纠结这个问题。

    结语

    总结一下我的建议:

    • Windows-only项目:无脑上SetConsoleTextAttribute,稳定可靠,不用折腾。
    • 跨平台项目:用ANSI转义码,配合isatty()做环境检测,Windows下记得开启VT模式。
    • 随便玩玩:system("color")最省事。

    颜色控制说到底就是跟操作系统或终端打交道,搞清楚原理之后其实就那么回事。希望这篇文章能帮你少踩几个坑。

    赞(0)
    未经允许不得转载:171主机测评 » C/C++控制台文字颜色设置全攻略
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址