Come concatenare uno std :: string e un int?


655

Ho pensato che sarebbe stato molto semplice, ma presenta alcune difficoltà. Se ho

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

Come li combino per ottenere una singola stringa "John21"?


Herb Sutter ha un buon articolo su questo argomento: "The String Formatters of Manor Farm" . Si copre Boost::lexical_cast, std::stringstream, std::strstream(che è deprecato), e sprintfcontro snprintf.
Fred Larson,

Vorrei aggiungere a questo: ho provato 'str = "hi"; str + = 5; cout << str; ' e non ho visto alcun effetto. Risulta questo chiama l'operatore + = (carattere) e aggiunge un carattere non stampabile.
daveagp,

Risposte:


1126

In ordine alfabetico:

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. è sicuro, ma lento; richiede Boost (solo intestazione); la maggior parte / tutte le piattaforme
  2. è sicuro, richiede C ++ 11 ( to_string () è già incluso in #include <string>)
  3. è sicuro e veloce; richiede FastFormat , che deve essere compilato; la maggior parte / tutte le piattaforme
  4. ( idem )
  5. è sicuro e veloce; richiede la libreria {fmt} , che può essere compilata o utilizzata in modalità solo intestazione; la maggior parte / tutte le piattaforme
  6. sicuro, lento e dettagliato; richiede #include <sstream>(dallo standard C ++)
  7. è fragile (è necessario fornire un buffer abbastanza grande), veloce e dettagliato; itoa () è un'estensione non standard e non è garantita la disponibilità per tutte le piattaforme
  8. è fragile (è necessario fornire un buffer abbastanza grande), veloce e dettagliato; non richiede nulla (è standard C ++); tutte le piattaforme
  9. è fragile (è necessario fornire un buffer abbastanza grande), probabilmente la conversione più veloce possibile , dettagliata; richiede STLSoft (solo intestazione); la maggior parte / tutte le piattaforme
  10. safe-ish (non usi più di una chiamata int_to_string () in una singola istruzione), veloce; richiede STLSoft (solo intestazione); Solo per Windows
  11. è sicuro, ma lento; richiede Poco C ++ ; la maggior parte / tutte le piattaforme

13
A parte l'unico link che hai creato, su cosa stai basando i tuoi commenti sul rendimento?
JamieH,

2
Questa è quasi tutta la tua reputazione da un'unica risposta !! Fagiolo fortunato;) Penso che 8 sia C standard (ovviamente anche C ++), ma probabilmente vale la pena differenziarlo.
noelicus,

2. è lento poiché std :: to_string (age) crea una stringa temporanea che viene aggiunta al risultato.
Igor Bukanov,

Se sei su Arduino, puoi anche usare String(number).
Machado,

267

In C ++ 11 è possibile utilizzare std::to_string, ad esempio:

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

mi piace questo, semplice. Grazie.
truthadjustr,

85

Se si dispone di Boost, è possibile convertire l'intero in una stringa utilizzando boost::lexical_cast<std::string>(age).

Un altro modo è quello di utilizzare i flussi di stringhe:

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

Un terzo approccio sarebbe quello di utilizzare sprintfo snprintfdalla libreria C.

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

Altri poster hanno suggerito di utilizzare itoa. Questa NON è una funzione standard, quindi il tuo codice non sarà portatile se lo usi. Ci sono compilatori che non lo supportano.


Si noti che snprintf non è garantito per terminare null la stringa. Ecco un modo per assicurarsi che funzioni: <pre> buffer di caratteri [128]; buffer [sizeof (buffer) -1] = '\ 0'; snprintf (buffer, sizeof (buffer) -1, "% s% d", nome.c_str (), età); std :: cout << buffer << std :: endl; </pre>
Fooz,

La mia tendenza sarebbe di non usare mai lo sprintf, dal momento che ciò può provocare buffer overflow. L'esempio sopra è un buon esempio in cui l'uso di sprintf non sarebbe sicuro se il nome fosse molto lungo.
terson,

si noti che snprintf è ugualmente non standard c ++ (come itoa di cui si parla). è preso dal c99
Johannes Schaub - litb

@terson: non vedo alcuna occorrenza sprintfnella risposta, solo snprintf.
David Foerster,

80
#include <iostream>
#include <sstream>

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

2
questo è fantastico, il file di intestazione BYT è sstream
landerlyoung il

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

Spudoratamente rubato da http://www.research.att.com/~bs/bs_faq2.html .


ma s è una pila di variabili, la memoria di ssarà libera dopo invocare itos. sdovrebbe allocare da heap, e freedopo aver usato, giusto?
kgbook

1
ritorno per valore è ok anche se l'oggetto stringa va di portata, stackoverflow.com/a/3977119/5393174
kgbook

32

Questo è il modo più semplice:

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

8
Questa è una soluzione post-C ++ 11!
YamHon.CHAN,

23

Se hai C ++ 11, puoi usare std::to_string.

Esempio:

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

name += std::to_string(age);

std::cout << name;

Produzione:

John21

2
Sarebbe name += std::to_string(static_cast<long long>(age));in VC ++ 2010 come puoi vedere qui
neonmate

@neonmate Che ne dici name += std::to_string(age + 0LL);invece?
chux - Ripristina Monica il

18

Mi sembra che la risposta più semplice sia usare la sprintffunzione:

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

1
snprintf può essere complicato (principalmente perché potenzialmente non può includere il carattere null in determinate situazioni), ma preferisco che per evitare sprintf il buffer trabocchi di potenziali problemi.
terson,

3
sprintf (char *, const char *, ...) fallirà su alcune versioni dei compilatori quando si passa una stringa std :: string a% s. Non tutti, però (è un comportamento indefinito) e può dipendere dalla lunghezza della stringa (SSO). Si prega di utilizzare .c_str ()
MSalters il

inoltre sprintf è soggetto a buffer overflow, quindi possibile iniezione di codice
Jean-François Fabre

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

11
#include <sstream>

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

Quindi il tuo utilizzo sarebbe simile a questo

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

Google [e testato: p]


10

Questo problema può essere fatto in molti modi. Lo mostrerò in due modi:

  1. Converti il ​​numero in stringa usando to_string(i).

  2. Utilizzo di flussi di stringhe.

    Codice:

    #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;
    }

