Frage

Ich möchte diese Schnipsel verwenden, um von Mr-Edd des iostreams Artikel std drucken :: irgendwo verstopfen.

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

int main()
{
    std::ostringstream oss;

    // Make clog use the buffer from oss
    std::streambuf *former_buff =
        std::clog.rdbuf(oss.rdbuf());

    std::clog << "This will appear in oss!" << std::flush;

    std::cout << oss.str() << '\\n';

    // Give clog back its previous buffer
    std::clog.rdbuf(former_buff);

    return 0;
}

so, in einem mainloop, werde ich so etwas wie

tun
while (! oss.eof())
{
    //add to window text somewhere
}

Hier ist der ostringstream docs aber ich habe Probleme zu verstehen, die besten Art und Weise, dies zu tun. Ich habe eine Methode, die den Text anzeigt, ich es einfach anrufen will mit allen Daten im Ostringstream.

Was ist der einfachste / beste Weg, etwas zu bekommen geschickt ein Verfahren meiner Wahl umgeleitet std :: Clog? wie oben ist es, und füllen Sie das während! eof Teil (nicht sicher, wie), oder gibt es eine bessere Art und Weise, etwa durch einige ‚begehen‘ Betreiber irgendwo Überlastung, die meine Methode aufruft? Ich bin loking für schnell und einfach, ich möchte wirklich nicht definieren, Waschbecken und solche mit Boost iostreams starten, wie der Artikel tut -. Das Zeug ist Art und Weise über den Kopf

War es hilfreich?

Lösung

Ich möchte Sie ermutigen, betrachten Boost.IOStreams . Es scheint, Ihren Anwendungsfall gut zu passen, und es verwendet, ist überraschend einfach:

#include <boost/iostreams/concepts.hpp> 
#include <boost/iostreams/stream_buffer.hpp>
#include <iostream>

namespace bio = boost::iostreams;

class MySink : public bio::sink
{
public:
    std::streamsize write(const char* s, std::streamsize n)
    {
        //Do whatever you want with s
        //...
        return n;
    }
};

int main()
{
    bio::stream_buffer<MySink> sb;
    sb.open(MySink());
    std::streambuf * oldbuf = std::clog.rdbuf(&sb);
    std::clog << "hello, world" << std::endl;
    std::clog.rdbuf(oldbuf);
    return 0;
}

Andere Tipps

I denken Sie möchten den Text aus dem Ostream ziehen, während sie nicht leer ist. Man könnte so etwas tun:

std::string s = oss.str();
if(!s.empty()) {
    // output s here
    oss.str(""); // set oss to contain the empty string
}

Lassen Sie mich wissen, ob dies ist nicht das, was Sie wollten.

Natürlich ist die bessere Lösung ist die Mitte des Menschen zu entfernen und ein neues haben streambuf zu gehen, wohin du wirklich will es, keine Notwendigkeit, später zu untersuchen. so etwas wie diese (beachten Sie, dass dies macht es für jedes Zeichen, aber es gibt genügend Puffermöglichkeiten in streambufs auch):

class outbuf : public std::streambuf {
public:
    outbuf() {
        // no buffering, overflow on every char
        setp(0, 0);
    }

    virtual int_type overflow(int_type c = traits_type::eof()) {
        // add the char to wherever you want it, for example:
        // DebugConsole.setText(DebugControl.text() + c);
        return c;
    }
};

int main() {
    // set std::cout to use my custom streambuf
    outbuf ob;
    std::streambuf *sb = std::cout.rdbuf(&ob);

    // do some work here

    // make sure to restore the original so we don't get a crash on close!
    std::cout.rdbuf(sb);
    return 0;

}

Ich brauchte Ausgänge zu greifen std :: cout und std :: cerr von Bibliotheken von Drittanbietern und melden Sie sich mit ihnen log4cxx, und immer noch die ursprünglichen Ausgaben behalten.

Das ist, was ich kam mit. Es ist ziemlich geradlinig:

  • Ich ersetze den alten Puffer eines ostream (wie std :: cout) mit meiner eigenen Klasse, damit ich Zugang zu bekommen, was jemals geschrieben steht.

  • Außerdem erstellen ich ein neues std :: ostream Objekt mit dem alten Puffer, so dass ich auch weiterhin die Ausgabe auf meine Konsole zu bekommen, außer es zu meinem Logger senden. Was ich finde Art praktisch.

Code:

class intercept_stream : public std::streambuf{
public:
    intercept_stream(std::ostream& stream, char const* logger):
      _logger(log4cxx::Logger::getLogger(logger)),
      _orgstream(stream),
      _newstream(NULL)
    {
        //Swap the the old buffer in ostream with this buffer.
        _orgbuf=_orgstream.rdbuf(this);
        //Create a new ostream that we set the old buffer in
        boost::scoped_ptr<std::ostream> os(new std::ostream(_orgbuf));
        _newstream.swap(os);
    }
    ~intercept_stream(){
        _orgstream.rdbuf(_orgbuf);//Restore old buffer
    }
protected:
    virtual streamsize xsputn(const char *msg, streamsize count){
        //Output to new stream with old buffer (to e.g. screen [std::cout])
        _newstream->write(msg, count);
        //Output to log4cxx logger
        std::string s(msg,count);
        if (_logger->isInfoEnabled()) {
            _logger->forcedLog(::log4cxx::Level::getInfo(), s, LOG4CXX_LOCATION); 
        }
        return count;
    }
private:
    log4cxx::LoggerPtr _logger;
    std::streambuf*    _orgbuf;
    std::ostream&      _orgstream;
    boost::scoped_ptr<std::ostream>  _newstream;
};

Dann, es zu benutzen:

std::cout << "This will just go to my console"<<std::endl;
intercept_stream* intercepter = new intercept_stream(std::cout, "cout");
std::cout << "This will end up in both console and my log4cxx logfile, yay!" << std::endl;

Für das log4cxx Beispiel müssen Sie überschreiben Überlauf () und sync () ansonsten der badbit ist immer gesetzt, nachdem erste Strom empfangen wird.

Siehe auch: http://groups.google.com/group /comp.lang.c++.moderated/browse_thread/thread/fd9d973282e0a402/a872eaedb142debc

InterceptStream::int_type InterceptStream::overflow(int_type c)
{
    if(!traits_type::eq_int_type(c, traits_type::eof()))
    {
        char_type const t = traits_type::to_char_type(c);
        this->xsputn(&t, 1);
    }
    return !traits_type::eof();
}

int InterceptStream::sync()
{
    return 0;
}

Wenn Sie nur den Inhalt des Ostringstream erhalten möchten, verwenden Sie dann seine str () Mitglied. Zum Beispiel:

string s = oss.str();    
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top