首页 > 解决方案 > 将 cout 输出推迟到下一个输出之前

问题描述

我有一些 C++ 控制台程序,它们会定期在输出的最后一行显示进度信息。

在写入下一个实际输出(或更新的进度信息)之前清除此进度线;这可能来自源中的许多不同地方,我目前正在清除每个地方的进度线,例如:

cout << clearline << "Some real output" << endl;
...
cout << clearline << "Some other real output" << endl;
...
cout << clearline << setw(4) << ++icount << ") " << ... << endl;
...
cout << clearline << "Progress info number " << ++iprog << flush;

在这里,'clearline' 是一些(系统相关的)字符串,例如 "\r\33[2K" 清除当前的最后一行。

我更喜欢更干净的东西,它将源更改本地化为将要清除的实际行,就像简单地:

cout << "Progress info number " << ++iprog << flush << defer_clearline;

其中'defer_clearline' 导致'clearline' 的写入被推迟到下一个cout 输出之前,无论发生在什么地方。然后我不需要在所有其他行上使用“clearline”。

我认为如果 'defer_clearline' 是一个操纵器,和/或使用 xalloc() 和 iword(),可能会这样做。但我没有设法得到任何有效的东西。是否有可能做这种事情,如果可以,怎么做?

2020-12-30:编辑以包括缺少的“冲洗”。

标签: c++

解决方案


你可以很容易地设置一个std::cout包装器:

// Declare the empty struct clear_line and instantiate the object cls
struct clear_line { } cls;

class out {
private:
    std::ostream &strm = std::cout;
    bool is_next_clear = false;
public:
    template <typename T>
    out& operator<<(const T& obj) {
        if(is_next_clear) {
            strm << std::endl << std::endl << std::endl; // clear logic
            is_next_clear = false;
        }
        
        strm << obj;
        return *this;
    }
    
    out& operator<<(const clear_line& _) {
        is_next_clear = true;
        return *this;
    }
};

这很简单地存储了一个is_next_clear布尔值,用于判断是否应该清除下一个常规输出。然后,在一般情况下(模板化operator<<()),我们运行您的清晰逻辑并在is_next_clear适用时翻转标志。然后像往常一样输出。

然后,operator<<()对于对象的情况, 被重载clear_line。所以如果其中一个被发送,我们知道翻转is_next_clear标志,但实际上不输出任何东西。

这是一个使用示例:

int main() {
    out o;
    o << "Some real output" << cls;
    o << "Some other real output";
    
    return 0;
}

这是在行动:https ://ideone.com/0Dzwlv


如果你想使用endl,你需要为它添加一个特殊的重载,因为这个答案表明:https ://stackoverflow.com/a/1134467/2602718

// this is the type of std::cout
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;

// this is the function signature of std::endl
typedef CoutType& (*StandardEndLine)(CoutType&);

// define an operator<< to take in std::endl
out& operator<<(StandardEndLine manip)
{
    // call the function, but we cannot return its value
    manip(strm);
    return *this;
}

现场示例:https ://ideone.com/ACUMOOo


推荐阅读