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"?


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

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

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.


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();

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 .


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

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

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

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();
}

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]


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

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.


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 .


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"
}

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.


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 .



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

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
}

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

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}.


0

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


3
Esse é o mesmo código da resposta 0x499602D2.
BDL
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.