Alternative to itoa() for converting integer to string C++? [duplicate]
Asked Answered
E

18

160

I was wondering if there was an alternative to itoa() for converting an integer to a string because when I run it in visual Studio I get warnings, and when I try to build my program under Linux, I get a compilation error.

Elianaelianora answered 23/10, 2008 at 0:17 Comment(4)
Basically the inverse of this question. #200590 Answer is the same though.Garvy
How about some of the examples from the following: codeproject.com/KB/recipes/Tokenizer.aspx They are very efficient and somewhat elegant.Newsom
You can see here a benchmark comparing 3 modern C+ ways of converting integers to stringsWoodcock
I had the same requirement for a function in C. I'm sure you can figure out how to wrap in in C++. It is thread-safe and handles all positive, negative 32 bit integer numbers, and zero. The performance is EXCELLENT, and the algorithm is lean, so it doesn't soak up a lot of cache. Ben Voigt has a faster approach, but it's not a lightweight algorithm, so unless you are doing billions of these things, it maybe overkill.Vegetable
S
195

In C++11 you can use std::to_string:

#include <string>

std::string s = std::to_string(5);

If you're working with prior to C++11, you could use C++ streams:

#include <sstream>

int i = 5;
std::string s;
std::stringstream out;
out << i;
s = out.str();

Taken from http://notfaq.wordpress.com/2006/08/30/c-convert-int-to-string/

Sd answered 23/10, 2008 at 0:31 Comment(8)
Too bad Windows CE derived platforms doesn't have iostreams by default. The way to go there is preferaby with the _itoa<> family.Nonappearance
how do you clear the stringstream?Elianaelianora
net.pku.edu.cn/~course/cs101/resource/www.cppreference.com/…Sd
I suppose you mean: cppreference.com/cppsstream/all.htmlLynnelynnea
stringstream is nice but be aware that it can dramatically increase the size of the executable.Rasia
(for non C++11) There is also boost::to_string boost.org/doc/libs/1_51_0/boost/exception/to_string.hppWarlike
@Rasia You can see here a benchmark comparing 3 modern C+ ways of converting integers to strings and in one the answers common mistakes related to the use of stringstreamWoodcock
@NikosAthanasiou Excellent reference, thanks. It doesn't mention the size of the executable generated. I've seen gcc add megabytes of unused code to the executable.Rasia
R
56

boost::lexical_cast works pretty well.

