You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言移除ANSI转义序列问题:lolcat类程序过滤失效

用C实现lolcat:正确过滤ANSI转义序列的解决方案

你的核心问题是原代码的ANSI转义序列过滤逻辑不完整,只能处理极小一部分转义序列,而且循环逻辑存在错误。下面是问题分析和修正后的完整实现:

原代码的问题

  1. 仅处理\x1b[...m序列:ANSI转义序列远不止这一种,比如清屏的\x1b[2J、光标移动的\x1b[10A、窗口标题设置的\x1b]0;Title\x07等都无法被过滤
  2. 循环逻辑错误:在跳过转义序列后,外层循环的i++会额外跳过一个正常字符,导致输出丢失内容
  3. 不必要的格式重置:遇到转义序列时打印\x1b[0m完全多余,我们的目标是彻底移除输入中的转义序列,而非重置格式

修正后的完整代码

#include <stdio.h>
#include <ctype.h>

// 打印带RGB颜色的字符
void prntcol(char c, int r, int g, int b) {
    printf("\x1b[38;2;%d;%d;%dm%c\x1b[0m", r, g, b, c);
}

// 生成彩虹渐变的RGB颜色
void getRainbowColor(int step, int *r, int *g, int *b) {
    // 循环渐变周期:红→黄→绿→青→蓝→紫→红(共6*255=1530步)
    step %= 1530;
    if (step < 255) {
        *r = 255; *g = step; *b = 0;
    } else if (step < 510) {
        step -= 255;
        *r = 255 - step; *g = 255; *b = 0;
    } else if (step < 765) {
        step -= 510;
        *r = 0; *g = 255; *b = step;
    } else if (step < 1020) {
        step -= 765;
        *r = 0; *g = 255 - step; *b = 255;
    } else if (step < 1275) {
        step -= 1020;
        *r = step; *g = 0; *b = 255;
    } else {
        step -= 1275;
        *r = 255; *g = 0; *b = 255 - step;
    }
}

// 处理单行输入:过滤转义序列并添加彩虹色
void processLine(const char *line) {
    static int colorStep = 0; // 静态变量保持颜色渐变进度,换行可选择重置
    int i = 0;
    int r, g, b;

    while (line[i] != '\0') {
        if (line[i] == '\x1b') {
            // 遇到ESC,开始处理ANSI转义序列
            i++;
            if (line[i] == '\0') break; // 防止越界

            if (line[i] == '[') {
                // 处理CSI序列(\x1b[...字母),跳过直到结束字母
                i++;
                while (line[i] != '\0' && !isalpha((unsigned char)line[i])) {
                    i++;
                }
                if (line[i] != '\0') {
                    i++; // 跳过结束字母
                }
            } else if (line[i] == ']') {
                // 处理OSC序列(\x1b]...\x07),跳过直到BEL字符
                i++;
                while (line[i] != '\0' && line[i] != '\x07') {
                    i++;
                }
                if (line[i] != '\0') {
                    i++; // 跳过BEL
                }
            } else {
                // 处理单字符转义序列(如ESC c 重置终端)
                i++;
            }
        } else if (line[i] == '\n') {
            printf("\n");
            i++;
            // colorStep = 0; // 取消注释可让每行从头开始彩虹渐变
        } else {
            // 生成彩虹色并打印字符
            getRainbowColor(colorStep++, &r, &g, &b);
            prntcol(line[i], r, g, b);
            i++;
        }
    }
}

int main() {
    char buffer[BUFSIZ];

    while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
        processLine(buffer);
    }

    return 0;
}

关键改进点

  1. 完整的转义序列过滤:
    • 处理所有CSI序列(\x1b[...字母):通过isalpha()判断结束符,覆盖所有光标控制、颜色设置类序列
    • 处理OSC序列(\x1b]...\x07):跳过窗口标题等特殊序列
    • 处理单字符转义序列:覆盖ESC加单个字符的终端控制指令
  2. 修复循环逻辑:严格控制i的递增,避免跳过正常字符
  3. 实现真正的彩虹渐变:通过getRainbowColor()生成平滑的彩虹色循环,符合lolcat的核心功能
  4. 边界安全:增加line[i] != '\0'的判断,防止越界访问

内容的提问来源于stack exchange,提问作者spaceman0x2A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:35:52