【问题标题】:C++ output to windows terminal using cout<<term_cc<color, default, attrib> outputs colors and attributes properly on Windows but not on Linux使用 cout<<term_cc<color, default, attrib> 到 Windows 终端的 C++ 输出在 Windows 上正确输出颜色和属性,但在 Linux 上不正确
【发布时间】:2014-11-18 08:57:01
【问题描述】:

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

在 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 系统上正确显示颜色,但我无法使用该方法获得属性。

我一直在阅读的所有内容仅与颜色有关,而不是颜色和属性,它们还使用 echo 命令和特定终端的硬编码颜色。这些将需要对我的所有代码进行重大更改,并导致它无法在 Windows 上运行,并且只能在 Linux 上运行,所以我试图避免这种情况。

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

【问题讨论】:

  • 什么是term_ccterm_fg?你在使用一些图书馆吗?如果是这样,则应在问题或标签中提及。
  • 您提供的代码中是指cout&lt;term_cc 还是cout&lt;&lt;term_cc
  • 添加了对混音家伙的所有抱歉。还有 cout
  • 您的词法分析器是否从文件中读取,如果确实如此,它是否正确解释了在 Windows 上换行符是 CRLF 而在 Linux 上通常是 LF 的事实?
  • 它从控制台获取输入,所以输入会显示出来所以。当它得到一个标记 时,它知道它是一个“标签”并解析出箭头,返回一个字符串“red”。 @MichaelPetch

标签: c++ linux parsing colors


【解决方案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]);

假设每个TAG 都存在于colorMapattribMap 中。但是如果标签是像"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 字符 - 它输出 NUL 作为假定控制台代码的一部分。

我检查了xtermkonsole 和 Linux 控制台,它们都忽略了NUL 字符。 (我相信这是预期的行为;像 VT-100 这样的 DEC 终端忽略了NULs,尽管在某些情况下您需要插入它们,因为如果之前的控制时间过长,终端也会忽略任何字符。)我不'不知道您使用的是什么终端仿真器,它很可能具有不同的行为,例如终止控制代码序列。 term_cc 首先输出属性,即使它是第三个参数,所以很可能NUL 属性会导致终端仿真器简单地打印;31;49m 之类的东西,而不是将前景色设置为红色。

其他一些错误:

  • 你永远不会弹出attribVect;只有colorVect。所以我看不到如何正确恢复属性。

  • 您不会将 colorVect 初始化为 DEFAULT_COLOR。因此,在弹出第一个标签后,您将从colorVect 中弹出(唯一的)元素,使其为空,然后调用colorVect.back(),如果colorVect 为空,则未定义。

    李>

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

【讨论】:

  • 即使在 Windows 上,我也看不到它真正正确工作。它可能会运行,但我怀疑您是否得到了预期的结果。
猜你喜欢
  • 2017-01-09
  • 2019-01-31
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
相关资源
最近更新 更多