¿Cómo concatenar un std :: string y un int?

Pensé que esto sería realmente simple, pero presenta algunas dificultades. Si tengo

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

¿Cómo los combino para obtener una sola cadena? "John21"?

preguntado Oct 10 '08, 13:10

Herb Sutter tiene un buen artículo sobre este tema: "Los formateadores de cadenas de Manor Farm". El cubre Boost::lexical_cast, std::stringstream, std::strstream (que está en desuso), y sprintf vs snprintf. -

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

23 Respuestas

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 the {fmt} library
result = fmt::format("{}{}", name, age);

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

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

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

// 9. 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);

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

// 11. 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 (Encadenar() ya está incluido en #include <string>)
  3. es seguro y rápido; requiere formato rápido, que debe compilarse; la mayoría / todas las plataformas
  4. (ídem)
  5. es seguro y rápido; requiere la biblioteca {fmt}, que puede compilarse o usarse en un modo de solo encabezado; la mayoría / todas las plataformas
  6. seguro, lento y detallado; requiere #include <sstream> (de C ++ estándar)
  7. 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
  8. 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
  9. es frágil (debe proporcionar un búfer lo suficientemente grande), probablemente la conversión más rápida posible, detallado; requiere STLSoft (solo encabezado); la mayoría / todas las plataformas
  10. safe-ish (no usas más de uno int_to_string () llamar en una sola declaración), rápido; requiere STLSoft (solo encabezado); Solo Windows
  11. es seguro, pero lento; requiere Poco C ++ ; la mayoría / todas las plataformas

Respondido 21 Jul 19, 03:07

Aparte del único enlace que ha proporcionado, ¿en qué basa sus comentarios de rendimiento? - jamieh

¡¡Esa es casi toda tu reputación con una sola respuesta !! Tienes suerte, frijol;) Creo que 8 es C estándar (por supuesto, también C ++), pero probablemente valga la pena diferenciarlo. - Noelicus

2. es lento ya que std :: to_string (age) crea una cadena temporal que se agrega al resultado. - Ígor Bukanov

Si estás en Arduino, también puedes usar String(number). - Hacha

En C ++ 11, puede usar std::to_string, p.ej:

auto result = name + std::to_string( age );

Respondido 20 Abr '18, 10:04

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

Otra forma es usar cadenas de cadenas:

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

Un tercer enfoque sería utilizar sprintf or 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 usar 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.

Respondido 10 Oct 08, 16:10

Tenga en cuenta que no se garantiza que snprintf termine en nulo la cadena. Aquí hay una forma de asegurarse de que funcione: tampón char [128]; búfer [tamaño de (búfer) -1] = '\ 0'; snprintf (búfer, tamaño de (búfer) -1, "% s% d", nombre.c_str (), edad); std :: cout << buffer << std :: endl; - Señor fooz

Mi tendencia sería nunca usar sprintf, ya que esto puede resultar en desbordamientos de búfer. El ejemplo anterior es un buen ejemplo en el que usar sprintf no sería seguro si el nombre fuera muy largo. - terson

tenga en cuenta que snprintf es igualmente C ++ no estándar (como itoa que usted menciona). está tomado de c99 - Johannes Schaub - litb

@terson: No veo ninguna ocurrencia de sprintf en la respuesta, solo snprintf. - david foster

#include <iostream>
#include <sstream>

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

contestado el 16 de mayo de 19 a las 17:05

esto es genial, el archivo de encabezado BYT es sstream - landerly joven

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

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

Respondido el 07 de diciembre de 12 a las 16:12

pero s es una pila de variables, la memoria de s será gratis después de invocar itos. s debe asignar desde el montón, y free después de usarlo, ¿verdad? - kglibro

la devolución por valor está bien aunque el objeto de cadena se haya salido del alcance, stackoverflow.com/a/3977119/5393174 - kglibro

Esta es la manera más fácil:

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

Respondido el 21 de diciembre de 14 a las 21:12

¡Esta es una solución post-C ++ 11! - YamHon.CHAN

Si tiene C ++ 11, puede usar std::to_string.

Ejemplo:

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

name += std::to_string(age);

std::cout << name;

Salida:

John21

Respondido 20 Abr '18, 10:04

Podría ser name += std::to_string(static_cast<long long>(age)); en VC ++ 2010 como puede ver aquí - compañero de neón

@neonmate ¿Qué tal name += std::to_string(age + 0LL); ¿en lugar de? - chux - Reincorporar a Monica

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

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

Respondido el 07 de diciembre de 12 a las 16:12

snprintf puede ser complicado (principalmente porque potencialmente no puede incluir el carácter nulo en ciertas situaciones), pero lo prefiero para evitar problemas potenciales de desbordamiento del búfer de sprintf. - terson

sprintf (char *, const char *, ...) fallará en algunas versiones de compiladores cuando pase un std :: string a% s. Sin embargo, no todos (es un comportamiento indefinido) y puede depender de la longitud de la cadena (SSO). Utilice .c_str () - MSalters

además sprintf está sujeto a desbordamientos de búfer, por lo que es posible una inyección de código - Jean-François Fabre ♦

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

Respondido 10 Oct 08, 16:10

#include <sstream>

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

Entonces su uso se vería así

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

buscado en Google [y probado: p]

Respondido 13 Oct 08, 17:10

