How to concatenate a std::string and an int
Asked Answered
L

25

784

I thought this would be really simple, but it's presenting some difficulties. If I have

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

How do I combine them to get a single string "John21"?

Lehrer answered 10/10, 2008 at 15:5 Comment(2)
Herb Sutter has a good article on this subject: "The String Formatters of Manor Farm". He covers Boost::lexical_cast, std::stringstream, std::strstream (which is deprecated), and sprintf vs. snprintf.Ide
Let me add to this: I tried 'str = "hi"; str += 5; cout << str;' and saw no effect. Turns out this calls operator+=(char) and adds a non-printable character.Methedrine
S
1360

In alphabetical order:

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. is safe, but slow; requires Boost (header-only); most/all platforms
  2. is safe, requires C++11 (to_string() is already included in #include <string>)
  3. is safe, and fast; requires FastFormat, which must be compiled; most/all platforms
  4. (ditto)
  5. is safe, and fast; requires the {fmt} library, which can either be compiled or used in a header-only mode; most/all platforms
  6. safe, slow, and verbose; requires #include <sstream> (from standard C++)
  7. is brittle (you must supply a large enough buffer), fast, and verbose; itoa() is a non-standard extension, and not guaranteed to be available for all platforms
  8. is brittle (you must supply a large enough buffer), fast, and verbose; requires nothing (is standard C++); all platforms
  9. is brittle (you must supply a large enough buffer), probably the fastest-possible conversion, verbose; requires STLSoft (header-only); most/all platforms
  10. safe-ish (you don't use more than one int_to_string() call in a single statement), fast; requires STLSoft (header-only); Windows-only
  11. is safe, but slow; requires Poco C++ ; most/all platforms
Steinway answered 22/5, 2009 at 21:16 Comment(9)
Apart from the one link you've gfiven, what are you basing your performance comments on?Gustavo
That's nearly your entire reputation from a single answer!! You lucky bean ;) I think 8 is standard C (of course also C++), but is probably worth differentiating.Article
2. is slow as std::to_string(age) creates a temporary string that is appended to the result.Litha
If you're on Arduino, you can also use String(number).Geodetic
I would add snprintf too maybe instread of sprintf.Pasahow
It would be much better to add a performance benchmark link here.Regatta
You know an answer is good when they have to list them in alphabetical order. =)Therapist
(8) would be less brittle if you at least used snprintf to make sure you don't overflow your buffer. You still need a buffer long enough, though.Sheedy
I believe fmt is now part of the ISO standard (in the format header), starting with C++20.Elenaelenchus
V
322

In C++11, you can use std::to_string, e.g.:

auto result = name + std::to_string( age );
Vulvitis answered 8/8, 2012 at 8:17 Comment(1)
same as before.Eldoree
S
92

If you have Boost, you can convert the integer to a string using boost::lexical_cast<std::string>(age).

Another way is to use stringstreams:

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

A third approach would be to use sprintf or snprintf from the C library.

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

Other posters suggested using itoa. This is NOT a standard function, so your code will not be portable if you use it. There are compilers that don't support it.

Sulphurate answered 10/10, 2008 at 15:11 Comment(4)
Note that snprintf is not guaranteed to null-terminate the string. Here's one way to make sure it works: <pre> char buffer[128]; buffer[sizeof(buffer)-1] = '\0'; snprintf(buffer, sizeof(buffer)-1, "%s%d", name.c_str(), age); std::cout << buffer << std::endl; </pre>Fabe
My tendency would be to never use sprintf, since this can result in buffer-overflows. The example above is a good example where using sprintf would be unsafe if the name was very long.Bunde
note that snprintf is equally non-standard c++ (like itoa which you mention). it's taken from c99Wholesome
@terson: I see no occurence of sprintf in the answer, only snprintf.Harveyharvie
G
84
#include <iostream>
#include <sstream>

std::ostringstream o;
o << name << age;
std::cout << o.str();
Gingrich answered 10/10, 2008 at 15:9 Comment(1)
this is great, BYT header file is sstreamRecipient
P
59
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
string itos(int i) // convert int to string
{
    stringstream s;
    s << i;
    return s.str();
}

Shamelessly stolen from http://www.research.att.com/~bs/bs_faq2.html.

Paredes answered 10/10, 2008 at 15:9 Comment(3)
but s is a stack variables, the memory of s will be free after invoke itos. s should allocate from heap, and free after using, right?Doucet
return by value is ok even though the string object has gone out of scope, https://mcmap.net/q/55311/-best-way-to-return-an-std-string-that-local-to-a-functionDoucet
The link is broken: "Page Not Found"Certainly
M
36

This is the easiest way:

string s = name + std::to_string(age);
Mcvay answered 21/12, 2014 at 21:50 Comment(1)
This is a post-C++11 solution!It
P
32

If you have C++11, you can use std::to_string.

Example:

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

name += std::to_string(age);

std::cout << name;

Output:

John21
Phraseograph answered 27/5, 2013 at 21:56 Comment(3)
It would be name += std::to_string(static_cast<long long>(age)); in VC++ 2010 as you can see hereBravado
@Bravado How about name += std::to_string(age + 0LL); instead?Sole
great solution. ThanksUnamuno
B
18

It seems to me that the simplest answer is to use the sprintf function:

sprintf(outString,"%s%d",name,age);
Better answered 10/10, 2008 at 15:56 Comment(3)
snprintf can be tricky (mainly because it can potentially not include the null character in certain situations), but I prefer that to avoid sprintf buffer overflows potential problems.Bunde
sprintf(char*, const char*, ...) will fail on some versions of compilers when you pass a std::string to %s. Not all, though (it's undefined behavior) and it may depend on string length (SSO). Please use .c_str()Courses
plus sprintf is subject to buffer overflows so possible code injectionChina
G
15
#include <string>
#include <sstream>
using namespace std;
string concatenate(std::string const& name, int i)
{
    stringstream s;
    s << name << i;
    return s.str();
}
Gayelord answered 10/10, 2008 at 15:12 Comment(0)
W
12
#include <sstream>

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

Then your usage would look something like this

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

Googled [and tested :p ]

Width answered 10/10, 2008 at 19:53 Comment(0)
M
12

You can do it with C++20 std::format (godbolt):

std::string name = "John";
int age = 21;
std::string result = std::format("{}{}", name, age);

If std::format is not available you can use the {fmt} library, it is based on:

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

Disclaimer: I'm the author of the {fmt} library and C++20 std::format.

Muhammad answered 29/4, 2018 at 17:12 Comment(4)
Hi @vitaut, does fmt::format supports dynamic inputstring? ex: fmt::format(variable,name,age)Hunnish
It does. You'll need to wrap the dynamic format string in fmt::runtime in fmt 8.xMuhammad
Hi @vitaut, how to make codes work with number: store.push_back(fmt::arg("1", "pi")); , this also throws exception fmt::vformat("{1} = {2}",store)Hunnish
Hi @vitaut, can i using fmt::format with SYSTEMTIME t;? fmt::format("{}",t); please give me an example. thanks you!Hunnish
N
10

This problem can be done in many ways. I will show it in two ways:

  1. Convert the number to string using to_string(i).

  2. Using string streams.

    Code:

    #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;
    }
    
Nuclear answered 29/6, 2018 at 3:39 Comment(1)
Which one is faster?Encephalomyelitis
W
8

As a one liner: name += std::to_string(age);

Walcoff answered 30/3, 2020 at 11:55 Comment(0)
R
6

If you'd like to use + for concatenation of anything which has an output operator, you can provide a template version of operator+:

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

Then you can write your concatenations in a straightforward way:

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

Output:

the answer is 42

This isn't the most efficient way, but you don't need the most efficient way unless you're doing a lot of concatenation inside a loop.

Release answered 3/11, 2011 at 13:26 Comment(4)
If I try to add to integers or an integer and a double, will this function be called ? I am wondering if this solution will override the usual additions...Tsarism
The operator returns a std::string, so wouldn't be a candidate in expressions where a string isn't convertible into the needed type. E.g., this operator+ isn't eligible to be used for + in int x = 5 + 7;. All things considered, I wouldn't define an operator like this without a very compelling reason, but my aim was to offer an answer different from the others.Release
You are right (I just tested it...). And when I tried to do something like string s = 5 + 7, I got the error invalid conversion from ‘int’ to ‘const char’*Tsarism
For most use cases, using templates that tie either the left or the right operand to a string (which includes std::string, std::string_view and const char *) should suffice.Mellette
H
5

If you are using MFC, you can use a CString

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

Managed C++ also has a string formatter.

Hedonics answered 10/10, 2008 at 17:13 Comment(0)
A
4

The std::ostringstream is a good method, but sometimes this additional trick might get handy transforming the formatting to a one-liner:

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

Now you can format strings like this:

int main() {
    int i = 123;
    std::string message = MAKE_STRING("i = " << i);
    std::cout << message << std::endl; // prints: "i = 123"
}
Acidimetry answered 10/10, 2008 at 22:8 Comment(2)
Why use a preprocessor #define instead of a template? With variadic templates, even several token could be passed in. But I am hesitant to use this, as the static_cast back to std::ostringstream on the output of the << operand is a bit unsafe. It is a convention, that all the outputters return a referene to the original stream object, but this is nowhere guaranteed in the standard.Mellette
You're commenting on a 12-year old answer. We have variadic templates now. I'd probably pick github.com/fmtlib/fmt now.Acidimetry
C
4

As a Qt-related question was closed in favour of this one, here's how to do it using Qt:

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

The string variable now has someIntVariable's value in place of %1 and someOtherIntVariable's value at the end.

Carlcarla answered 10/8, 2011 at 13:29 Comment(1)
QString("Something ") + QString::number(someIntVariable) also worksSchaper
Z
3

There are more options possible to use to concatenate integer (or other numerric object) with string. It is 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);
}

