C++中的彩色输出

32

如何在Xcode中使用iostream打印彩色输出?例如,我想要将Hello World!打印为Hello红色,World蓝色和!黄色。应该怎么做?


1
可能是重复的问题(至少相关)https://dev59.com/2Ws05IYBdhLWcg3wJurp - Johan Lundberg
阅读此帖子 http://www.daniweb.com/software-development/cpp/threads/9921 - Henk Jansen
请查看http://ascii-table.com/ansi-escape-sequences.php。 - Some programmer dude
@Anycorn,你有什么替代方案可以提出吗? - Mr Lister
3个回答

93

你需要终端颜色代码。对于Linux来说,它是以下内容(你的系统可能不同,请查找):

//the following are UBUNTU/LINUX, and MacOS ONLY terminal color codes.
#define RESET   "\033[0m"
#define BLACK   "\033[30m"      /* Black */
#define RED     "\033[31m"      /* Red */
#define GREEN   "\033[32m"      /* Green */
#define YELLOW  "\033[33m"      /* Yellow */
#define BLUE    "\033[34m"      /* Blue */
#define MAGENTA "\033[35m"      /* Magenta */
#define CYAN    "\033[36m"      /* Cyan */
#define WHITE   "\033[37m"      /* White */
#define BOLDBLACK   "\033[1m\033[30m"      /* Bold Black */
#define BOLDRED     "\033[1m\033[31m"      /* Bold Red */
#define BOLDGREEN   "\033[1m\033[32m"      /* Bold Green */
#define BOLDYELLOW  "\033[1m\033[33m"      /* Bold Yellow */
#define BOLDBLUE    "\033[1m\033[34m"      /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m"      /* Bold Magenta */
#define BOLDCYAN    "\033[1m\033[36m"      /* Bold Cyan */
#define BOLDWHITE   "\033[1m\033[37m"      /* Bold White */

这使你能够做到以下事情:

std::cout << RED << "hello world" << RESET << std::endl;
注意:如果你没有使用RESET,该颜色将保持更改状态,直到下一次使用颜色代码。

1
他使用的是Mac OS(至少我认为是,因为他提到了XCode),所以这应该可以工作。 - Mr Lister
16
它可以在终端中运行,但无法在Xcode控制台窗口中运行。 - Paul R
@shuttle87,感谢您的回复。我该如何设置三个不同颜色的变量,例如char hello ='H'char world ='W'char ex ='!'以不同的颜色显示? - Shoe
1
你需要将格式化代码发送到终端,然后再发送字符和重置代码。因此,如果您想为单个字符执行此操作,可以像这样做:cout << RED << hello << RESET;。如果您经常执行此操作,则还可以编写一些实用程序函数以使其更加容易。 - shuttle87
2
@Paul R,你知道如何检测控制台是否支持ANSI转义码,以便Xcode控制台不会打印它们吗? - elmattic
顺便说一下,虽然是小事,但在C++中不要使用define来定义这样的东西。总之,非常感谢! - IceFire

12
在支持ANSI的终端上,使用更C++的方式编写自己的ansi流操作符是可能的,就像std::endl一样,但用于处理ansi转义代码。
以下为基本原始实现的代码:
namespace ansi {
  template < class CharT, class Traits >
  constexpr
  std::basic_ostream< CharT, Traits > & reset( std::basic_ostream< CharT, Traits > &os )
  {
     return os << "\033[0m";
  }

  template < class CharT, class Traits >
  constexpr
  std::basic_ostream< CharT, Traits > & foreground_black( std::basic_ostream< CharT, Traits > &os )
  {
     return os << "\033[30m";
  }

  template < class CharT, class Traits >
  constexpr
  std::basic_ostream< CharT, Traits > & foreground_red( std::basic_ostream< CharT, Traits > &os )
  {
     return os << "\033[31m";
  }
  ...
 } // ansi

这个可以在代码中像这样使用:

std::cout << ansi::foreground_red << "in red" << ansi::reset << std::endl;

2
非常优雅的解决方案,赞! - Mecanik
不错。通过使用 constexpr auto& 推导返回类型,稍微简化了这些内容。 - MHebes

9

使用{fmt}库,它正在被逐步吸收到C++标准中,从C++20开始在<format>头文件中实现。目前,文本颜色和样式还没有被纳入标准,但是您可以通过从GitHub获取的版本来获得它们,在那里您可以找到这个示例:

#include <fmt/color.h>

int main() {
  fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold,
             "Hello, {}!\n", "world");
  fmt::print(fg(fmt::color::floral_white) | bg(fmt::color::slate_gray) |
             fmt::emphasis::underline, "Hello, {}!\n", "мир");
  fmt::print(fg(fmt::color::steel_blue) | fmt::emphasis::italic,
             "Hello, {}!\n", "世界");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接