彩色端子输出不会复位

时间:2015-05-05 17:57:45

标签: c linux terminal stdio

在编写更大的程序时,我偶然发现了彩色文本输出的小问题。这是一个更简单的程序,可以重现这个问题。

#include <stdio.h>

#define COL_RESET "\033[0m"
#define COL_BG_RED  "\x1B[41m"

char *str = "the quick brown fox jumped over the lazy dog";

int main(int argc, char *argv[])
{
    int i = 10;
    while (i) {
        puts(COL_BG_RED);
        puts(str);
        puts(COL_RESET);
        puts(str);
        i--;
    }
    return 0;
}

现在这是我运行程序时得到的结果:

第一次 - 预期结果

first time

第二次

enter image description here

正如您所知,即使重置红色后,程序也会决定随机打印行。在新终端中启动时,它始终打印预期结果。除非我运行clear,否则无法保证输出不会像第二张图片那样受损。

在我使用xterm的图片中,虽然其他终端做同样的事情。

我该怎么做才能防止这种情况发生?

3 个答案:

答案 0 :(得分:3)

终端开始滚动时似乎出现问题。

问题可能是puts附加换行符这一事实造成的。使用printf修改您的代码。

printf(COL_BG_RED);
printf(str);
puts(COL_RESET);
puts(str);

答案 1 :(得分:3)

如上所述,这是一些众所周知的终端的已知行为:当滚动(或反向滚动)时,屏幕上新清除的区域将填充当前背景颜色。 Linux控制台就是这样做的(除了几年前的一个小故障,在terminal database中注明)。 xterm does it

在ncurses中,几个相关的行为被集中在一起作为bce(背景颜色擦除)功能:

  • 由于滚动而填充新清除的行
  • 删除显示,以及删除以光标结尾或以光标开头的部分。
  • 删除一条线,或将部分擦除,或从光标擦除到线的末尾
  • 在光标位置插入(空白)
  • 删除字符

通常ncurses填充空白(当终端条目为poorly chosen时,这只是一个问题),你不会看到这个。但是使用普通的转义序列意味着你可以稍微探索bce的细微差别。

直接使用转义序列打印颜色的终端应用程序应在写入任何其他不打算着色的文本之前重置颜色。其他应用程序(例如shell中的行编辑)在删除行内的文本时必须牢记此规则

答案 2 :(得分:0)

当我在本地运行时,我也观察到一些奇怪的行为。

是:

#define COL_RESET      "\0x1b[39;49m" // reset fore/back ground to normal
#define COL_BG_RED     "\033[41m"

<强>输出:

enter image description here

当我将#define更改为使用八进制而不是十六进制时,我得到一个不同的(预期的)结果。

是:

#define COL_RESET "\033[39;49m"

<强>输出:

enter image description here

您也可以考虑创建一个使用printf颜色的宏。

#include <stdio.h>

#define COL_RESET      "\033[39;49m"
#define COL_BG_RED     "\033[41m"
#define COL_BG_NORMAL  "\033[49m"

#define COLOR_NORMAL    "\033[m"
#define COLOR_RESET     "\033[0m"
#define COLOR_BLACK     "\033[30m"
#define COLOR_RED       "\033[31m"
#define COLOR_GREEN     "\033[32m"
#define COLOR_YELLOW    "\033[33m"
#define COLOR_BLUE      "\033[34m"
#define COLOR_MAGENTA   "\033[35m"
#define COLOR_CYAN      "\033[36m"
#define COLOR_WHITE     "\033[37m"

#define COLOR_PRINTF(colorCode,fmt,...) printf("%s" fmt "%s", colorCode, __VA_ARGS__, COL_RESET)

char *str = "the quick brown fox jumped over the lazy dog";

int main(int argc, char *argv[])
{
    int i = 1;
    while (i) {
        COLOR_PRINTF(COLOR_GREEN, "%s\n", str);
        COLOR_PRINTF(COL_BG_RED, "%s\n", str);
        i--;
    }
    return 0;
}