c ++ ansi转义码不向控制台显示颜色

c++ ansi escape codes not displaying color to console

我正在尝试更改控制台中文本的颜色。

我们应该使用配置文件从以下位置读取 ansi 转义码:

这是我文件中的内容

red     3[0;31m      #red
blue    3[0;34m      #blue
green   3[0;32m      #green
grey    3[0;37m      #grey

这是我的代码:

    #include <iostream> 
    #include <sstream>
    #include <iomanip>
    #include <string>
    #include <fstream>
    #include <map>
    using namespace std;

int main(int argc, char * argv[]){
    string file = "config.txt";
    string line = "";
    string tag = "";
    string ansi = "";
    map <string, string> m;

    if(argc == 2){  
        file = argv[1];
    }
    ifstream in(file, ios_base::in | ios_base::binary);
    if(!in){
        cerr<<"could not open file";
    }

    while (getline(in, line)){
        istringstream iss(line);
        if(iss>>tag>>ansi){
            auto it = m.find(tag);
            if(it == m.end()){
                m.insert(make_pair(tag,ansi));
            }

        }
    }

    for(auto x: m){
        cout<<x.second<<x.first<<endl;
    }
    cout<<"3[0;35mhello";
    return 0;
}

不知道为什么,但只有最后一个打印语句实际显示为彩色,其他输出 ansi 转义码作为文本。

这是我的输出:

3[0;34mblue
3[0;32mgreen
3[0;37mgrey
3[0;31mred
hello (in purple)

文件中的转义序列不会转换为 ESC 字符。

此外,您的文件有共同的部分。

因此,我将包含ESC字符的公共部分移动到程序中,并让配置文件只有颜色代码。

文件:

red     31      #red
blue    34      #blue
green   32      #green
grey    37      #grey

计划:

#include <iostream> 
#include <sstream>
#include <iomanip>
#include <string>
#include <fstream>
#include <map>
using namespace std;

int main(int argc, char * argv[]){
    string file = "config.txt";
    string line = "";
    string tag = "";
    string ansi = "";
    map <string, string> m;

    if(argc == 2){  
        file = argv[1];
    }
    ifstream in(file, ios_base::in | ios_base::binary);
    if(!in){
        cerr<<"could not open file";
    }

    while (getline(in, line)){
        istringstream iss(line);
        if(iss>>tag>>ansi){
            auto it = m.find(tag);
            if(it == m.end()){
                m.insert(make_pair(tag,ansi));
            }

        }
    }

    for(auto x: m){
        cout<<"3[0;"<<x.second<<"m"<<x.first<<endl;
    }
    cout<<"3[0;35mhello";
    return 0;
}

读取 config.txt 文件的问题是字符串被读取时好像被分配为:

std::string str = "\033[0;31m";

\ 被视为一个字符。代码中需要的是"3",即八进制数033.

表示的字符

您可以更改代码中的以下行以忽略字符串的 "\033" 部分并打印八进制数。

    cout << x.second << x.first <<endl;

需要:

    cout << '3' << x.second.substr(4) << x.first <<endl;

有了这个改变,我在我的桌面上尝试了你的程序,它按预期工作。

而不是这样做:

cout<<"3[0;35mhello";

C++ 提供了编写您自己的流操纵器的可能性,例如 std::endl 来处理转义码。

目标是编写对我来说更具可读性的代码:

cout << ansi::foreground_magenta << "hello" ;

为了编写您自己的流操纵器,您可以像这样进行(简单的原始实现,但您需要从地图中获取值...):

#include <ostream>

namespace ansi {
  template < class CharT, class Traits >
  constexpr
  std::basic_ostream< CharT, Traits > & reset( std::basic_ostream< CharT, Traits > &os )
  {
     return os << "3[0m";
  }

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

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

或者,C 提供了使用#define 创建常量的可能性。

#define foreground_magenta "3[35m"