views:

23575

answers:

15

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

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

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

+3  A: 

Common Answer: itoa()

This is bad. itoa is non-standard, as pointed out in http://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux

Tom Ritter
itoa is non standard: http://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux
David Dibben
+10  A: 
tloach
+29  A: 
std::ostringstream o;
o << name << age;
std::cout << o.str();
Ben Hoffstein
+40  A: 

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.

Jay Conrod
Boost. The library that no C++ programmer should be without.
Chris Charabaruk
name << ss.str() would probably be more efficient than name + ss.str(). Also instead of using the literal 128 in snprintf, you should use sizeof(buffer). Numeric literals are nicer if they are used just once.
Ates Goral
Good points Ates. I've updated the code to reflect this.
Jay Conrod
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>
Mr Fooz
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.
terson
note that snprintf is equally non-standard c++ (like itoa which you mention). it's taken from c99
Johannes Schaub - litb
+6  A: 
#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
+6  A: 

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

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

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.
terson
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()
MSalters
+7  A: 

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.

Fred Larson
+2  A: 

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:

bsruth
+1  A: 
#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 ]

Zing-
A: 

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"
}
pyrtsa
Ick. I think I'd rather use an inline function, thank you.
T.E.D.
A: 

EDITED: My former version was incorrectly written. Here's a quick one using the sprintf_s functionality.

#include <iostream>
#include <string>
using namespace std;
int main()
{
   char name[] = "John";
   int age = 21;
   char nameAndAge[50];
   sprintf_s(nameAndAge,"%s%d",name,age);
   cout << nameAndAge << endl;
   return 0;
}
SauceMaster
Did you actually try this? I'm certain that std::string doesn't support these operations -- how would it know how you want the number formatted, etc? Maybe you are using some kind of extended string class that allows these operations, but it's not in the standard...
Adrian
...Yeah, you are right. I did not test this in a development environment. I think I did a little mixing of Java and C++ there. Thanks for pointing out the mistake. A corrected version will be posted.
SauceMaster
+4  A: 

I don't have karma enough to comment (let alone edit), but Jay's post (currently the top-voted one at 27) contains an error. This code:

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

Does not solve the stated problem of creating a string consisting of a concatenated string and integer. I think Jay meant something more like this:

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

The final line is just to print the result, and shows how to access the final concatenated string.

unwind
A: 

If using sstream for completeness refer to http://stackoverflow.com/questions/20731/in-c-how-do-you-clear-a-stringstream-variable. Continued use of the stringstream variable causes grief, e.g.

char loop = 'n'; //y to continue looping
int count = 1; 
stringstream out;
string prefix;
do
{
    out << count;
    prefix = out.str();
    //out.str("");//uncomment to clear the stream
    cout << prefix << endl; 
    cout << "Continue (y/n): ";
    cin >> loop;
    cout << endl;
    count++;
}while(tolower(loop) == 'y');
topcat
+19  A: 

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 FastFormat.Format
fastformat::fmt(result, "{0}{1}", name, age);

// 3. with FastFormat.Write
fastformat::write(result, name, age);

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

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

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

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

// 8. with STLSoft's winstl::int_to_string()
result = name + winstl::int_to_string(age);
  1. is safe, but slow; requires Boost (header-only); most/all platforms
  2. is safe, and fast; requires FastFormat, which must be compiled; most/all platforms
  3. is safe, and fast; requires FastFormat, which must be compiled; most/all platforms
  4. safe, slow, and verbose; requires nothing (is standard C++)
  5. 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
  6. is brittle (you must supply a large enough buffer), fast, and verbose; requires nothing (is standard C++); all platforms
  7. is brittle (you must supply a large enough buffer), probably the fastest-possible conversion, verbose; requires STLSoft (header-only); most/all platforms
  8. safe-ish (you not use more than one int_to_string() call in a single statement), fast; requires STLSoft (header-only); Windows-only
DannyT
Apart from the one link you've gfiven, what are you basing your performance comments on?
JamieH
+1 for detailed and complete answer
deuberger
See http://tinyurl.com/234rq9u for a comparison of some of the solutions
Luca Martini
A: 

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.

mloskot