Configuración del búfer interno utilizado por una secuencia estándar (pubsetbuf)

Estoy escribiendo una subrutina que necesita escribir datos en un búfer existente, y me gustaría usar la clase de stringstream para facilitar el formateo de los datos.

Inicialmente, utilicé el siguiente código para copiar el contenido de la transmisión en el búfer, pero me gustaría evitar esta solución ya que copia demasiados datos.

 #include  #include  void FillBuffer(char* buffer, unsigned int size) { std::stringstream message; message << "Hello" << std::endl; message << "World!" << std::endl; std::string messageText(message.str()); std::copy(messageText.begin(), messageText.end(), buffer); } 

Esto es cuando descubrí el streambuf::pubsetbuf() y simplemente volví a escribir el código anterior de la siguiente manera.

 #include  void FillBuffer(char* buffer, unsigned int size) { std::stringstream message; message.rdbuf()->pubsetbuf(buffer, size); message << "Hello" << std::endl; message << "World!" << std::endl; } 

Desafortunadamente, esto no funciona en la implementación de la biblioteca estándar de C ++ que se incluye con Visual Studio 2008; buffer permanece sin cambios.

Miré la implementación de pubsetbuf y resulta que literalmente “no hace nada”.

 virtual _Myt *__CLR_OR_THIS_CALL setbuf(_Elem *, streamsize) { // offer buffer to external agent (do nothing) return (this); } 

Esto parece ser una limitación de la implementación de la biblioteca estándar de C ++ dada. ¿Cuál es la forma recomendada de configurar una secuencia para escribir su contenido en un búfer determinado?

Después de investigar un poco más sobre este problema y analizar mi código, encontré una publicación que sugería el uso de una clase std::streambuf codificada a mano. La idea detrás de este código es crear un streambuf que inicialice sus internos para referirse al buffer dado. El código es el siguiente.

 #include  template  struct ostreambuf : public std::basic_streambuf > { ostreambuf(char_type* buffer, std::streamsize bufferLength) { // set the "put" pointer the start of the buffer and record it's length. setp(buffer, buffer + bufferLength); } }; 

Ahora, si miras mi código original , notarás que para empezar no necesitaba realmente un stringstream . Todo lo que realmente necesitaba era una forma de escribir en un búfer externo utilizando la biblioteca IOStream y std::ostream es un tipo mucho mejor para solucionar este problema. Por cierto, sospecho que así es como se implementa el tipo array_sink de Boost.IOStreams .

Aquí está el código modificado que usa mi tipo ostreambuf .

 #include  #include "ostreambuf.h" // file including ostreambuf struct from above. void FillBuffer(char* buffer, unsigned int size) { ostreambuf ostreamBuffer(buffer, size); std::ostream messageStream(&ostreamBuffer); messageStream << "Hello" << std::endl; messageStream << "World!" << std::endl; } 

Parece un trabajo para el estándar std :: strstream (oficialmente obsoleto, pero aún estándar). También puede consultar la biblioteca Boost.IOStream , array_sink , en particular.

Como dice el enlace publicado: “las implementaciones específicas pueden variar”.

¿No puede simplemente devolver el objeto std :: string y luego usar std :: string :: c_str () o std :: string :: data () en el punto donde se requiere el búfer char?

Alternativamente, use sprintf () de la biblioteca C, luego toda la operación puede completarse en el buffer pasado. Dado que de esa manera puede provocar un potencial desbordamiento del búfer y está utilizando Visual C ++, puede considerar sprintf_s