Get previous cout text to string

Need to get previous cout text to string.
Need to keep cout for debug
Tried sstring buffer, but it can replace cout
Use a program like tee from the shell
https://man7.org/linux/man-pages/man1/tee.1.html
Example:
./program | tee stdout.txt

Alternatively, write debug output to standard error (with std::cerr or std::clog) and redirect it to a file.
https://linux.die.net/man/1/bash (See section REDIRECTION)
Example:
./program 2> stderr.txt

To solve the problem using C++ code, the behavior of std::cout can be changed by replacing its underlying stream buffer. For example see this thread:
https://cplusplus.com/forum/general/97966/
Last edited on
Is there alternative for tee on Windows?
There should be a direct Windows-equivalent, tee.exe, available somewhere on the web, but the one website I found that might have a link to it seems to be down. I have it locally on my machine. Try searching for something like "unix tools tee windows".
Last edited on
I found analog for Windows for tee, but how to get terminal (output text) contains?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <sstream>

namespace utility
{
    template < typename C, typename T = std::char_traits<C> >
    struct basic_teebuf : public std::basic_streambuf<C,T>
    {
        using streambuf_type = std::basic_streambuf<C,T> ;
        using int_type = typename T::int_type ;

        basic_teebuf( streambuf_type* buff_a, streambuf_type* buff_b )
            : first(buff_a), second(buff_b) {}

        protected:
            virtual int_type overflow( int_type c ) override
            {
                const int_type eof = T::eof() ;
                if( T::eq_int_type( c, eof ) ) return T::not_eof(c) ;
                else
                {
                    const auto ch = T::to_char_type(c) ;
                    return T::eq_int_type( first->sputc(ch), eof ) ||
                           T::eq_int_type( second->sputc(ch), eof ) ? eof : c ;
                }
            }

            virtual int sync() override { return !first->pubsync() && !second->pubsync() ? 0 : -1 ; }

        private:
            streambuf_type* first ;
            streambuf_type* second ;
    };

    using teebuf = basic_teebuf<char> ;
}

int main()
{
    // set up a tee to also send output of stdout to a string buffer
    std::stringbuf sbuf( std::ios_base::out ) ;
    const auto oldbuf = std::cout.rdbuf() ;
    utility::teebuf tbuf( oldbuf, std::addressof(sbuf) ) ;
    std::cout.rdbuf( std::addressof(tbuf) ) ;
    
    std::cout << "line #1: " << 1234 << '\n'
              << "line #2: " << 56.78 << '\n'
              << "line #3: " << 999 << ' ' << 999.999 << '\n' << std::flush ;

    std::cout.rdbuf(oldbuf) ; // restore old behaviour of cout

    const std::string str = sbuf.str() ; // retrieve the string from the string buffer
    
    std::cout << "\ntext in string str\n------------------\n" << str ;
}

http://coliru.stacked-crooked.com/a/a153648df1b8403b
for windows:

https://learn.microsoft.com/en-us/windows/console/readconsoleoutput?redirectedfrom=MSDN

I have not used it, but it sounds like it could do what you want.

you can also just make your own stuff, keeping the last output string every time you write out.
I 've tried win API variant but it's not clear for me
How to get data to string?
If print unichar set it just prints its standard and array members

Can you give me a clue how to get data from terminal and put it to string using link https://learn.microsoft.com/en-us/windows/console/reading-and-writing-blocks-of-characters-and-attributes?redirectedfrom=MSDN
Last edited on
I found the way how to output data with tee to text, but there is no terminal output string yet
Please advise
Added
I have gcc version 4.9.1, can not use streambuf_type
Last edited on
C++98, credits to JLBorges
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <sstream>

namespace utility
{
    template < typename C, typename T = std::char_traits<C> >
    struct basic_teebuf : public std::basic_streambuf<C,T>
    {
        typedef std::basic_streambuf<C,T> streambuf_type;
        typedef typename T::int_type int_type;

        basic_teebuf( streambuf_type* buff_a, streambuf_type* buff_b )
            : first(buff_a), second(buff_b) {}

        protected:
            virtual int_type overflow( int_type c )
            {
                const int_type eof = T::eof() ;
                if( T::eq_int_type( c, eof ) ) return T::not_eof(c) ;
                else
                {
                    const typename T::char_type ch = T::to_char_type(c) ;
                    return T::eq_int_type( first->sputc(ch), eof ) ||
                           T::eq_int_type( second->sputc(ch), eof ) ? eof : c ;
                }
            }

            virtual int sync() { return !first->pubsync() && !second->pubsync() ? 0 : -1 ; }

        private:
            streambuf_type* first ;
            streambuf_type* second ;
    };

    typedef basic_teebuf<char> teebuf;
}

int main()
{
    // set up a tee to also send output of stdout to a string buffer
    std::stringbuf sbuf( std::ios_base::out ) ;
    std::streambuf* const oldbuf = std::cout.rdbuf() ;
    utility::teebuf tbuf( oldbuf, &sbuf ) ;
    std::cout.rdbuf( &tbuf ) ;
    
    std::cout << "line #1: " << 1234 << '\n'
              << "line #2: " << 56.78 << '\n'
              << "line #3: " << 999 << ' ' << 999.999 << '\n' << std::flush ;

    std::cout.rdbuf(oldbuf) ; // restore old behaviour of cout

    const std::string str = sbuf.str() ; // retrieve the string from the string buffer
    
    std::cout << "\ntext in string str\n------------------\n" << str ;
}
Last edited on
Topic archived. No new replies allowed.