Quale è più veloce?
GyuHyeon Choi,

7

Se desideri utilizzare +per la concatenazione di tutto ciò che ha un operatore di output, puoi fornire una versione modello di operator+:

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

Quindi puoi scrivere le tue concatenazioni in modo semplice:

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

Produzione:

the answer is 42

Questo non è il modo più efficiente, ma non è necessario il modo più efficiente a meno che non si stia facendo molta concatenazione all'interno di un ciclo.


Se provo ad aggiungere numeri interi o un numero intero e un doppio, questa funzione verrà chiamata? Mi chiedo se questa soluzione prevarrà sulle solite aggiunte ...
Hilder Vitor Lima Pereira

L'operatore restituisce a std::string, quindi non sarebbe un candidato nelle espressioni in cui una stringa non è convertibile nel tipo necessario. Ad esempio, questo operator+non è idoneo per essere utilizzato +in int x = 5 + 7;. Tutto sommato, non definirei un operatore come questo senza un motivo molto convincente, ma il mio obiettivo era offrire una risposta diversa dalle altre.
Uckelman,

Hai ragione (l'ho appena provato ...). E quando ho provato a fare qualcosa come string s = 5 + 7 , ho ricevuto l'errore di conversione non valida da 'int' a 'const char ' *
Hilder Vitor Lima Pereira,

5

Se si utilizza MFC, è possibile utilizzare un CString

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

Managed C ++ ha anche un formattatore di stringhe .


4

Std :: ostringstream è un buon metodo, ma a volte questo trucco aggiuntivo potrebbe essere utile per trasformare la formattazione in una riga:

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

Ora puoi formattare le stringhe in questo modo:

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

4

Poiché una domanda relativa a Qt è stata chiusa a favore di questa, ecco come farlo usando Qt:

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

La variabile stringa ora ha il valore di someIntVariable al posto di% 1 e il valore di someOtherIntVariable alla fine.


QString ("Something") + QString :: number (someIntVariable) funziona anche
gremwell

3

Sono disponibili più opzioni per concatenare numeri interi (o altri oggetti numerici) con stringa. È 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);
}

e Karma di 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 afferma di essere una delle opzioni più veloci per la conversione da intero a stringa .



3

Puoi concatenare int a stringa usando il semplice trucco indicato di seguito, ma nota che funziona solo quando il numero intero è di una sola cifra. Altrimenti, aggiungi un numero intero per cifra a quella stringa.

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

Output:  John5

2

Ecco un'implementazione di come aggiungere un int a una stringa usando le sfaccettature di analisi e formattazione della libreria 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
}

2
  • 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));

Qual è il più veloce?
GyuHyeon Choi,

2

C'è una funzione che ho scritto, che accetta il numero int come parametro e lo converte in una stringa letterale. Questa funzione dipende da un'altra funzione che converte una singola cifra nel suo 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;
}

1

Con la libreria {fmt} :

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

Un sottoinsieme della libreria viene proposto per la standardizzazione come P0645 Formattazione del testo e, se accettato, quanto sopra diventerà:

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

Disclaimer : sono l'autore della libreria {fmt}.


0

Come una fodera: name += std::to_string(age);


3
Questo è lo stesso codice della risposta 0x499602D2.
BDL
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.