繁体   English   中英

使用 C 更改文本颜色

[英]Change text color using C

我一直在阅读一些关于使用 C 更改文本颜色的文章,但问题是它们都与 Turbo C 有关

textcolor(RED);

而且我需要更改变量的颜色:值(用户输入)输出类似于我们在终端程序上执行“inxi -S”时得到的输出。 如何更改控制台程序的颜色?

这个问题只能部分回答,因为没有指定彩色输出,它只知道文本。 所以解决方案取决于目标平台,从评论中可以看出,OP 对不止一个平台感兴趣。

不久前我做了我自己的实现,它在支持 ANSI 颜色的 *nix 终端和win32控制台中工作,我已经在评论中提到过,但是对于答案,这应该被简化到最低限度,所以这里有一个例子:

#ifdef _WIN32
#include <windows.h>    // for win32 API functions
#include <io.h>         // for _get_osfhandle()
#else
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE   // enable POSIX extensions in standard library headers
#endif
#include <unistd.h>     // for isatty()
#endif

#include <stdlib.h>
#include <stdio.h>

// use an enum for platform-independent interface:
typedef enum TextColor
{
    TC_BLACK = 0,
    TC_BLUE = 1,
    TC_GREEN = 2,
    TC_CYAN = 3,
    TC_RED = 4,
    TC_MAGENTA = 5,
    TC_BROWN = 6,
    TC_LIGHTGRAY = 7,
    TC_DARKGRAY = 8,
    TC_LIGHTBLUE = 9,
    TC_LIGHTGREEN = 10,
    TC_LIGHTCYAN = 11,
    TC_LIGHTRED = 12,
    TC_LIGHTMAGENTA = 13,
    TC_YELLOW = 14,
    TC_WHITE = 15
} TextColor;

// set output color on the given stream:
void setTextColor(FILE *stream, TextColor color);

int main(void)
{
    puts("Color test.");
    setTextColor(stdout, TC_GREEN);
    puts("This is green!");
    setTextColor(stdout, TC_LIGHTGRAY);
    puts("back to normal.");
    return EXIT_SUCCESS;
}

#ifdef _WIN32

void setTextColor(FILE *stream, TextColor color)
{
    int outfd = fileno(stream);
    HANDLE out = (HANDLE)_get_osfhandle(outfd);
    DWORD outType = GetFileType(out);
    DWORD mode;
    if (outType == FILE_TYPE_CHAR && GetConsoleMode(out, &mode))
    {
        // we're directly outputting to a win32 console if the file type
        // is FILE_TYPE_CHAR and GetConsoleMode() returns success

        SetConsoleTextAttribute(out, color);
        // the enum constants are defined to the same values
        // SetConsoleTextAttribute() uses, so just pass on.
    }
}

#else

static const char *ansiColorSequences[] =
{
    "\x1B[0;30m",
    "\x1B[0;34m",
    "\x1B[0;32m",
    "\x1B[0;36m",
    "\x1B[0;31m",
    "\x1B[0;35m",
    "\x1B[0;33m",
    "\x1B[0;37m",
    "\x1B[1;30m",
    "\x1B[1;34m",
    "\x1B[1;32m",
    "\x1B[1;36m",
    "\x1B[1;31m",
    "\x1B[1;35m",
    "\x1B[1;33m",
    "\x1B[1;37m"
};

static const char *ansiColorTerms[] =
{
    "xterm",
    "rxvt",
    "vt100",
    "linux",
    "screen",
    0
    // there are probably missing a few others
};

// get current terminal and check whether it's in our list of terminals
// supporting ANSI colors:
static int isAnsiColorTerm(void)
{
    char *term = getenv("TERM");
    for (const char **ansiTerm = &ansiColorTerms[0]; *ansiTerm; ++ansiTerm)
    {
        int match = 1;
        const char *t = term;
        const char *a = *ansiTerm;
        while (*a && *t)
        {
            if (*a++ != *t++)
            {
                match = 0;
                break;
            }
        }
        if (match) return 1;
    }
    return 0;
}

void setTextColor(FILE *stream, TextColor color)
{
    int outfd = fileno(stream);
    if (isatty(outfd) && isAnsiColorTerm())
    {
        // we're directly outputting to a terminal supporting ANSI colors,
        // so send the appropriate sequence:
        fputs(ansiColorSequences[color], stream);
    }
}

#endif

注 1 :我的原始代码做了更多的工作,包括通过管道发送 ansi 颜色代码,这可能不是您想要的,具体取决于您希望将输出通过管道传输到何处。 它还有一个类似printf()界面支持颜色。 您可以在此处的“核心”库中找到它。

注意 2 :如果您最终想对终端做更多的事情而不仅仅是颜色,例如控制光标,输出到固定位置等,我建议您改用curses Linux 系统上的默认实现是ncurses ,对于 Windows,您可以使用pdcurses —— 可以针对 ncurses 或 pdcurses 构建/链接相同的代码,具体取决于您的目标平台。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM