使用C更改文本颜色

使用C更改文本颜色,c,linux,gcc,C,Linux,Gcc,我读了一些关于使用C更改文本颜色的文章,但问题是它们都与Turbo C有关 textcolor(RED); 我需要改变变量的颜色:值(用户输入)输出,类似于我们在终端程序上执行“inxi-S”时得到的结果。如何更改控制台程序的颜色?这个问题只能部分回答,因为它不指定彩色输出,只知道文本。因此,解决方案取决于目标平台,从评论中可以看出,OP对不止一个平台感兴趣 不久前,我做了自己的实现,它在支持ANSI颜色的*nix终端和win32控制台中工作,我在评论中已经提到了这一点,但为了回答这个问题,应

我读了一些关于使用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
\ifdef\u WIN32
#包含//用于win32 API函数
#包括//for _get_osfhandle()
#否则
#ifndef\u POSIX\u来源
#定义_POSIX_SOURCE//在标准库头中启用POSIX扩展
#恩迪夫
#包括//用于isatty()
#恩迪夫
#包括
#包括
//对平台无关接口使用枚举:
typedef枚举文本颜色
{
TC_黑色=0,
TC_蓝=1,
TC_绿色=2,
TC_青色=3,
TC_RED=4,
TC_品红=5,
TC_BROWN=6,
TC_LIGHTGRAY=7,
TC_DARKGRAY=8,
TC_浅蓝色=9,
TC_浅绿色=10,
TC_LIGHTCYAN=11,
TC_浅红色=12,
TC_浅品红色=13,
TC_黄色=14,
TC_白色=15
}文本颜色;
//在给定流上设置输出颜色:
void setTextColor(文件*流,文本颜色);
内部主(空)
{
puts(“颜色测试”);
setTextColor(标准色、TC_绿色);
puts(“这是绿色的!”);
setTextColor(标准色、TC_浅灰色);
使(“恢复正常”);
返回退出成功;
}
#ifdef_WIN32
void setTextColor(文件*流,文本颜色)
{
int outpd=文件号(流);
句柄输出=(句柄)\u获取\u OSF句柄(输出);
DWORD OUTYPE=GetFileType(输出);
德沃德模式;
if(outType==FILE\u TYPE\u CHAR&&GetConsoleMode(out,&mode))
{
//如果文件类型为
//文件类型为CHAR,GetConsoleMode()返回成功
SetConsoleTextAttribute(输出,颜色);
//枚举常量定义为相同的值
//SetConsoleTextAttribute()使用,所以请继续。
}
}
#否则
静态常量字符*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”
};
静态常量字符*ansiColorTerms[]=
{
“xterm”,
“rxvt”,
“vt100”,
“linux”,
“屏幕”,
0
//可能还有一些人失踪了
};
//获取当前终端并检查它是否在我们的终端列表中
//支持ANSI颜色:
静态整数isAnsiColorTerm(无效)
{
char*term=getenv(“术语”);
for(常量字符**ansiTerm=&ansiColorTerms[0];*ansiTerm;++ansiTerm)
{
int匹配=1;
const char*t=术语;
常量字符*a=*ansiTerm;
而(*a&&*t)
{
如果(*a++!=*t++)
{
匹配=0;
打破
}
}
如果(匹配)返回1;
}
返回0;
}
void setTextColor(文件*流,文本颜色)
{
int outpd=文件号(流);
if(isatty(outpd)和&isAnsiColorTerm())
{
//我们直接输出到支持ANSI颜色的终端,
//因此,发送适当的序列:
FPUT(ansiColorSequences[颜色],流);
}
}
#恩迪夫
注意1:我的原始代码做了更多的工作,包括通过管道发送ansi颜色代码,这可能不是您想要的,这取决于您希望输出通过管道传输到的位置。它还有一个类似于支持颜色的接口的
printf()
。您可以找到它


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

您是在询问Portable C,还是Linux或POSIX特定的C?实现这一点的两种常见方法是自行发布或使用类似于ncurses的库(它不仅仅用于颜色).@KeyikedalubeNdang它将在windows 10上工作,而不是在早期版本上。对于早期版本,您必须在控制台窗口中使用windows的控制台API进行颜色设置。@KeyikedalubeNdang这里是一个(ansi代码用于管道,您可以不着色管道输出)。另外,请查看和@KeyikedalubeNdang
textcolor()
与windows API无关,似乎是一个带有“turbo C”的特殊库调用,因此不,这在windows上不起作用。您需要
SetConsoleTextAttribute()
@MAChitgarha您建议的删除粗体颜色的编辑几乎肯定违背了OP的意图,因为现在您只是在数组中重复每种颜色两次。@KonradRudolph哦,很抱歉。请忽略编辑。