and Karma from 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 claims to be one of the fastest option for integer to string conversion.

Zincate answered 4/10, 2010 at 10:0 Comment(0)
E
3
  • 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));
Excaudate answered 3/8, 2018 at 7:9 Comment(1)
Which one is the fastest?Encephalomyelitis
C
2

Common Answer: itoa()

This is bad. itoa is non-standard, as pointed out here.

Cataldo answered 10/10, 2008 at 15:9 Comment(1)
itoa is non standard: #190729Acumen
P
2

Here is an implementation of how to append an int to a string using the parsing and formatting facets from the IOStreams library.

#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
}
Phraseograph answered 25/11, 2013 at 13:57 Comment(0)
N
2

You can concatenate int to string by using the given below simple trick, but note that this only works when integer is of single digit. Otherwise, add integer digit by digit to that string.

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

Output:  John5
Noteworthy answered 28/9, 2016 at 18:15 Comment(0)
A
1

There is a function I wrote, which takes the int number as the parameter, and convert it to a string literal. This function is dependent on another function that converts a single digit to its char equivalent:

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;
}
Asaasabi answered 28/8, 2013 at 13:23 Comment(0)
E
1

In C++ 20 you can have a variadic lambda that does concatenate arbitrary streamable types to a string in a few lines:

auto make_string=[os=std::ostringstream{}](auto&& ...p) mutable 
{ 
  (os << ... << std::forward<decltype(p)>(p) ); 
  return std::move(os).str();
};

int main() {
std::cout << make_string("Hello world: ",4,2, " is ", 42.0);
}

see https://godbolt.org/z/dEe9h75eb

using move(os).str() guarantees that the ostringstream object's stringbuffer is empty next time the lambda is called.

Englis answered 12/5, 2021 at 15:26 Comment(2)
Note that this lambda would not be thread-safe / re-entrant, unlike some of the other solutions presented here. That could be resolved by moving the ostringstream lifetime into the lambda body, and I don't think there's any benefit to keeping it initialized in the capture list (there won't be any memory reuse either way, due to the move).Tantara
In c++20 you could also use en.cppreference.com/w/cpp/utility/format/format unfortunatly libstdc++ gcc.gnu.org/onlinedocs/libstdc++/manual/status.html doesn't implement it yet. Clang's libc++ does (in trunk atm), and you can always fall back to fmtlib github.com/fmtlib/fmtGamboge
T
0

You can use the C function itoa() like this:

    char buf[3];
    itoa(age, buf, 10);
    name += buf;
Tyrus answered 13/1, 2023 at 1:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.