Eigener cout Befehl



  • Hallo zusammen,

    ich würde gerne meine eigene Output Funktion schreiben.

    Die bei dem Aufruf funkt(<wie auch immer formatierter Output>)
    den Output: "Task <nr>: <wie auch immer formatierter Output>"
    Ausgibt.

    void myPrintf( const char * format, ... )
    {
    #ifdef PARALLEL
      printf( "Task %03d: ", ThisTask.number );
    #endif
      va_list args;
      va_start( args, format );
      vprintf( format, args );
      va_end( args );
    }
    

    Es wäre nur schön das ganze nun für cont zu Erzeugen.
    So dass man den << Operator nutzen und weiterhin überladen kann.
    um zum Beispiel auch eigene Formate wie komplexe Zahlen oder Datum etc. Formatiert ausgeben kann.
    Also dass ich weiterhin:

    ostream& operator<<(ostream& Stream, complex& Z)
    {
        return Stream << Z.real << '+i' << Z.imag;
    }
    

    mit meinem neuen Output:

    MYIO::cout<< Z << "beliebiger string" << <anderer Datentyp> << std::end
    

    verwenden kann.

    wenn die Funktion dann auch noch am Ende auch noch selbstständig einen Zeilenumbruch macht, wäre das natürlich auch schön.


  • Mod

    Da gibt's sicher viele Möglichkeiten, ich würde da mal spontan meinen alten Musterstreambuf reaktivieren und in dessen Overflowfunktion die Lognachricht ausgeben:

    #include <streambuf>
    #include <ios>    
    #include <thread>
    #include <sstream>
    
    class seppjs_thread_logger_streambuf : public std::streambuf
    {
    public:
      seppjs_thread_logger_streambuf(std::ios& in) : in(in), buf (in.rdbuf()), newline(true)
      {
        in.rdbuf(this);
      }
      ~seppjs_thread_logger_streambuf()
      {
        in.rdbuf(buf);
      }
      seppjs_thread_logger_streambuf(const seppjs_thread_logger_streambuf&) = delete;
      seppjs_thread_logger_streambuf& operator=(const seppjs_thread_logger_streambuf&) = delete;
    
    private:
      std::ios& in;
      std::streambuf* buf;
      bool newline;
    
    protected:
      virtual int_type overflow(int_type c)
      {
        if(newline)
          {
            std::stringstream message;
            message << "Task " << std::this_thread::get_id() << ": ";
            buf->sputn(message.str().data(), message.str().size());
            newline = false;
          }
        if (traits_type::eq_int_type(c, traits_type::to_int_type('\n')))
          newline = true;
        buf->sputc(c);
        return c;  
      }
    };
    
    // Beispielanwendung
    #include <iostream>
    
    void function()
    {
      std::cout << "Blah\nBlupp\nBäh\n";  
    }
    
    int main()
    {
      seppjs_thread_logger_streambuf foo(std::cout);
      std::thread t1(function), t2(function);
    
      t1.join();
      t2.join();
    }
    

    edit: ideone-Link: http://ideone.com/i6YeBH

    Dazu sei noch angemerkt, dass printf auf manchen Systemen (mindestens solchen mit glibc) garantiert threadsicher ist. Ausgaben über std::cout aber nicht*! Dies ist daher auch eine gute Gelegenheit, noch einen Mutex vor die Ausgabe zu schalten. Das überlasse ich aber dem geneigten Leser zur Übung.

    *: In dem Sinne, dass Streamausgabefunktionen zwar reentrant sind, aber dass gleichzeitige Ausgaben dann eventuell wild miteinander verquirlt werden. Bei printf ist bei der glibc hingegen garantiert, dass ein printf komplett abgearbeitet wird, bevor das nächste dran kommt.


Log in to reply