Como concatenar um std :: string e um int?

655

Eu pensei que isso seria realmente simples, mas está apresentando algumas dificuldades. Se eu tiver

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

Como faço para combiná-los para obter uma única string "John21"?

Obediah Stane
fonte
Herb Sutter tem um bom artigo sobre este assunto: "Os Formatadores de Cordas da Manor Farm" . Ele cobre Boost::lexical_cast, std::stringstream, std::strstream(que está obsoleta), e sprintfvs. snprintf.
Fred Larson
Deixe-me acrescentar a isso: tentei 'str = "oi"; str + = 5; cout << str; ' e não viu efeito. Acontece que isso chama o operador + = (char) e adiciona um caractere não imprimível.
Daveagp

Respostas:

1126

Em ordem alfabética:

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. é seguro, mas lento; requer impulso (somente cabeçalho); maioria / todas as plataformas
  2. é seguro, requer C ++ 11 ( to_string () já está incluído no#include <string> )
  3. é seguro e rápido; requer FastFormat , que deve ser compilado; maioria / todas as plataformas
  4. ( idem )
  5. é seguro e rápido; requer a biblioteca {fmt} , que pode ser compilada ou usada no modo somente cabeçalho; maioria / todas as plataformas
  6. seguro, lento e detalhado; requer #include <sstream>(do C ++ padrão)
  7. é quebradiço (você deve fornecer um buffer grande o suficiente), rápido e detalhado; itoa () é uma extensão não padrão e não está garantida para estar disponível para todas as plataformas
  8. é quebradiço (você deve fornecer um buffer grande o suficiente), rápido e detalhado; não requer nada (é C ++ padrão); todas as plataformas
  9. é quebradiço (você deve fornecer um buffer suficientemente grande), provavelmente a conversão mais rápida possível , detalhada; requer STLSoft (somente cabeçalho); maioria / todas as plataformas
  10. safe-ish (você não usa mais de uma chamada int_to_string () em uma única instrução), rápido; requer STLSoft (somente cabeçalho); Somente Windows
  11. é seguro, mas lento; requer Poco C ++ ; maioria / todas as plataformas
DannyT
fonte
13
Além do link que você forneceu, em que você está baseando seus comentários de desempenho?
21711 JamieH
2
Isso é quase toda a sua reputação com uma única resposta !! Você tem sorte;) Eu acho que 8 é o padrão C (é claro, também C ++), mas provavelmente vale a pena diferenciar.
Noelicus 16/08/19
2. é lento, pois std :: to_string (age) cria uma string temporária que é anexada ao resultado.
Igor Bukanov 15/09/19
Se você estiver no Arduino, também poderá usar String(number).
Machado
267

No C ++ 11, você pode usar std::to_string, por exemplo:

auto result = name + std::to_string( age );
Jeremy
fonte
Eu gosto deste, simples. Obrigado.
truthadjustr 12/04
85

Se você possui o Boost, pode converter o número inteiro em uma string usando boost::lexical_cast<std::string>(age).

Outra maneira é usar strings:

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

Uma terceira abordagem seria usar sprintfou a snprintfpartir da biblioteca C.

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

Outros pôsteres sugeriram o uso itoa. Essa NÃO é uma função padrão; portanto, seu código não será portátil se você o usar. Existem compiladores que não suportam isso.

Jay Conrod
fonte
Observe que não é garantido que snprintf encerre a seqüência de caracteres nula. Aqui está uma maneira de garantir que funcione: <pre> char buffer [128]; buffer [sizeof (buffer) -1] = '\ 0'; snprintf (buffer, sizeof (buffer) -1, "% s% d", nome.c_str (), idade); std :: cout << buffer << std :: endl; </pre>
Mr Fooz
Minha tendência seria nunca usar o sprintf, pois isso pode resultar em estouros de buffer. O exemplo acima é um bom exemplo em que o uso do sprintf não seria seguro se o nome fosse muito longo.
terson 11/10/08
note que snprintf é igualmente não-padrão em c ++ (como itoa que você mencionou). é retirado de c99
Johannes Schaub - litb 9/02/09
@terson: Não vejo ocorrência de sprintfapenas resposta snprintf.
David Foerster
80
#include <iostream>
#include <sstream>

std::ostringstream o;
o << name << age;
std::cout << o.str();
Ben Hoffstein
fonte
2
isso é ótimo, arquivo de cabeçalho BYT é sstream
landerlyoung
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();
}

Roubado descaradamente de http://www.research.att.com/~bs/bs_faq2.html .

abordagem
fonte
mas s é uma pilha variáveis, a memória de sserá liberada após a chamada itos. sdeve alocar da pilha, e freedepois de usar, certo?
kgbook
1
retorno por valor está ok, mesmo que o objeto string tenha ficado fora do escopo, stackoverflow.com/a/3977119/5393174
kgbook 10/09/18
32

Esta é a maneira mais fácil:

