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"
我正在尝试更改控制台中文本的颜色。
我们应该使用配置文件从以下位置读取 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"