跳到主要内容
ansicode
C

在 C 中使用 ANSI 转义码

C 没有 ESC 的转义字面量 —— 请写 `\x1b`(十六进制)或 `\033`(八进制)。`printf` 与 `fputs` 在所有平台均按字节透传;在 Windows 10+ 上需先用 `SetConsoleMode(..., ENABLE_VIRTUAL_TERMINAL_PROCESSING)` 启用虚拟终端处理。任何接近 TUI 的需求(菜单、窗口、鼠标)请直接链接 `ncurses`,不要自行实现。

推荐库

  • ncurses

    C 的标准 TUI 库 —— 窗口、面板、菜单、表单、配色对。处理 terminfo 查找与原始输入,让你无需直接发送 ANSI。

  • termios

    POSIX 终端属性 API(`<termios.h>`)—— 切换到原始模式、关闭回显、关闭 ICANON 以读取单个按键。读取终端回送的鼠标 / 焦点 / 括号粘贴转义时必备。

  • termcap / terminfo (term.h)

    `setupterm()` + `tigetstr()` 查询能力(如 `setaf`、`cup`、`civis`),返回当前 `$TERM` 对应的转义字符串。

  • notcurses

    ncurses 的现代继任者 —— TrueColor、sixel/Kitty 图形、Unicode 感知。需要超出 ncurses 能力的新代码可选。

常用写法

直接使用 printf
#include <stdio.h>

int main(void) {
    printf("\x1b[1;31merror:\x1b[0m permission denied\n");
    return 0;
}
使用 tigetstr 查询 terminfo
#include <stdio.h>
#include <term.h>
#include <stdlib.h>

int main(void) {
    setupterm(NULL, 1, NULL);
    char *red   = tigetstr("setaf"); // takes one parameter
    char *reset = tigetstr("sgr0");
    putp(tparm(red, 1));
    fputs("error: permission denied", stdout);
    putp(reset);
    putchar('\n');
    return 0;
}
/* link with: cc prog.c -lncurses */
进度条期间隐藏光标,结束后务必恢复
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

static void restore(int sig) { (void)sig; printf("\x1b[?25h"); _exit(0); }

int main(void) {
    signal(SIGINT, restore);
    signal(SIGTERM, restore);
    printf("\x1b[?25l");  // hide cursor
    for (int i = 0; i <= 100; i++) {
        printf("\r\x1b[K%d%%", i);
        fflush(stdout);
        usleep(20000);
    }
    printf("\n");
    printf("\x1b[?25h");  // show cursor
    return 0;
}
进入原始模式读取转义输入
#include <termios.h>
#include <unistd.h>
#include <stdio.h>

int main(void) {
    struct termios orig, raw;
    tcgetattr(STDIN_FILENO, &orig);
    raw = orig;
    raw.c_lflag &= ~(ICANON | ECHO);     // no line-buffering, no echo
    tcsetattr(STDIN_FILENO, TCSANOW, &raw);

    /* now reads of stdin deliver single bytes including ESC sequences */
    int c;
    while ((c = getchar()) != 'q') { printf("0x%02x ", c); fflush(stdout); }

    tcsetattr(STDIN_FILENO, TCSANOW, &orig);  // always restore
    return 0;
}

相关序列

其他语言