2011-04-16 10 views
15

¿Existe una manera rápida y fácil de obtener un formato similar a Sprintf al construir una std :: string? Algo así como ...Cadenas de formato rápido en C++

std::string foo("A number (%d) and a character (%c).\n", 18, 'a'); 
+0

Echa un vistazo a mi solución. Esa es la solución de Estilo C++. No depende de la cadena de formato de estilo C que implica '% d' y'% c', como boost. – Nawaz

Respuesta

15

No incorporado en el constructor de la cadena, pero es posible que desee comprobar hacia fuera boost format. Es un formato de cadena de estilo sprintf más seguro. Con él se puede al menos hacer esto:

std::string foo = 
    boost::str(boost::format("A number (%d) and a character (%c)\n") % 18 % 'a'); 
+0

¡Está perfectamente bien, gracias! – slezica

+0

Coloque un 'uint8_t' en lugar del literal' 18' - y, voila, la salida de Boost está totalmente reventada: recibirá dos caracteres en lugar de un número con el carácter. –

10

He escrito una clase stringbuilder que se puede utilizar y creo que es mejor que boost::format como a diferencia de ella, stringbuilder no utiliza C-estilo de formato de cadena como %d , %c. etc.

Aquí es cómo stringbuilder te pueden ayudar de una sola línea:

std::string s=stringbuilder() << "A number " << 18 <<" and a character " <<'a'; 

La implementación de stringbuilder es muy simple:

struct stringbuilder 
{ 
    std::stringstream ss; 
    template<typename T> 
    stringbuilder & operator << (const T &data) 
    { 
     ss << data; 
     return *this; 
    } 
    operator std::string() { return ss.str(); } 
}; 

demo en Ideone: http://ideone.com/J9ALB


Acabo de escribir el siguiente blog describiendo g las muchas formas diferentes del uso de stringbuilder.

+7

+1 Gracias por compartir :), pero me gusta un poco la sintaxis de formato C-style. Personalmente encuentro el enfoque "este es mi hilo, reemplazando tokens apropiados" para formatear más cómodamente que ensamblarlos pieza por pieza. – slezica

+0

@Santiago: Pero sabes que los formateos C-Style no son seguros, es por eso que C++ no los usa, y en su lugar surgieron 'cout' y' cin', y otras clases de flujo que son seguras. – Nawaz

+4

@Nawaz: que es también la razón por la cual se desarrolló el formato boost ::, que tiene formato similar a printf y es tan seguro como iostream. –

1

Cómo sobre éste, se utiliza printf directamente:

#include <stdio.h> 
#include <stdarg.h> 

std::string format(const char *fmt, ...) 
{ 
    va_list ap; 
    va_start(ap, fmt); 

    const size_t SIZE = 512; 
    char buffer[SIZE] = { 0 }; 
    vsnprintf(buffer, SIZE, fmt, ap); 

    va_end(ap); 

    return std::string(buffer); 
} 
+0

Es mejor mirar el valor de retorno 'vsnprintf' para asignar un búfer del tamaño correcto, en lugar de cortarlo en 512 caracteres. O use ['asprintf'] (http://linux.die.net/man/3/vasprintf) en Linux. Además, use [atributos de funciones gcc-style] (http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html) para que pueda obtener algún tipo de seguridad sobre los argumentos. – poolie

7

El C++ Format library proporciona una sprintf aplicación segura que devuelve una cadena:

std::string foo(fmt::sprintf("A number (%d) and a character (%c).\n", 18, 'a')); 

Este la biblioteca también es compatible con P str.format sintaxis de ython:

std::string foo(fmt::format("A number ({}) and a character ({}).\n", 18, 'a')); 

Es similar en propósito a impulsar formato, pero es much faster, bastante pequeña y no tiene dependencias externas distintas de la biblioteca estándar de C++.

Descargo de responsabilidad: soy el autor de esta biblioteca.