Este problema se puede solucionar de muchas formas. Lo mostraré de dos maneras:

  1. Convierta el número en una cadena usando to_string(i).

  2. Utilizando secuencias de cadenas.

    Código:

    #include <string>
    #include <sstream>
    #include <bits/stdc++.h>
    #include <iostream>
    using namespace std;
    
    int main() {
        string name = "John";
        int age = 21;
    
        string answer1 = "";
        // Method 1). string s1 = to_string(age).
    
        string s1=to_string(age); // Know the integer get converted into string
        // where as we know that concatenation can easily be done using '+' in C++
    
        answer1 = name + s1;
    
        cout << answer1 << endl;
    
        // Method 2). Using string streams
    
        ostringstream s2;
    
        s2 << age;
    
        string s3 = s2.str(); // The str() function will convert a number into a string
    
        string answer2 = "";  // For concatenation of strings.
    
        answer2 = name + s3;
    
        cout << answer2 << endl;
    
        return 0;
    }
    

respondido 01 mar '19, 09:03

Cual es mas rapido? - ghchoi

Si desea utilizar + para la concatenación de cualquier cosa que tenga un operador de salida, puede proporcionar una versión de 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 puede escribir sus concatenaciones de una manera sencilla:

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 mucha concatenación dentro de un bucle.

respondido 03 nov., 11:13

Si intento sumar números enteros o un número entero y un doble, ¿se llamará a esta función? Me pregunto si esta solución anulará las adiciones habituales ... - Hilder Vítor Lima Pereira

El operador devuelve un std::string, por lo que no sería un candidato en expresiones donde una cadena no se puede convertir en el tipo necesario. Por ejemplo, este operator+ no es apto para su uso + in int x = 5 + 7;. A fin de cuentas, no definiría un operador como este sin un muy razón de peso, pero mi objetivo era ofrecer una respuesta diferente a las demás. - uckelman

Tienes razón (acabo de probarlo ...). Y cuando intenté hacer algo como cuerda s = 5 + 7, Tengo el error conversión no válida de 'int' a 'const char'* - Hilder Vítor Lima Pereira

Para la mayoría de los casos de uso, el uso de plantillas que vinculan el operando izquierdo o derecho a una cadena (que incluye std::string, std::string_view y const char *) debería ser suficiente. - Kai Petzke

Si está utilizando MFC, puede utilizar un CString

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

C ++ administrado también tiene un formateador de cadenas.

Respondido 18 ago 17, 16:08

El std :: ostringstream es un buen método, pero a veces este truco adicional puede resultar útil para transformar el formato en una sola línea:

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

Ahora puede formatear cadenas como esta:

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

Respondido 10 Oct 08, 23:10

Por que utilizar un preprocesador #define en lugar de un template? Con plantillas variadas, incluso se podrían pasar varios tokens. Pero dudo en usar esto, ya que el static_cast de nuevo a std::ostringstream en la salida del << operando es un poco inseguro. Es una convención que todos los generadores devuelvan un referente al objeto de flujo original, pero esto no está garantizado en ninguna parte en el estándar. - Kai Petzke

Estás comentando la respuesta de un niño de 12 años. Ahora tenemos plantillas variadas. Probablemente elegiría github.com/fmtlib/fmt ahora. - Piry Jahkola

Como una pregunta relacionada con Qt se cerró a favor de esta, aquí se explica 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 el valor de someIntVariable en lugar de% 1 y el valor de someOtherIntVariable al final.

Respondido 10 ago 11, 14:08

QString ("Algo") + QString :: number (someIntVariable) también funciona - Gremwell

Respuesta común: itoa ()

Esto es malo. itoa no es estándar, como se señaló aquí.

Respondido 20 Abr '18, 10:04

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

#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 Impulsar el espíritu (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 uno de los opción más rápida de entero a cadena conversión.

Respondido 04 Oct 10, 11:10

En C ++ 20 podrás hacer:

auto result = std::format("{}{}", name, age);

Mientras tanto puedes usar la biblioteca {fmt}, std::format está basado en:

auto result = fmt::format("{}{}", name, age);

Descargo de responsabilidad: Soy el autor de la biblioteca {fmt} y C ++ 20 std::format.

Respondido el 21 de diciembre de 20 a las 04:12

Aquí hay una implementación de cómo agregar un int a una cadena usando las facetas de análisis y 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
}

Respondido el 31 de diciembre de 13 a las 16:12

  • std :: ostringstream
#include <sstream>

std::ostringstream s;
s << "John " << age;
std::string query(s.str());
  • std :: to_string (C ++ 11)
std::string query("John " + std::to_string(age));
  • boost :: lexical_cast
#include <boost/lexical_cast.hpp>

std::string query("John " + boost::lexical_cast<std::string>(age));

Respondido 03 ago 18, 08:08

Cual es el mas rapido? - ghchoi

Puede concatenar int a string utilizando el truco simple que se proporciona a continuación, pero tenga en cuenta que esto solo funciona cuando el número entero es de un solo dígito. De lo contrario, agregue número entero dígito por dígito a esa cadena.

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

Output:  John5

Respondido el 09 de Septiembre de 18 a las 22:09

Como un trazador de líneas: name += std::to_string(age);

respondido 30 mar '20, 14:03

Hay una función que escribí, que toma el número int como parámetro y lo convierte en un literal de cadena. Esta función depende de otra función que convierte un solo dígito en 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 holds 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 combination 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;
}

Respondido el 09 de Septiembre de 18 a las 22:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.