string s = name + std::to_string(age);
Kevin
fonte
8
Esta é uma solução pós-C ++ 11!
YamHon.CHAN
23

Se você possui C ++ 11, pode usar std::to_string.

Exemplo:

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

name += std::to_string(age);

std::cout << name;

Resultado:

John21
0x499602D2
fonte
2
Seria name += std::to_string(static_cast<long long>(age));no VC ++ 2010, como você pode ver aqui #
neonmate
@neonmate Que tal em name += std::to_string(age + 0LL);vez disso?
chux - Restabelece Monica
18

Parece-me que a resposta mais simples é usar a sprintffunção:

sprintf(outString,"%s%d",name,age);
user12576
fonte
1
O snprintf pode ser complicado (principalmente porque ele pode não incluir o caractere nulo em determinadas situações), mas eu prefiro isso para evitar que o buffer do sprintf ultrapasse os possíveis problemas.
terson
3
O sprintf (char *, const char *, ...) falhará em algumas versões dos compiladores quando você passa um std :: string para% s. Nem todos, porém (é um comportamento indefinido) e pode depender do tamanho da string (SSO). Por favor, use .c_str ()
MSalters
mais o sprintf está sujeito a estouros de buffer, portanto, possível injeção de código
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();
}
Seb Rose
fonte
11
#include <sstream>

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

Então seu uso seria algo parecido com isto

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

Pesquisou no Google [e testou: p]

Zing-
fonte
10

Esse problema pode ser feito de várias maneiras. Vou mostrar de duas maneiras:

  1. Converta o número em string usando to_string(i).

  2. Usando fluxos de string.

    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;
    }
lohith99
fonte
Qual é o mais rápido?
GyuHyeon Choi 18/02
7

Se você deseja usar +para concatenação de qualquer coisa que possua um operador de saída, é possível fornecer uma versão do modelo de operator+:

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

Em seguida, você pode escrever suas concatenações de maneira direta:

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

Resultado:

the answer is 42

Essa não é a maneira mais eficiente, mas você não precisa da maneira mais eficiente, a menos que esteja fazendo muita concatenação dentro de um loop.

uckelman
fonte
Se eu tentar adicionar números inteiros ou um número inteiro e um duplo, essa função será chamada? Eu estou querendo saber se esta solução irá substituir as adições habituais ...
Hilder Vitor Lima Pereira
O operador retorna a std::string, portanto, não seria candidato em expressões em que uma string não é convertível no tipo necessário. Por exemplo, isso operator+não é elegível para uso +em int x = 5 + 7;. Considerando tudo, eu não definiria um operador como esse sem uma razão muito convincente, mas meu objetivo era oferecer uma resposta diferente dos outros.
uckelman
Você está certo (eu apenas testei ...). E quando eu tentei fazer algo como string s = 5 + 7 , recebi o erro de conversão inválida de 'int' para 'const char ' *
Hilder Vitor Lima Pereira
5

Se você estiver usando o MFC, poderá usar um CString

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

O C ++ gerenciado também possui um formatador de string .

bsruth
fonte
4

O std :: ostringstream é um bom método, mas às vezes esse truque adicional pode ser útil para transformar a formatação em uma linha:

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

Agora você pode formatar strings como este:

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

Como uma pergunta relacionada ao Qt foi encerrada em favor deste, veja como fazê-lo usando o Qt:

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

A variável string agora tem o valor de someIntVariable no lugar de% 1 e o valor de someOtherIntVariable no final.

leinir
fonte
QString ( "Something") + QString :: número (someIntVariable) também funciona
gremwell
3

Há mais opções possíveis para concatenar número inteiro (ou outro objeto numérico) com a sequência. É 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 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;
}

O Boost.Spirit Karma afirma ser uma das opções mais rápidas para conversão de número inteiro em string .

mloskot
fonte
3

Você pode concatenar int para string usando o truque simples abaixo, mas observe que isso só funciona quando o número inteiro é de um dígito. Caso contrário, adicione dígito inteiro por dígito a essa sequência.

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

Output:  John5
Sukhbir
fonte
2

Aqui está uma implementação de como anexar um int a uma string usando as facetas de análise e formatação da 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
}
0x499602D2
fonte
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));
Isma Rekathakusuma
fonte
Qual é o mais rápido?
GyuHyeon Choi 18/02
2

Há uma função que escrevi, que pega o número int como parâmetro e o converte em uma string literal. Esta função depende de outra função que converte um único dígito em seu equivalente de caractere:

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;
}
Reda Lahdili
fonte
1

Com a biblioteca {fmt} :

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

Um subconjunto da biblioteca é proposto para padronização como Formatação de texto P0645 e, se aceito, o acima será:

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

Isenção de responsabilidade : sou o autor da biblioteca {fmt}.

vitaut
fonte
0

Como um forro: name += std::to_string(age);

ant_dev
fonte
3
Esse é o mesmo código da resposta 0x499602D2.
BDL