管道cout干扰cerr

时间:2015-10-11 13:34:54

标签: c++ stdin cout stderr

我为进度条写了一个标题。它包含以下功能:

/**
 * @brief advances the progress bar every time an interval of x
 *        function calls has been completed
 * @param current the current iteration
 * @param o the stream to write to
 */
inline void run(step current, sost& o=std::cerr)
{
    if(current%interval == 0 && !(current > max))
    {
        // do away with the cursor
        #ifdef UNIXLIKE
        printf("\e[?25l");
        #endif

        // fill line with background symbol
        for (int i = 0; i < PSD+lbracketSize; ++i) o << " ";
        for (unsigned i = 0; i < pres; ++i) o << pre;
        o << rbracket << "\r";
        o.flush();

        // calculate percentage and make a string of it
        float prct = ((float)current/max)*100;
        sstr strprct = helper::to_string((int)prct);
        // get percantge to length of three
        if (helper::utf8_size(strprct) < 2) strprct = " "+strprct;
        if (helper::utf8_size(strprct) < 3) strprct = " "+strprct;

        // print percentage and bar
        o << "[" << strprct << "% ] " << lbracket;
        for (auto i = pbar.begin(); i != pbar.end(); ++i) o << *i;

        o << "\r";
        o.flush();

        pbar.push_back(bar);
    }
    if(current>=max-1)
    {
        cancel();
    }
}

工作正常。如您所见,我将进度条发送给stderr。这背后的想法是,我可以管道我的程序的输出,这是stdout,而没有捕获stderr上的进度条。但在实践中它并不常用。虽然进度条没有按预期被管道捕获,但\r命令似乎没有生效,因为条形码是用新行写的,而不是保持在同一行,就像它一样我不管道stdout。这是为什么?对我没有任何意义。

所以,通常栏看起来像这样:

[ 37% ] ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

当我将stdout传输到一个文件时,我在终端上找到了无数行:

        ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

1 个答案:

答案 0 :(得分:3)

如果重定向stdout,请检查以下代码是否对您不起作用:

#include <iostream>

int main(int argc, char ** argv)
{
    std::cerr << "Hello,\rWorld!\n";
    return 0;
}

我对您的代码有一些建议:

  1. printf("\e[?25l");应更改为o << "\e[?25l"。你不应该将stdio.hiostream混合,你应该将控制序列输出到stderr。

  2. stderr也可以重定向。您需要检查流是否为终端并检测终端的功能。实施是特定于系统的。可以找到其中一个解决方案herethis link也可能会有所帮助。

  3. 您可以使用tty命令获取终端名称并写入终端,强行输出到终端。