usar resueltos leer imprimir funciones ejercicios ejemplos como caracteres cadenas cadena arreglo c++ object reference const temporary

c++ - resueltos - imprimir cadena de caracteres en c



Imprimir una cadena a un objeto de flujo temporal en C++ (4)

Tengo un tipo especial de ostringstream al que estoy tratando de enviar el texto como un objeto temporal, pero estoy teniendo algunos problemas. Para ser claro, esto es esencialmente lo que quiero hacer:

ostringstream() << "PARTY DOWN!" << endl;

Ahora, antes de decir: "¡Pero Zack, ese código no tiene ningún valor! El objeto se destruye al final de la línea, ¿cómo sabrías si hiciera algo?", Escúchame. No trato de hacer esto con cadenas de caracteres ostring simples, sino más bien una clase derivada en la que el destructor realmente proporciona una ruta para que los datos salgan del objeto. Entonces, en realidad, se parece mucho más a esto:

specialstringstream() << "PARTY DOWN!" << endl;

Donde specialstringstream tiene un destructor que vuelca el texto en otro lugar.

No entraré en demasiados detalles sobre por qué hago esto. Tendrás que confiar en mí de que tiene sentido lo que tengo que hacer y se adapta muy bien a una base de códigos existente y gigantesca.

Aquí está el problema: cuando hago esto, todo se compila y se ejecuta, pero obtengo una dirección de puntero impresa a mi salida en lugar de "PARTY DOWN!" cuerda. ostream& operator<< (const void* val) que esto estaba sucediendo porque el operador elegido por el compilador para realizar la salida de flujo es ostream& operator<< (const void* val) , no ostream& operator<< (ostream& out, const char* s ) .

Tengo una vaga idea de por qué, pero no sé cómo solucionarlo. ¿Qué puedo hacer para obtener char * s para imprimir en una instancia temporal de un stringstream?

Aquí hay una versión corta del objeto SpecialStringStream que muestra el comportamiento:

class SpecialStringStream : public ostringstream { public: SpecialStringStream(ostream* regularStream) { regularStream_ = regularStream; } ~SpecialStringStream() { if (regularStream_ != NULL) (*regularStream_) << str(); } private: ostream* regularStream_; };

Cuando hago algo como: SpecialStringStream(someStreamPtr) << "PARTY DOWN!" << endl; SpecialStringStream(someStreamPtr) << "PARTY DOWN!" << endl; , Obtengo una dirección de puntero como "00444D60" en mi salida en lugar del mensaje.

EDITAR: dado que soy muy nuevo como usuario para responder a mi propia pregunta, esto es lo que he decidido gracias a todas las respuestas.

Se me ocurrió la siguiente solución, que funciona con Visual C ++ 8 y todos los demás compiladores que necesitaba. Creé un operador de plantilla que básicamente elimina un const SpecialStringStream de su constness, lo lanza como un ostream y permite que los operadores de ostream hagan lo suyo. ¡Siéntete libre de hacer trizas en los comentarios y advertirme de todos los errores potenciales horribles que he introducido!

template <class T> std::ostream& operator<<(const SpecialStringStream &o, T msg) { return static_cast<std::ostream&>(const_cast<SpecialStringStream&>(o)) << msg; }


La sobrecarga ostream& operator<< (ostream& out, const char*) no es viable porque su temporal no se ostream& referencia ostream& sin const. No hay mucho que puedas hacer al respecto (ya que no puedes convertir un valor r en un valor l) aparte de declarar una variable local y usar eso:

{ specialstringstream ss; ss << "Hello world" << std::endl; // OK, can bind to lvalue }

Posible solución: puede declarar otra sobrecarga que acepte una referencia rvalue:

std::ostream & operator<<(specialstringstream && o, const char * s) { return o << s; // note: *not* "std::move(o)" }


No desea implementar stringstream. Desea implementar un basic_streambuf que escriba en su cadena especial.

Las secuencias en sí son responsables del formateo y funciones similares; los streambufs son responsables de lo que finalmente se convierte en el sumidero de los datos.

Después de todo, todo un stringstream es un iostream, con un basic_stringbuf adjunto.


Tal vez hay alguna forma mejor, pero pensé en otra solución:

#include <iostream> #include <sstream> class LogClass { template <typename T> friend const LogClass& operator << (const LogClass& lc, const T& v); public: LogClass() : str(new std::ostringstream()) , refCount(new int(1)) {} LogClass(const LogClass& other) : str(other.str) { ++(*refCount); } ~LogClass() { --(*refCount); if (!*refCount) { delete refCount; std::cout << str->str() << std::endl; delete str; } } private: mutable std::ostringstream *str; int *refCount; LogClass& operator = (const LogClass&); }; template <typename T> const LogClass& operator << (const LogClass& lc, const T& v) { (*lc.str) << v; return lc; } int main(int , char**) { for (size_t i = 0; i < 10 ; ++i) { LogClass() << "PARTY DOWN! " << i; } }

Ejecutando con valgrind:

valgrind --tool = memcheck --leak-check = completo ./LogClass

== 16197 == Memcheck, un detector de errores de memoria

== 16197 == Copyright (C) 2002-2010, y GNU GPL''d, por Julian Seward et al.

== 16197 == Usando Valgrind-3.7.0.SVN y LibVEX; vuelva a ejecutar con -h para información de copyright

== 16197 == Comando: ./LogClass

== 16197 ==

FIESTA ABAJO! 0

FIESTA ABAJO! 1

FIESTA ABAJO! 2

FIESTA ABAJO! 3

FIESTA ABAJO! 4

FIESTA ABAJO! 5

FIESTA ABAJO! 6

FIESTA ABAJO! 7

FIESTA ABAJO! 8

FIESTA ABAJO! 9

== 16197 ==

== 16197 == RESUMEN DE HEPA:

== 16197 == en uso en la salida: 0 bytes en 0 bloques

== 16197 == uso total del montón: 40 allocs, 40 libres, 7,350 bytes asignados

== 16197 ==

== 16197 == Se liberaron todos los bloques de pila, no es posible ninguna filtración

== 16197 ==

== 16197 == Para los recuentos de errores detectados y reprimidos, vuelva a ejecutar con: -v

== 16197 == RESUMEN DEL ERROR: 0 errores de 0 contextos (suprimido: 15 de 8)

Eso es lo que quería, pero no es seguro para subprocesos . Usa shared_ptr de boost para que sea así.


aquí hay una solución que estoy usando:

#define STRM2STR(x) (dynamic_cast<std::ostringstream &>(std::ostringstream() << std::dec << x).str())

La inserción de std :: dec dará como resultado la llamada a ostream :: operator << (ios_base & (* pf) (ios_base &)) que devuelve ostream utilizable &