#include <boost/lexical_cast.hpp>
int main(int argc, char** argv) {
    std::string foo = boost::lexical_cast<std::string>(argc);
}
Roseannroseanna answered 23/10, 2008 at 0:19 Comment(7)
Taking the Boost library for a single cast. :(Sparke
But if you're already using Boost, it's a freebie.Sardonyx
boost::lexical_cast is painfully slow. Do not use it if performance is important.Newsom
I think worrying about that is premature optimization in most cases. It wouldn't stop me from using it unless my profiler told me otherwise.Roseannroseanna
Painfully slow? Where did you get that? It actually performs rather well! boost.org/doc/libs/1_49_0/doc/html/boost_lexical_cast/…Pteranodon
@Pteranodon To clarify, lexical_cast is claimed to outperform both sprintf and stringstream by a lot (scroll to bottom), except for string->float and float->string, where sprintf is the winner.Fredela
@Fredela You can see here a benchmark comparing 3 modern C+ ways of converting integers to strings and the actual performance of lexical castWoodcock
C
51

Archeology

itoa was a non-standard helper function designed to complement the atoi standard function, and probably hiding a sprintf (Most its features can be implemented in terms of sprintf): http://www.cplusplus.com/reference/clibrary/cstdlib/itoa.html

The C Way

Use sprintf. Or snprintf. Or whatever tool you find.

Despite the fact some functions are not in the standard, as rightly mentioned by "onebyone" in one of his comments, most compiler will offer you an alternative (e.g. Visual C++ has its own _snprintf you can typedef to snprintf if you need it).

The C++ way.

Use the C++ streams (in the current case std::stringstream (or even the deprecated std::strstream, as proposed by Herb Sutter in one of his books, because it's somewhat faster).

Conclusion

You're in C++, which means that you can choose the way you want it:

  • The faster way (i.e. the C way), but you should be sure the code is a bottleneck in your application (premature optimizations are evil, etc.) and that your code is safely encapsulated to avoid risking buffer overruns.

  • The safer way (i.e., the C++ way), if you know this part of the code is not critical, so better be sure this part of the code won't break at random moments because someone mistook a size or a pointer (which happens in real life, like... yesterday, on my computer, because someone thought it "cool" to use the faster way without really needing it).

Circumpolar answered 23/10, 2008 at 7:17 Comment(15)
The C way isn't necessarily faster - remember *printf() and family have to implement their own runtime lexical engine to parse your input string - the C++ version doesn't have this limitation.Sardonyx
@Chris Kaminski: My one tests did show the sprintf was a 5 to ten times faster, which is confirmed my Herb Sutter's own measurements. if you have tests with different results, I'm interested.Circumpolar
@Chris Kaminski: If you study the c++ stream's interface, you'll understand why they are slower, even when output a simple integer: In C, you use your own buffer, possibly allocated in the stack, whereas in C++, the stringstream will use its own. In C, you can then reuse your buffer. In C++, you must extract the string from the stringstream, which is a std::string copy.Circumpolar
If you need fast int-to-string, you can write a quick function that's faster than any generic library call; just keep taking %10 and /10, and fill a static buffer from the back, returning a pointer to the highest digit. Don't use sprintf, this is a security flaw.Truculent
@Truculent : Do you have performance comparison between a generic sprintf and your quick function?Circumpolar
@paercebal: A performance comparison is going to differ widely depending on platform and library version, but you can see at sourceware.org/git/?p=glibc.git;a=blob;f=stdio-common/… that in glibc at least, the itoa function (which is called by sprintf) is my quick function; the difference is that it is nested inside a number of unnecessary jump tables to handle bases and string formatting, and is hidden behind an uninlineable library call. It usually gives better results to make your own optimized functions if you need fast specific tasks.Truculent
@Truculent : Ok. Interesting to know, and a good exercise for a coder, but as far as I am concerned (following the "premature optimization is the root of all evil" principle), most of the time (i.e. 99% of the time), a one-line sprintf(buffer, "%i") safely wrapped in a function or object will be more than enough if performance is an issue forbidding the use of the iostreams, and less as source of bugs than a fully hand-coded function.Circumpolar
@paercebal: I can see that. You should really never use sprintf -- if your code is ever used on a system where the width of an integer allows values outside the size of your buffer (or you forget to allow for a negative sign or the trailing \0 or misguess the number of base ten digits available), you will have crashes and potential security problems. snprintf and itoa are safer and comparable in speed (itoa should be faster with modern gcc). The C++ standard library now includes the to_string optimized template functions anyway, which resolve all this craziness once and for all.Truculent
@Truculent : Thanks for your concern, but I guess I'm familiar enough with both C API and C++ API to handle sprintf, and know when (and how) to use it safely, and when NOT to use it at all... :-DCircumpolar
@paercebal: But why get in the habit of using sprintf, which will probably emit a warning on secure systems even if used safely, when snprintf is available? How can you know that a standard library will convert values to strings of a given length in any possible system your code will be compiled on? In glibc, a user of code you write may have redefined a format specifier: gnu.org/software/libc/manual/html_node/… ! It is impossible to know for sure how much data sprintf will write except in a restricted environment. Don't use it in production code.Truculent
@fuzzyTew: 1 In my post, I spoke about sprintf and its secure variants, not only sprintf. 2 Knowing where your code is compiled is not an impossible task (in my case, at worst, Windows/VC++, Solaris/CC and Linux/g++, at best, Windows/VC++ only). 3 You are describing a world where saboteurs trying to crash your code are the norm. My world is composed by normal developers, so losing time trying to protect my code from saboteurs by rewriting my "secure" version of every API is not productive. [...]Circumpolar
@fuzzyTew: [...] Conclusion Use the best tool at hand. And if the best tool is a sprintf hidden inside a wrapper class or function... Now, if you advocate the rewriting of sprintf as an answer for this question, feel free to write your own answer. I'm not sure the question author reads all the comments.Circumpolar
You can see here a benchmark comparing 3 modern C+ ways of converting integers to stringsWoodcock
sprintf is also pretty slow compared to a proper itoa implementation.Typewritten
This solves most data->string issues in a reusable manner: #2342662Typewritten
P
39

Try sprintf():

char str[12];
int num = 3;
sprintf(str, "%d", num); // str now contains "3"

sprintf() is like printf() but outputs to a string.

Also, as Parappa mentioned in the comments, you might want to use snprintf() to stop a buffer overflow from occuring (where the number you're converting doesn't fit the size of your string.) It works like this:

snprintf(str, sizeof(str), "%d", num);
Plebiscite answered 23/10, 2008 at 0:21 Comment(5)
sprintf() isn't C++. It's C.Vibes
You should use snprintf() to avoid buffer overflows. It's only a one line change in the above example: snprintf(str, sizeof(str), "%d", num);Poetry
IMHO Stringstreams would be a better option.Force
OJ: sprintf is c++ too... most C stuff works in c++. this is not an accident. c++ was intended to be a "layer" on top of c++... not a defining architecture like it's (probably to a fault) becomeTypewritten
The type of str in function: sprintf is 'str', but question should be 'string'.Nipper
B
20

Behind the scenes, lexical_cast does this:

std::stringstream str;
str << myint;
std::string result;
str >> result;

If you don't want to "drag in" boost for this, then using the above is a good solution.

Biddle answered 23/10, 2008 at 0:32 Comment(3)
I doubt it would stream into the string when str.str() would suffice.Deemster
if lexical_cast does this, how is the big gap in performance explained?Woodcock
Didn't he explain that in the question you linked as being due to creating stringstream objects every time?Biddle
N
13

С++11 finally resolves this providing std::to_string. Also boost::lexical_cast is handy tool for older compilers.

Neman answered 17/5, 2012 at 19:9 Comment(0)
D
13

We can define our own iota function in c++ as:

string itoa(int a)
{
    string ss="";   //create empty string
    while(a)
    {
        int x=a%10;
        a/=10;
        char i='0';
        i=i+x;
        ss=i+ss;      //append new character at the front of the string!
    }
    return ss;
}

Don't forget to #include <string>.

Drugge answered 2/11, 2012 at 21:14 Comment(0)
G
9

I use these templates

template <typename T> string toStr(T tmp)
{
    ostringstream out;
    out << tmp;
    return out.str();
}


template <typename T> T strTo(string tmp)
{
    T output;
    istringstream in(tmp);
    in >> output;
    return output;
}
Gallup answered 28/8, 2011 at 18:46 Comment(1)
These are good but unfortunately lack error handling.Deemster
P
7

Try Boost.Format or FastFormat, both high-quality C++ libraries:

int i = 10;
std::string result;

WIth Boost.Format

result = str(boost::format("%1%", i));

or FastFormat

fastformat::fmt(result, "{0}", i);
fastformat::write(result, i);

Obviously they both do a lot more than a simple conversion of a single integer

Pejorative answered 22/5, 2009 at 21:28 Comment(0)
R
6

You can actually convert anything to a string with one cleverly written template function. This code example uses a loop to create subdirectories in a Win-32 system. The string concatenation operator, operator+, is used to concatenate a root with a suffix to generate directory names. The suffix is created by converting the loop control variable, i, to a C++ string, using the template function, and concatenating that with another string.

//Mark Renslow, Globe University, Minnesota School of Business, Utah Career College
//C++ instructor and Network Dean of Information Technology

#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream> // string stream
#include <direct.h>

using namespace std;

string intToString(int x)
{
/**************************************/
/* This function is similar to itoa() */
/* "integer to alpha", a non-standard */
/* C language function. It takes an   */
/* integer as input and as output,    */
/* returns a C++ string.              */
/* itoa()  returned a C-string (null- */
/* terminated)                        */
/* This function is not needed because*/
/* the following template function    */
/* does it all                        */
/**************************************/   
       string r;
       stringstream s;

       s << x;
       r = s.str();

       return r;

}

template <class T>
string toString( T argument)
{
/**************************************/
/* This template shows the power of   */
/* C++ templates. This function will  */
/* convert anything to a string!      */
/* Precondition:                      */
/* operator<< is defined for type T    */
/**************************************/
       string r;
       stringstream s;

       s << argument;
       r = s.str();

       return r;

}

int main( )
{
    string s;

    cout << "What directory would you like me to make?";

    cin >> s;

    try
    {
      mkdir(s.c_str());
    }
    catch (exception& e) 
    {
      cerr << e.what( ) << endl;
    }

    chdir(s.c_str());

    //Using a loop and string concatenation to make several sub-directories
    for(int i = 0; i < 10; i++)
    {
        s = "Dir_";
        s = s + toString(i);
        mkdir(s.c_str());
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}
Rendarender answered 4/5, 2010 at 20:12 Comment(0)
H
4

Allocate a string of sufficient length, then use snprintf.

Homburg answered 23/10, 2008 at 0:22 Comment(0)
R
2
int number = 123;

stringstream = s;

s << number;

cout << ss.str() << endl;
Rhonarhonchus answered 27/6, 2011 at 14:16 Comment(0)
E
2

If you are interested in fast as well as safe integer to string conversion method and not limited to the standard library, I can recommend the format_int method from the {fmt} library:

fmt::format_int(42).str();   // convert to std::string
fmt::format_int(42).c_str(); // convert and get as a C string
                             // (mind the lifetime, same as std::string::c_str())

According to the integer to string conversion benchmarks from Boost Karma, this method several times faster than glibc's sprintf or std::stringstream. It is even faster than Boost Karma's own int_generator as was confirm by an independent benchmark.

Disclaimer: I'm the author of this library.

Emlynn answered 29/4, 2014 at 17:32 Comment(0)
V
2

I wrote this thread-safe function some time ago, and am very happy with the results and feel the algorithm is lightweight and lean, with performance that is about 3X the standard MSVC _itoa() function.

Here's the link. Optimal Base-10 only itoa() function? Performance is at least 10X that of sprintf(). The benchmark is also the function's QA test, as follows.

start = clock();
for (int i = LONG_MIN; i < LONG_MAX; i++) {
    if (i != atoi(_i32toa(buff, (int32_t)i))) {
        printf("\nError for %i", i);
    }
    if (!i) printf("\nAt zero");
}
printf("\nElapsed time was %f milliseconds", (double)clock() - (double)(start));

There are some silly suggestions made about using the caller's storage that would leave the result floating somewhere in a buffer in the caller's address space. Ignore them. The code I listed works perfectly, as the benchmark/QA code demonstrates.

I believe this code is lean enough to use in an embedded environment. YMMV, of course.

Vegetable answered 1/7, 2014 at 7:54 Comment(0)
T
2

The best answer, IMO, is the function provided here:

http://www.jb.man.ac.uk/~slowe/cpp/itoa.html

It mimics the non-ANSI function provided by many libs.

char* itoa(int value, char* result, int base);

It's also lightning fast and optimizes well under -O3, and the reason you're not using c++ string_format() ... or sprintf is that they are too slow, right?

Typewritten answered 7/7, 2014 at 20:42 Comment(2)
This is the only answer that fully answers the question. The C++ to_string() method does not replicate the full functionality of C's itoa as it cannot deal with arbitrary bases. A little confusing why this functionality wouldn't have been included, especially considering that the inverse function stoi() can handle arbitrary bases.Adnah
Updated link (same article): strudel.org.uk/itoaParasitic
D
1

Note that all of the stringstream methods may involve locking around the use of the locale object for formatting. This may be something to be wary of if you're using this conversion from multiple threads...

See here for more. Convert a number to a string with specified length in C++

Drivel answered 23/10, 2008 at 6:45 Comment(0)
N
0

On Windows CE derived platforms, there are no iostreams by default. The way to go there is preferaby with the _itoa<> family, usually _itow<> (since most string stuff are Unicode there anyway).

Nonappearance answered 23/10, 2008 at 17:34 Comment(0)
V
-1

Most of the above suggestions technically aren't C++, they're C solutions.

Look into the use of std::stringstream.

Vibes answered 23/10, 2008 at 0:31 Comment(1)
@OJ: "technically aren't C++" - That's nitpicking (and to nitpick further, as onebyone mentions most of them are technically in C++), especially since the OP was looking for a no-warning replacement for itoa().Avian

© 2022 - 2024 — McMap. All rights reserved.