2008-10-10 17 views
531

Pensé que esto sería muy simple pero presenta algunas dificultades. Si tengoCómo concatenar un std :: string y un int?

std::string name = "John"; 
int age = 21; 

¿Cómo ellos se combinan para obtener una única cadena ?

+9

@Rubenvb: llegué aquí a través de Google cuando se trata de hacer exactamente lo que el autor de la pregunta está pidiendo. El propósito es transferir conocimiento, y la pregunta pregunta qué pedirían otras personas. Evidentemente, del conteo de votos de la pregunta, esta es una pregunta común, expresada de la manera en que los consultadores la ven. –

+1

posible duplicado de [¿Cómo se agrega un int a una cadena en C++?] (Http://stackoverflow.com/questions/64782/how-do-you-append-an-int-to-a-string-in -c) – Meysam

+0

Permítanme agregar a esto: probé 'str =' hola '; str + = 5; cout << str; ' y no vio ningún efecto. Resulta que llama al operador + = (char) y agrega un carácter no imprimible. – daveagp

Respuesta

4

respuesta común: itoa()

Esto es malo. itoa no es estándar, como se ha señalado en Where is the itoa function in Linux?

+0

itoa no es estándar: http://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux –

+1

iota está en el encabezado 'numérico' a partir de C++ 11. – uckelman

+1

@uckelman iota! = Itoa – emlai

45
#include <iostream> 
#include <string> 
#include <sstream> 
using namespace std; 
string itos(int i) // convert int to string 
{ 
    stringstream s; 
    s << i; 
    return s.str(); 
} 

robado Desvergonzadamente de http://www.research.att.com/~bs/bs_faq2.html.

+0

gracias por el código, el enlace está roto ahora: D –

69
std::ostringstream o; 
o << name << age; 
std::cout << o.str(); 
+0

esto es genial, el archivo de encabezado BYT es sstream – landerlyoung

80

Si tiene Boost, puede convertir el entero a una cadena utilizando boost::lexical_cast<std::string>(age).

Otra forma es utilizar stringstreams:

std::stringstream ss; 
ss << age; 
std::cout << name << ss.str() << std::endl; 

Un tercer enfoque sería utilizar sprintf o snprintf de la biblioteca C.

char buffer[128]; 
snprintf(buffer, sizeof(buffer), "%s%d", name.c_str(), age); 
std::cout << buffer << std::endl; 

Otros carteles sugirieron utilizar itoa. Esta NO es una función estándar, por lo que su código no será portátil si lo usa. Hay compiladores que no lo admiten.

+5

name << ss.str() probablemente sería más eficiente que name + ss.str () Además, en lugar de usar el literal 128 en snprintf, debe usar sizeof (buffer). Los literales numéricos son más agradables si se usan solo una vez. –

+0

Buenos puntos Ates. He actualizado el código para reflejar esto. –

+0

Tenga en cuenta que snprintf no garantiza la terminación nula de la cadena. Aquí hay una forma de asegurarse de que funciona:

 char buffer[128]; buffer[sizeof(buffer)-1] = '\0'; snprintf(buffer, sizeof(buffer)-1, "%s%d", name.c_str(), age); std::cout << buffer << std::endl; 

14
#include <string> 
#include <sstream> 
using namespace std; 
string concatenate(std::string const& name, int i) 
{ 
    stringstream s; 
    s << name << i; 
    return s.str(); 
} 
17

Me parece que la respuesta más simple es utilizar la función sprintf:

sprintf(outString,"%s%d",name,age); 
+1

snprintf puede ser complicado (principalmente porque potencialmente no puede incluir el carácter nulo en ciertas situaciones), pero prefiero que para evitar el buffer de sprintf se desborden los problemas potenciales. – terson

+2

sprintf (char *, const char *, ...) fallará en algunas versiones de compiladores cuando pase una std :: a% s. No todo, sin embargo (es un comportamiento indefinido) y puede depender de la longitud de la cadena (SSO). Utilice .c_str() – MSalters

12

Herb Sutter tiene un buen artículo sobre este tema: "The String Formatters of Manor Farm". Cubre Boost::lexical_cast, std::stringstream, std::strstream (que está en desuso) y sprintf contra snprintf.

5

Si está utilizando MFC, se puede utilizar un CString

CString nameAge = ""; 
nameAge.Format("%s%d", "John", 21); 

de C++ también tiene un string formatter.

10
#include <sstream> 

template <class T> 
inline std::string to_string (const T& t) 
{ 
    std::stringstream ss; 
    ss << t; 
    return ss.str(); 
} 

Luego, su uso sería algo como esto

std::string szName = "John"; 
    int numAge = 23; 
    szName += to_string<int>(numAge); 
    cout << szName << endl; 

Googled [y probado: p]

4

El std :: ostringstream es un buen método, pero a veces este truco adicional podría conseguir práctico transformar el formato a un trazador:

#include <sstream> 
#define MAKE_STRING(tokens) /****************/ \ 
    static_cast<std::ostringstream&>(   \ 
     std::ostringstream().flush() << tokens \ 
    ).str()         \ 
    /**/ 

Ahora se puede dar formato a cadenas como esta:

int main() { 
    int i = 123; 
    std::string message = MAKE_STRING("i = " << i); 
    std::cout << message << std::endl; // prints: "i = 123" 
} 
+0

Ick. Creo que prefiero usar una función en línea, gracias. –

15

no tengo el karma suficiente para comentar (por no hablar de edición), pero después de Jay (actualmente con más votos uno a 27) contiene un error.Este código:

std::stringstream ss; 
ss << age; 
std::cout << name << ss.str() << std::endl; 

Hace no resolver el problema planteado de crear una cadena que consiste en una cadena concatenada entero. Creo que Jay significaba algo más parecido a esto:

std::stringstream ss; 
ss << name; 
ss << age; 
std::cout << "built string: " << ss.str() << std::endl; 

La última línea es sólo para imprimir el resultado, y muestra cómo acceder a la cadena concatenada final.

885

En orden alfabético:

std::string name = "John"; 
int age = 21; 
std::string result; 

// 1. with Boost 
result = name + boost::lexical_cast<std::string>(age); 

// 2. with C++11 
result = name + std::to_string(age); 

// 3. with FastFormat.Format 
fastformat::fmt(result, "{0}{1}", name, age); 

// 4. with FastFormat.Write 
fastformat::write(result, name, age); 

// 5. with IOStreams 
std::stringstream sstm; 
sstm << name << age; 
result = sstm.str(); 

// 6. with itoa 
char numstr[21]; // enough to hold all numbers up to 64-bits 
result = name + itoa(age, numstr, 10); 

// 7. with sprintf 
char numstr[21]; // enough to hold all numbers up to 64-bits 
sprintf(numstr, "%d", age); 
result = name + numstr; 

// 8. with STLSoft's integer_to_string 
char numstr[21]; // enough to hold all numbers up to 64-bits 
result = name + stlsoft::integer_to_string(numstr, 21, age); 

// 9. with STLSoft's winstl::int_to_string() 
result = name + winstl::int_to_string(age); 

// 10. With Poco NumberFormatter 
result = name + Poco::NumberFormatter().format(age); 
  1. es seguro, pero lento; requiere Boost (solo encabezado); la mayoría/todas las plataformas
  2. es seguro, requiere C++ 11 (to_string() ya está incluida en #include <string>)
  3. es seguro y rápido; requiere FastFormat, que debe compilarse; la mayoría de las plataformas
  4. es segura y rápida; requiere FastFormat, que debe compilarse; la mayoría de las plataformas
  5. seguras, lentas y detalladas; requiere #include <sstream> (del estándar C++)
  6. es frágil (debe proporcionar un búfer lo suficientemente grande), rápido y detallado; itoa() es una extensión no estándar, y no se garantiza que esté disponible para todas las plataformas
  7. es frágil (debe proporcionar un búfer lo suficientemente grande), rápido y detallado; no requiere nada (es estándar C++); todas las plataformas
  8. son frágiles (debe proporcionar un búfer lo suficientemente grande), probably the fastest-possible conversion, detallado; requiere STLSoft (solo encabezado); la mayoría de las plataformas
  9. safe-ish (no utiliza más de una llamada int_to_string() en una sola instrucción), rápido; requiere STLSoft (solo encabezado); Sólo Windows
  10. es seguro, pero lento; requiere Poco C++; la mayoría de las plataformas
+13

Además del único enlace que has dado, ¿en qué basas tus comentarios de rendimiento? – JamieH

+1

Ver http: // tinyurl.com/234rq9u para una comparación de algunas de las soluciones –

+13

@Luca Martini: Las comparaciones no son completas ya que no incluyen las mejores bibliotecas de su clase. El MEJOR lugar para buscar comparaciones sin formato es: http://www.codeproject.com/KB/recipes/Tokenizer.aspx –

3

Hay más opciones posibles para concatenar un entero (u otro objeto numérico) con una cadena. Es Boost.Format

#include <boost/format.hpp> 
#include <string> 
int main() 
{ 
    using boost::format; 

    int age = 22; 
    std::string str_age = str(format("age is %1%") % age); 
} 

y Karma de Boost.Spirit (v2)

#include <boost/spirit/include/karma.hpp> 
#include <iterator> 
#include <string> 
int main() 
{ 
    using namespace boost::spirit; 

    int age = 22; 
    std::string str_age("age is "); 
    std::back_insert_iterator<std::string> sink(str_age); 
    karma::generate(sink, int_, age); 

    return 0; 
} 

Boost.Spirit Karma afirma ser una de la conversión fastest option for integer to string.

3

Si desea obtener un char *, y de haber utilizado stringstream según lo que los respondants anteriores han esbozado, y luego hacerlo por ejemplo:

myFuncWhichTakesPtrToChar(ss.str().c_str()); 

Ya que lo que los stringstream regresa por str() es un estándar cadena, puede llamar a c_str() sobre eso para obtener su tipo de salida deseado.

4

como una cuestión relacionada con Qt se cerró en favor de éste, aquí es cómo hacerlo usando Qt:

QString string = QString("Some string %1 with an int somewhere").arg(someIntVariable); 
string.append(someOtherIntVariable); 

La variable de cadena ahora tiene un valor de someIntVariable en lugar de% 1 y el valor de someOtherIntVariable en el fin.

+0

QString ("Algo") + QString :: number (someIntVariable) también funciona – gremwell

6

Si desea utilizar + para la concatenación de cualquier cosa que tenga un operador de salida, puede proporcionar una versión de la plantilla de operator+:

template <typename L, typename R> std::string operator+(L left, R right) { 
    std::ostringstream os; 
    os << left << right; 
    return os.str(); 
} 

entonces usted puede escribir sus concatenaciones de una manera directa:

std::string foo("the answer is "); 
int i = 42; 
std::string bar(foo + i);  
std::cout << bar << std::endl; 

salida:

the answer is 42 

Esta no es la forma más eficiente, pero no necesita la forma más eficiente a menos que esté haciendo una gran cantidad de concatenación dentro de un bucle.

+0

Si intento agregar números enteros o un entero y un doble, ¿se invocará esta función? Me pregunto si esta solución anulará las adiciones habituales ... –

+0

El operador devuelve un 'std :: string', por lo que no sería un candidato en las expresiones donde una cadena no es convertible en el tipo necesario. Por ejemplo, este 'operador +' no es elegible para ser usado por '+' en 'int x = 5 + 7;'. Teniendo en cuenta todo esto, no definiría un operador como este sin una razón muy convincente, pero mi objetivo era ofrecer una respuesta diferente a las demás. – uckelman

+0

Tienes razón (acabo de probarlo ...). Y cuando traté de hacer algo como * string s = 5 + 7 *, recibí el error * conversión inválida de 'int' a 'const char * * * –

1

Otra manera fácil de hacerlo es:

name.append(age+""); 
cout << name; 
+4

No entiendo cómo se activó 5 veces ... ¡Esto ni siquiera compila! – 0x499602D2

+3

En realidad, compila pero invoca un comportamiento indefinido – 0x499602D2

+1

Está degradando la cadena literal '" "' a 'char *' e incrementando ese puntero por 'edad'. En otras palabras, comportamiento indefinido. – emlai

224

en C++ 11,

std::string result = name + std::to_string (age); 
17

Si tiene C++ 11 se puede utilizar std::to_string:

std::string name = "John"; 
int age = 21; 

name += std::to_string(age); 

std::cout << name; // "John21" 
+2

Sería 'name + = std :: to_string (static_cast (age));' en VC++ 2010 como puede ver [aquí] (http://stackoverflow.com/questions/10664699/stdto-string-more- than-instance-of-overloaded-function-matches-the-argument) – neonmate

+0

@neonmate ¿Qué tal 'name + = std :: to_string (age + 0LL);' en su lugar? – chux

3

Hay una función que escribí, que toma los parámetros el número int, y lo convierte en un literal de cadena, esta función depende de otra función ion que convierte un único dígito a su equivalente Char:

char intToChar (int num) 
{ 
    if (num < 10 && num >= 0) 
    { 
     return num + 48; 
     //48 is the number that we add to an integer number to have its character equivalent (see the unsigned ASCII table) 
    } 
    else 
    { 
     return '*'; 
    } 
} 

string intToString (int num) 
{ 
    int digits = 0, process, single; 
    string numString; 
    process = num; 

    //The following process the number of digits in num 
    while (process != 0) 
    { 
     single = process % 10; // single now hold the rightmost portion of the int 
     process = (process - single)/10; 
     // take out the rightmost number of the int (it's a zero in this portion of the int), then divide it by 10 
     // The above combinasion eliminates the rightmost portion of the int 
     digits ++; 
    } 

    process = num; 

    //Fill the numString with '*' times digits 
    for (int i = 0; i < digits; i++) 
    { 
     numString += '*'; 
    } 


    for (int i = digits-1; i >= 0; i--) 
    { 
     single = process % 10; 
     numString[i] = intToChar (single); 
     process = (process - single)/10; 
    } 

    return numString; 
} 
2

Aquí es una implementación de cómo anexar un int en una cadena mediante las facetas de análisis y de formato de la biblioteca iostreams.

#include <iostream> 
#include <locale> 
#include <string> 

template <class Facet> 
struct erasable_facet : Facet 
{ 
    erasable_facet() : Facet(1) { } 
    ~erasable_facet() { } 
}; 

void append_int(std::string& s, int n) 
{ 
    erasable_facet<std::num_put<char, 
           std::back_insert_iterator<std::string>>> facet; 
    std::ios str(nullptr); 

    facet.put(std::back_inserter(s), str, 
            str.fill(), static_cast<unsigned long>(n)); 
} 

int main() 
{ 
    std::string str = "ID: "; 
    int id = 123; 

    append_int(str, id); 

    std::cout << str; // ID: 123 
} 
1

Sin C++ 11, para una pequeña gama de enteros, he encontrado este es todo lo que necesitaba:

declare/incluye alguna variante de la siguiente parte:

const string intToString[10] = {"0","1","2","3","4","5","6","7","8","9"}; 

a continuación:

string str = intToString[3]+" + "+intToString[4]+" = "+intToString[7]; //str equals "3 + 4 = 7" 

Funciona con enums too.

-3

Soy un usuario principiante C++ y encontré esto de la manera más fácil:

cout << name << age; 

Esto concatenar con éxito el nombre y la edad, la salida será "John21".

Sin embargo, tiene que haber una razón por la que nadie haya dicho esto; Creo que puede haber un defecto, aunque no he experimentado hasta ahora.

EDIT: Me he dado cuenta de que esta no es necesariamente la respuesta correcta, sin embargo la mantendré aquí en caso de que cualquier principiante en C++ desee saber cómo enviar cadenas concatenadas.

+5

Esto es solo ** salida ** dos cadenas juntas, sin construir una nueva cadena. Entonces, por ejemplo, no puede pasar el resultado a otras funciones. Esta no es una respuesta. –

+1

Ah, no interpreté la pregunta de OP correctamente, en ese caso. Pero IOStream funcionaría, ¿correcto? –

+1

Esto * podría * convertirse fácilmente en una buena respuesta a la pregunta del OP si invoca 'stringstream's .... – Hurkyl

24

Ésta es la manera más fácil:

string s = name + std::to_string(age); 
+7

¡Esta es una solución posterior a C++ 11! –

4

Puede contatenar int a cadena utilizando la figura a continuación truco simple, pero tenga en cuenta que esto sólo funciona cuando se entero es de un solo dígito de lo contrario añadir dígitos enteros por dígitos a esa cuerda

string name = "John"; 
int age = 5; 
char temp=5+'0'; 
name=name+temp; 
cout<<name<<endl; 

Output:- John5 
0

Sugerencia de una solución alternativa para personas como yo que pueden no tener acceso a C++ 11 y bibliotecas/encabezados adicionales como boost. Una simple conversión funciona así:

ejemplo el número es 4, para convertir 3 en ascii simplemente podemos usar el código:
char a = '0' + 4

Esto almacenará inmediatamente 4 como un personaje de a.

A partir de aquí, simplemente podemos concatenar a con el resto de la cadena.

1

El detailed answer está enterrado en otras respuestas a continuación, volver a allanar parte de ella:

#include <iostream> // cout 
#include <string> // string, to_string(some_number_here) 

using namespace std; 

int main() { 
    // using constants 
    cout << "John" + std::to_string(21) << endl; 
    // output is: 
    // John21 

    // using variables 
    string name = "John"; 
    int age = 21; 
    cout << name + to_string(age) << endl; 
    // output is: 
    // John21 
} 
Cuestiones relacionadas