使用cout输出到Windows终端&lt; <term_cc <color,default,=“”attrib =“”>在Windows上正确输出颜色和属性但不在Linux上输出</term_cc <color,>

时间:2014-09-24 01:34:51

标签: c++ linux parsing colors

以为我已经完成并准备提交这个小项目,直到我得到这个意想不到的曲线球。 目标是使用令牌词法分析器创建解析器。 实质上 <underline><red> R <green> G </green> <blue> B </blue> and back to red </red></underline> 将输出为:&#34; RGB并返回红色&#34;各自的颜色和属性。

在Windows上一切正常但是当我将它移到Linux系统时,它会输出颜色代码而不会发生任何事情。

#include <iostream>
#include <sstream>
#include <stack>
#include <map>
#include <cstdlib>
#include <vector> 
#include "cmd.h"
#include "Lexer.h" // you should make use of the provided Lexer
#include "term_control.h"
#include "error_handling.h"

using namespace std;

map<string, term_colors_t> colorMap;    
map<string, term_attrib_t> attribMap;
string display(const string& expression) 
{
if(validate(expression) == "VALID") {
Lexer lex;
Token tok;

vector<term_colors_t> colorVect;
vector<term_attrib_t> attribVect;

lex.set_input(expression);
while(lex.has_more_token()){
    tok = lex.next_token();
    string sTok = tok.value;
        if(tok.type == TAG && tok.value.at(0) != '/'){
            cout<<term_cc(colorMap[tok.value], DEFAULT_COLOR, attribMap[tok.value]);
            colorVect.push_back(colorMap[tok.value]);
            attribVect.push_back(attribMap[tok.value]);
        }
        if(tok.type == TAG && tok.value.at(0) == '/'){
        colorVect.pop_back();
        cout<<term_cc(colorVect.back(), DEFAULT_COLOR, attribVect.back());
        }
        if(tok.type != TAG){
            cout<<tok.value;
        }
    }
}
else if(validate(expression) != "VALID")    return validate(expression);
return "";

}

_

    cout<term_cc(Color, DEFAULT_COLOR, Attribute)

是隐藏问题的特定方法我一直在寻找并且似乎找不到合适的方法。

    cout<<term_fg(color)

该方法在Linux系统上正确显示颜色,但我没有该方法的属性。

我读过的所有东西都只涉及颜色而不是颜色和属性,他们也使用了回声命令和特定终端的硬编码颜色。这些都需要对我的所有代码进行严格更改,导致它无法在Windows上运行,只能在Linux上运行,所以我试图避免这种情况。

提前感谢您对这个问题的任何建议,我很感激,希望我能在12点之前得到这个!

1 个答案:

答案 0 :(得分:1)

我不清楚colorMapattribMap在哪里被初始化以及在什么值上,我只是在这里本能,但似乎关键colorMap的颜色和attribMap的键是属性。在这种情况下,underline不是colorMap中的密钥,而red不是attribMap中的密钥。

在您的计划中,您执行以下操作:

if(tok.type == TAG && tok.value.at(0) != '/'){
        cout<<term_cc(colorMap[tok.value], DEFAULT_COLOR, attribMap[tok.value]);

假设TAGcolorMap中都存在attribMap {}}。但是,如果标记是"red"之类的颜色,则(可能)仅在colorMap中,如果它是"underline"之类的属性,则它(可能)仅在attribMap中}。

现在,执行colorMap["underline"]会发生什么?在这里,C ++标准库的便利性可能有点不利,因为它默默地隐藏了一个错误。答案是将"underline"term_colors_t的默认值的映射添加到地图中,以便查找始终返回一些内容。 term_colors_t是一个枚举,因此其默认值为0 '0')。

现在,term_cc - 如果它与@MikePetch挖出的term_cc相同 - 不检查其参数的有效性;它只是假设它们是有效的ANSI数字('0''9',或者换句话说是48到57之间的数字,包括在内。)因为它没有检查它们,所以它只是输出包括它们在输出中,因为您(可能)使用属性参数0调用term_cc - 即NUL字符 - 它输出{{1作为假设的控制台代码的一部分。

我检查了NULxterm和Linux控制台,所有这些都忽略了konsole字符。 (我相信这是预期的行为;像VT-100这样的DEC终端忽略了NUL,虽然在某些情况下你需要插入它们,因为如果前一个控制花费太长时间,终端也会忽略任何字符。)我不知道您正在使用什么终端仿真器,并且它很可能具有不同的行为,例如终止控制代码序列。 NUL首先输出属性,即使它是第三个参数,因此term_cc属性可能会导致终端模拟器只打印NUL之类的内容而不是设置前景色为红色。

其他一些错误:

  • 你永远不会弹出;31;49m;只有1个}}。所以我不知道如何正确恢复这些属性。

  • 您不能将attribVect初始化为colorVect。因此,在弹出第一个标记后,您将从colorVect中弹出(仅)元素,将其留空,然后调用DEFAULT_COLOR,如果colorVectcolorVect.back(),则为colorVect空。

这些只是我在快速浏览代码时注意到的事情。可能还有其他问题。