Thread: Output string to both console and file at the same time

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    34

    Output string to both console and file at the same time

    Hi guys,

    I'm new to c++, I'm trying to print a string to both console and a file at the same time.

    I know this works:

    Code:
    //This is just an example
    cout<<"I want to print "<<3+4<<" in to a file."<<endl;
    ofstream out("file.txt");
    out<<"I want to print "<<3+4<<" in to a file."<<endl;
    but is there a better way to do it without repeat the code? Because the actual stuff I'm going to print is more complicated than the example above.

    thanks!

  2. #2
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Actually, if it were me, I would put everything into a stringstream, and output the stringstream to both the file and standard out.

  3. #3
    Use this: dudeomanodude's Avatar
    Join Date
    Jan 2008
    Location
    Hampton, VA
    Posts
    391
    overload ostream
    Ubuntu Desktop
    GCC/G++
    Geany (for quick projects)
    Anjuta (for larger things)

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Create your own streambuf that outputs to two internal streambufs...
    Code:
    #include <iostream>
    #include <fstream>
    #include <streambuf>
    
    //------------------------------------------------------------------------------
    
    template <class charT, class traits = std::char_traits<charT> >
    class basic_teebuf : public std::basic_streambuf<charT, traits>
    {
    public:
        typedef charT char_type;
        typedef typename traits::int_type int_type;
        typedef typename traits::pos_type pos_type;
        typedef typename traits::off_type off_type;
        typedef traits traits_type;
        typedef std::basic_streambuf<charT, traits> streambuf_type;
    
    private:
        streambuf_type *m_sbuf1;
        streambuf_type *m_sbuf2;
        char_type *m_buffer;
    
        enum {BUFFER_SIZE = 4096 / sizeof(char_type)};
    
    public:
        basic_teebuf(streambuf_type *sbuf1, streambuf_type *sbuf2)
            : m_sbuf1(sbuf1), m_sbuf2(sbuf2), m_buffer(new char_type[BUFFER_SIZE])
        {
            setp(m_buffer, m_buffer + BUFFER_SIZE);
        }//constructor
    
        ~basic_teebuf()
        {
            pubsync();
            delete[] m_buffer;
        }//destructor
    
    protected:
        virtual int_type overflow(int_type c = traits_type::eof())
        {
            // empty our buffer into m_sbuf1 and m_sbuf2
            std::streamsize n = static_cast<std::streamsize>(pptr() - pbase());
            std::streamsize size1 = m_sbuf1->sputn(pbase(), n);
            std::streamsize size2 = m_sbuf2->sputn(pbase(), n);
            if (size1 != n || size2 != n)
                return traits_type::eof();
    
            // reset our buffer
            setp(m_buffer, m_buffer + BUFFER_SIZE);
    
            // write the passed character if necessary
            if (!traits_type::eq_int_type(c, traits_type::eof()))
            {
                traits_type::assign(*pptr(), traits_type::to_char_type(c));
                pbump(1);
            }//if
    
            return traits_type::not_eof(c);
        }//overflow
    
        virtual int sync()
        {
            // flush our buffer into m_sbuf1 and m_sbuf2
            int_type c = overflow(traits_type::eof());
    
            // checking return for eof.
            if (traits_type::eq_int_type(c, traits_type::eof()))
                return -1;
    
            // flush m_sbuf1 and m_sbuf2
            if (m_sbuf1->pubsync() == -1 || m_sbuf2->pubsync() == -1)
                return -1;
    
            return 0;
        }//sync
    };//basic_teebuf
    
    typedef basic_teebuf<char>    teebuf;
    typedef basic_teebuf<wchar_t> wteebuf;
    
    //------------------------------------------------------------------------------
    
    template <class charT, class traits = std::char_traits<charT> >
    struct scoped_basic_streambuf_assignment
    {
        typedef std::basic_ostream<charT, traits> ostream_type;
        typedef std::basic_streambuf<charT, traits> streambuf_type;
    
        ostream_type &m_s;
        streambuf_type *m_orig_sb;
    
        scoped_basic_streambuf_assignment(ostream_type &s, streambuf_type *new_sb) 
            : m_s(s)
        {
            m_orig_sb = m_s.rdbuf(new_sb);
        }//constructor
    
        ~scoped_basic_streambuf_assignment()
        {
            m_s.rdbuf(m_orig_sb);
        }//destructor
    };//scoped_basic_streambuf_replacement
    
    typedef scoped_basic_streambuf_assignment<char>    scoped_streambuf_assignment;
    typedef scoped_basic_streambuf_assignment<wchar_t> scoped_wstreambuf_assignment;
    
    //------------------------------------------------------------------------------
    
    using namespace std;
    
    int main()
    {
        ofstream file("data.txt");
    
        // tbuf will write to both file and cout
        teebuf tbuf(file.rdbuf(), cout.rdbuf());
    
        // replace cout's streambuf with tbuf
        scoped_streambuf_assignment ssa(cout, &tbuf);
    
        cout << "Hello World" << endl;
    
        return 0;
    }//main
    gg

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Actually, if it were me, I would put everything into a stringstream, and output the stringstream to both the file and standard out.
    My exact solution for a similar problem I had a couple of weeks ago. Worked like a charm.

  6. #6
    ‡ †hë Ö†hÈr sîÐè ‡ Nor's Avatar
    Join Date
    Nov 2001
    Posts
    299
    Codeplug code is a little complex. you said your new so try this
    Code:
    #include <iostream> //console commands
    #include <fstream>  // file commands
    //Global stuff - bad way to do this<<
    std::fstream file;
    void output(char* string);
    int main(void){
        char TEXT[] = "some debuging stuff to look at\n Nor is Great."
        file.open("testfile", std::ios::out);
        if( !file.is_open()) // please note the '!'. it is very inportant to check for errors.
            exit(1);            //could not open file
        output(&TEXT[0])l
        file.close();
        return 0;
    }   
    void output(char* string){
     std::cout << string << std::endl;
     file << string << std::endl;
    //or file.write(string, strlen(string));
    }
    Try to help all less knowledgeable than yourself, within
    the limits provided by time, complexity and tolerance.
    - Nor

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Code:
    ./myprogram | tee outfile.txt
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. getting a string from console and put it in a file
    By estarapapax in forum C Programming
    Replies: 2
    Last Post: 08-17-2008, 12:42 AM
  2. Replies: 4
    Last Post: 03-29-2006, 04:36 PM
  3. Something is wrong with this menu...
    By DarkViper in forum Windows Programming
    Replies: 2
    Last Post: 12-14-2002, 11:06 PM
  4. Recording console window output to a text file?
    By HolySmiter in forum C++ Programming
    Replies: 3
    Last Post: 02-24-2002, 03:13 PM