2

I want to check whether output is written to the standard output (through cout) in a certain part of my program.

What I found is a way to block any output by changing the streambuf of cout. (here:C++: Redirecting STDOUT). That is interesting and first I thought it might help. I found the following code example (source: answer to C++: Redirecting STDOUT)

// Redirect cout.
streambuf* oldCoutStreamBuf = cout.rdbuf();
ostringstream strCout;
cout.rdbuf( strCout.rdbuf() );

// This goes to the string stream.
cout << "Hello, World!" << endl;

// Restore old cout.
cout.rdbuf( oldCoutStreamBuf );

// Will output our Hello World! from above.
cout << strCout.str();

So I can just check whether strCout.str() is a string with 1 or more characters by checking its size.

But what if I do not want to delay the output significantly? So I do not want to save all output in my own ostringstream, wait until I checked whether there was output at the end of my program and then print all the output shortly before my programm ends. I just want to know, whether there was output in a certain part of my program.

Example:

main {
bool wasthereoutput=false;

function1();
function2();
startoutputcheckhere();
function3();
function4();
endoutputcheckhere();
therewasoutput=wasthereoutput();

if therewasoutput{

//do something
}

I don't want to change anything in function3 or function4. I do not want to delay any output generated by those functions until i call endoutputcheckhere() or even wasthereoutput(). I just want to know if there was any output going to std output through cout.

Community
  • 1
  • 1

1 Answers1

3

You can create a stream buffer which both collects the written characters for later and also forwards them to another stream buffer, e.g., the one used by std::cout. A simple implementation of this approach could look like this:

class savebuf:
    public std::streambuf {
    std::streambuf* sbuf;
    std::string     save;
    int overflow(int c) {
         if (!traits_type::eq_int_type(c, traits_type::eof()) {
             save.push_back(traits_type::to_char_type(c);
             return sbuf->sputc(c);
         }
         else {
             return traits_type::not_eof(c);
         }
    }
    int sync() { return sbuf->pubsync(); }
public:
    savebuf(std::streambuf* sbuf): sbuf(sbuf) {}
    std::string str() const { return save; }
};

int main() {
     std::streambuf* coutbuf = std::cout.rdbuf();
     savebuf sbuf(coutbuf);
     std::cout.rdbuf(&sbuf);
     std::cout << "Hello, world\n";
     std::cout.rdbuf(coutbuf); // restore the original stream buffer
     std::cout << "saved \"" << sbuf.str() << "\"\n";
}

Note that you should restore std::cout's stream buffer as the stream buffer is flushed (i.e. pubsync() is called on it) when std::cout is sort of destroyed.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380