Pregunta

Quiero utilizar este fragmento de de Mr-Edd iostreams artículo imprimir std :: obstruye alguna parte.

#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;
}

Por lo tanto, en un mainloop, voy a hacer algo como

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

Esta es la docs ostringstream pero estoy teniendo problemas para entender la mejor manera de hacer esto. Tengo un método que muestra el texto, sólo quiero llamarlo con cualquier dato en la ostringstream.

¿Cuál es la mejor manera más fácil / para conseguir cualquier cosa enviada a std :: estorbo redirigido a un método de mi elección? es como anteriormente, y enviando al mismo tiempo! parte eof (no sé cómo), o hay una mejor manera, dicen que por la sobrecarga de algunos 'comprometerse' operador en alguna parte que llama mi método? Estoy buscando alojamiento para una rápida y fácil, yo realmente no quiero empezar a definir los sumideros y con tal iostreams impulso, ya que el artículo no -. Eso está muy por encima de mi cabeza

¿Fue útil?

Solución

Os animo a mirar a Boost.IOStreams . Parece para adaptarse a su caso de uso muy bien, y su uso es sorprendentemente simple:

#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;
}

Otros consejos

pensar desea extraer el texto de la ostream mientras no está vacío. Se podría hacer algo como esto:

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

Quiero saber si esto no es lo que quería.

Por supuesto, la mejor solución es eliminar los intermediarios y tener una nueva streambuf ir donde realmente que desee, sin necesidad de sonda más tarde. algo como esto (en cuenta que esto lo hace por cada char, pero hay un montón de opciones de almacenamiento en búfer streambufs también):

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;

}

que necesitaba para agarrar salidas a std :: cout y std :: cerr de bibliotecas de terceros y los de registro mediante log4cxx, y que todavía conserva las salidas originales.

Esto es lo que ocurrió. Es bastante recta hacia adelante:

  • se sustituye la antigua memoria intermedia de un ostream (como std :: cout) con mi propia clase de modo que consiga el acceso a lo que cada vez se escribe en ella.

  • También se crea un nuevo objeto std :: ostream con la vieja memoria intermedia de modo que pueda continuar recibiendo la salida a mi consola, además de enviarlo a mi registrador. Que me parece tipo de práctica.

Código:

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;
};

A continuación, se usa:

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;

En el ejemplo log4cxx debe invalidar desbordamiento () y sync () de lo contrario el badbit siempre se establece después de recibir el primer flujo.

Ver: 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;
}

Si lo que desea es obtener el contenido de la ostringstream, a continuación, utilizar su miembro de str (). Por ejemplo:

string s = oss.str();    
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top