Using freopen() to print to file and screen

前端 未结 2 1382
不思量自难忘°
不思量自难忘° 2020-12-20 13:07

I am trying to use freopen() to print to a text file and the screen, but I am only achieving the printing to a file.

I was wondering if there was an easy to save the

相关标签:
2条回答
  • 2020-12-20 13:31

    The easy way in a UNIX-like environment is to use the shell command tee:

    $ my-program | tee output.txt
    

    will copy stdout to the terminal, and also to the file output.txt.


    If you have to do it in code, you could use your own output stream instead of cout, which forwards every operator<< to two (or more) ostreams. This feels nicer (to me) than mucking around with the C output file underlying the C++ ostream cout.

    #include <ostream>
    
    class Tee {
        std::ostream &first, &second;
    
        template<typename T> friend Tee& operator<< (Tee&, T);
    
    public:
        Tee(std::ostream &f, std::ostream &s) : first(f), second(s) {}
    };
    
    template <typename T>
    Tee& operator<< (Tee &t, T val)
    {
        t.first << val;
        t.second << val;
        return t;
    }
    

    Then, if you replace your freopen line with:

    std::ofstream outfile("file.txt");
    Tee tee(std::cout, outfile);
    

    you can just use tee << instead of cout <<.

    Note that you'll either need to pass tee into your functions, or make it a global for that to work.

    0 讨论(0)
  • I don't know a simple way to achieve that, but I've managed to solve this somehow.

    Using fstreams you can output to file the same way you can write to console.

    #include <fstream>
    
    int main()
    {
         std::ofstream f("file.txt");
         f << "something";
    }
    

    Now there's a point we can start: is there a way we can output to the console and file simultaneously?

    I've recently written stream demultiplexer to address that problem:

    #include <vector>
    #include <ostream>
    class stream_demultiplexer
    {
    private:
        typedef std::vector<std::ostream*> str_cont;
        str_cont d;
    public:
        stream_demultiplexer& put(std::ostream::char_type ch)
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (*it)->put(ch);
            return *this;
        }
    
        stream_demultiplexer& write(const std::ostream::char_type* s, std::streamsize count)
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (*it)->write(s, count);
            return *this;
        }
    
        stream_demultiplexer& flush()
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (*it)->flush();
            return *this;
        }
    
    
        template<typename T>
        stream_demultiplexer& operator<<( const T& obj )
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (**it) << obj;
            return *this;
        }
    
        stream_demultiplexer& operator<<(std::ios_base& (*func)(std::ios_base&))
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (**it) << func;
            return *this;
        }
    
        template<typename CharT, typename Traits>
        stream_demultiplexer& operator<<(std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) )
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (**it) << func;
            return *this;
        }
    
        stream_demultiplexer& operator<<(std::ostream& (*func)(std::ostream&) )
        {
            for(str_cont::iterator it = d.begin(); it != d.end(); ++it)
                (**it) << func;
            return *this;
        }
    
        void add_stream(std::ostream& ss)
        {
            d.push_back(&ss);
        }
    };
    

    You can use it like this:

    stream_demultiplexer spl;
    std::ofstream f("file.txt");
    spl.add_stream(f);
    spl.add_stream(std::cout);
    spl << 55 << " HELLO WORLD";
    

    My approach has advantage that manipulators and unformatted output works correctly:

    spl << 76 << " " << std::hex << 76 << std::endl;
    spl.put('a');
    spl.write("ABCDE", 5);
    
    0 讨论(0)
提交回复
热议问题