Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is there a STL equivalent of sprintf

1,085 views
Skip to first unread message

WJ

unread,
Dec 17, 2008, 11:51:01 AM12/17/08
to
I want to convert a number (int or float) to std::string, just wondering if
there is a STL class or function can do that.

I have been using sprintf, but I have to declear char[] array, and then set
the std::string to be the temp char[] array.

Thanks.

Cholo Lennon

unread,
Dec 17, 2008, 12:05:16 PM12/17/08
to

Just use std::stringstream:

#include <sstream>
#include <iostream>

...
std::stringstream ss;
ss << 3.18;

std::cout << ss.str();


Regards

--
Cholo Lennon
Bs.As.
ARG

Duane Hebert

unread,
Dec 17, 2008, 11:59:38 AM12/17/08
to

"WJ" <W...@discussions.microsoft.com> wrote in message
news:4C301E65-CA9A-4BCC...@microsoft.com...

If you use boost libs, try boost format.

Cholo Lennon

unread,
Dec 17, 2008, 12:21:18 PM12/17/08
to

If you want a function:

template<typename TRes, typename TArg>
TRes ConvertTo(const TArg &rArg)
{
std::stringstream ss;
ss << rArg;
TRes res = TRes();
ss >> res;
return res;
}

...

using std::string;
string str1 = ConvertTo<string>(35);
string str2 = ConvertTo<string>(4.5);
double d = ConvertTo<double>("45.67");


For more details (constraints and advantages) take a look to boost::lexical_cast

http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm

WJ

unread,
Dec 17, 2008, 12:17:01 PM12/17/08
to
Thanks!

Wanjun

"Cholo Lennon" wrote:

> WJ wrote:
> > I want to convert a number (int or float) to std::string, just
> > wondering if there is a STL class or function can do that.
> >
> > I have been using sprintf, but I have to declear char[] array, and
> > then set the std::string to be the temp char[] array.
> >
> > Thanks.
>
> Just use std::stringstream:
>
> #include <sstream>
> #include <iostream>
>

> ....

Hendrik Schober

unread,
Dec 18, 2008, 3:27:12 AM12/18/08
to
Cholo Lennon wrote:
> Cholo Lennon wrote:
>> WJ wrote:
>>> I want to convert a number (int or float) to std::string, just
>>> wondering if there is a STL class or function can do that.
>>>
>>> I have been using sprintf, but I have to declear char[] array, and
>>> then set the std::string to be the temp char[] array.
>>>
>>> Thanks.
>> Just use std::stringstream:
>>
>> #include <sstream>
>> #include <iostream>
>>
>> ...
>> std::stringstream ss;
>> ss << 3.18;
>>
>> std::cout << ss.str();
>>
>
> If you want a function:
>
> template<typename TRes, typename TArg>
> TRes ConvertTo(const TArg &rArg)
> {
> std::stringstream ss;
> ss << rArg;
> TRes res = TRes();
> ss >> res;
> return res;
> }
>
> [...]

However, you probably want this to check ('ss.good()')
whether the conversion actually worked.

Schobi

Ulrich Eckhardt

unread,
Dec 18, 2008, 5:11:38 AM12/18/08
to
Duane Hebert wrote:
> "WJ" <W...@discussions.microsoft.com> wrote in message
> news:4C301E65-CA9A-4BCC...@microsoft.com...
>>I want to convert a number (int or float) to std::string, just wondering
>>if there is a STL class or function can do that.
[...]
> If you use boost libs, try boost format.

...or boost::lexical_cast.

;)

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Duane Hebert

unread,
Dec 18, 2008, 10:01:21 AM12/18/08
to

"Ulrich Eckhardt" <eckh...@satorlaser.com> wrote in message
news:r7kp16-...@satorlaser.homedns.org...

> Duane Hebert wrote:
>> "WJ" <W...@discussions.microsoft.com> wrote in message
>> news:4C301E65-CA9A-4BCC...@microsoft.com...
>>>I want to convert a number (int or float) to std::string, just wondering
>>>if there is a STL class or function can do that.
> [...]
>> If you use boost libs, try boost format.
>
> ...or boost::lexical_cast.
>
> ;)

Yep. But boost::format is a closer match to sprintf.

Daniel Lidström

unread,
Dec 19, 2008, 9:24:12 AM12/19/08
to
"WJ" <W...@discussions.microsoft.com> wrote in message
news:4C301E65-CA9A-4BCC...@microsoft.com...


Hi,

I have written a safe sprintf-like function using boost:.format.

You would use it like this:

char buff[1024];
sprintf(buff) % "%d" % 5;

It works with wchar_t as well.

This function will check that there was no overflow of the buffer, and
throws an exception if there was.
If you already have a lot of sprintf's, like we do, then you can safely
change them to use this method to
improve the type safety. On the other hand, if you are writing code from
scratch, you are better off using
boost:.format directly.

Anyway, here's the beauty:

#include <boost/format.hpp> // boost::basic_format

namespace Util
{
namespace detail
{
template<class Char>
class feeder
{ };

template<class Char, std::size_t N>
class feeder<Char[N]>
{
typedef typename boost::basic_format<Char> format_type;
typedef typename std::basic_string<Char> string_type;

format_type format;
Char* buffer;

public:

feeder(Char* b)
: buffer(b)
{ }

~feeder()
{
string_type result = str(format);
if( result.size()>=N )
throw std::logic_error("buffer overflow in sprintf");
std::copy(result.begin(), result.end(), buffer);
buffer[result.size()] = 0;
}

//! Format string
format_type& operator%(const Char* c)
{
format.parse(c);
return format;
}

format_type& operator%(const string_type& s)
{
format.parse(s);
return format;
}
};
}

//!
//! Type-safe sprintf. Use like this:
//! char buff[1024];
//! sprintf(buff) % "%d" % 5;
//!
//! @param buffer Buffer to write to
//!
template<class Source>
typename detail::feeder<Source> sprintf(Source& buffer)
{
typedef typename detail::feeder<Source> Feeder;
return Feeder(buffer);
}
}

Andre Kaufmann

unread,
Feb 19, 2009, 5:12:20 AM2/19/09
to

The C++ replacement for sprintf - stringstream - is O.K. for a small
number of conversions.

But if you have to convert a huge number of integers (> 100000) or build
huge strings I wouldn't recommend its usage, because IMHO it's painfully
slow.

And what's quite "funny", if you want to use stringstream to prevent the
usage of sprintf you do it perhaps anyways, because stringstream
implementations often use sprintf internally (or the safe version
sprintf_s).

Andre

Mateusz Loskot

unread,
Feb 21, 2009, 6:42:00 AM2/21/09
to
Andre Kaufmann pisze:

> WJ wrote:
>> I want to convert a number (int or float) to std::string, just
>> wondering if there is a STL class or function can do that.
>>
>> I have been using sprintf, but I have to declear char[] array, and
>> then set the std::string to be the temp char[] array.
>> Thanks.
>
> The C++ replacement for sprintf - stringstream - is O.K. for a small
> number of conversions.
>
> But if you have to convert a huge number of integers (> 100000) or build
> huge strings I wouldn't recommend its usage, because IMHO it's painfully
> slow.

Do you have any numbers/benchmarks in mind?

If the std:: thing indeed works slow for you, there
seems to be an alternative:

http://msobczak.com/prog/fastreams/

Best regards,
--
Mateusz Loskot, http://mateusz.loskot.net
Charter Member of OSGeo, http://osgeo.org

Andre Kaufmann

unread,
Feb 21, 2009, 3:02:15 PM2/21/09
to
Mateusz Loskot wrote:
> Andre Kaufmann pisze:
>> [...]

>> But if you have to convert a huge number of integers (> 100000) or
>> build huge strings I wouldn't recommend its usage, because IMHO it's
>> painfully slow.
>
> Do you have any numbers/benchmarks in mind?

Well I've converted Pascal code to C++, which read ASCII integers from a
text file and converted them to their binary representation.
The original code needed some milliseconds, while the C++ one which used
stringstreams needed multiple seconds.

E.g.: (opposite conversion integer to string)

C#:
for (int i = 0; i < 1000000; ++i) { string s = i.ToString(); }

C++:
for (int i = 0; i < 1000000; ++i)
{
std::stringstream s; s << i;
std::string x = s.str();
}

The C# code on my computer is

12 times faster

than the C++ code.

It's not a representative example and I don't hope that some
optimizations caused the difference, but since in more complex programs
I experience the same speed difference I doubt it.


> If the std:: thing indeed works slow for you, there
> seems to be an alternative:
>
> http://msobczak.com/prog/fastreams/

Thank you for the link. Perhaps a good replacement.

Although I think generally it's some kind of overkill to create an
object just for a simple task like string conversion.
(same applies to string to integer/object conversion)

In our current project we implemented a flat overloaded function in C++
named namespace::ToString(...) which can convert all C++ native types
and most of our objects to a std::string / std::wstring. This
implementation is using either std::stringstream (for rarely used
conversions) or (!much!) faster replacements.

I know the power of streams and the flexibility of the template based
implementation of them. But I have the impression that sometimes an
optional and more "lightweight" implementation would be more appropriate.


> Best regards,
Best regards too,
Andre

Mateusz Loskot

unread,
Feb 25, 2009, 9:07:37 AM2/25/09
to
Andre Kaufmann wrote:
> I know the power of streams and the flexibility of the template based
> implementation of them. But I have the impression that sometimes an
> optional and more "lightweight" implementation would be more appropriate.

I completely agree with this.

Stephen Howe

unread,
Mar 2, 2009, 10:01:38 AM3/2/09
to
On Thu, 19 Feb 2009 11:12:20 +0100, Andre Kaufmann
<andre.kaufm...@t-online.de> wrote:

>The C++ replacement for sprintf - stringstream - is O.K. for a small
>number of conversions.

Have you considered ostrstream or istrstream with a fixed size buffer?
You have to remember to nul terminate final input/output (or use ends
manipulator).

With no dynamic memory underneath, they are faster.
Yes deprecated but they will still be around 20 years from now.
They are in the standard.

Stephen Howe

Andre Kaufmann

unread,
Mar 2, 2009, 1:40:36 PM3/2/09
to
Stephen Howe wrote:
> On Thu, 19 Feb 2009 11:12:20 +0100, Andre Kaufmann
> <andre.kaufm...@t-online.de> wrote:
>
>> The C++ replacement for sprintf - stringstream - is O.K. for a small
>> number of conversions.
>
> Have you considered ostrstream or istrstream with a fixed size buffer?

Thank you for the hint - good idea.
I've played around with various optimization before and I think I've
tested fix buffers too. But I'm not sure about that.
But to play it safe I tried it again - results see below.
I've also disabled synchronization etc. but got no significant speed
increase.

> You have to remember to nul terminate final input/output (or use ends
> manipulator).
>
> With no dynamic memory underneath, they are faster.

Yes, they are. But unfortunately they are still (much) slower than using
sprintf. I think this is not only due to memory allocations but also due
to a deep call hierarchy and complex code, which can't be easily
optimized by the compiler.

Since sprintf is used internally in stringstreams I don't see a
performance advantage to prefer the stream library for string conversion
of integers. A simple wrapper function

typename<T> std::string ToString(const T& value);

Specialized for native types is IMHO more convenient and faster (if
sprintf is used) than stringstream.


> Yes deprecated but they will still be around 20 years from now.
> They are in the standard.

Yep - but I think the whole iostream library should be
rewritten/redesigned with both in mind - simplicity >and< performance.
The STL for example is a good example - regarding performance.

> Stephen Howe

Andre

Stephen Howe

unread,
Mar 5, 2009, 4:54:56 PM3/5/09
to

>Yep - but I think the whole iostream library should be
>rewritten/redesigned with both in mind - simplicity >and< performance.
>The STL for example is a good example - regarding performance.

I agree. While sprintf() is type unsafe and you can get buffer
overflow problems, it amounts to 1 function call. It is fast.

All those << operators are separate functions.
I have yet to find an iostream package that is within 10% of stdio.
I think iostream needs a complete rethink.

Stephen Howe

Hendrik Schober

unread,
Mar 10, 2009, 5:21:46 AM3/10/09
to

I think the problem is that IO streams usually are implemented
on top of C IO. That makes for a convenient implementation, but
turns the advantages C++ has into disadvantages.
Theoretically, IO streams might be faster than C IO, since they
don't have to find out about types at run-time, as C IO has by
parsing formatting strings. With streams, output types are known
at compile-time.
However, if the only use of this advantage is to create the
appropriate formatting string for forwarding the request to
'printf()', that certainly makes C++' IO streams slower than
using C IO directly.
Dietmar Kühl once had a C++ IO stream library which was said to
be faster than C IO. Unfortunately there seems to not to have
been enough interest and the project died.

> Stephen Howe

Schobi

Ulrich Eckhardt

unread,
Mar 11, 2009, 4:03:15 AM3/11/09
to
Stephen Howe <sjhoweATdialDOTpipexDOTcom> wrote:
>>Yep - but I think the whole iostream library should be
>>rewritten/redesigned with both in mind - simplicity >and< performance.
>>The STL for example is a good example - regarding performance.
>
> I agree. While sprintf() is type unsafe and you can get buffer
> overflow problems, it amounts to 1 function call. It is fast.
>
> All those << operators are separate functions.

Not so much, as those are inlined. What definitely is a separate function
call is the invocation of formatters or parsers from the locale, as those
are implemented as virtual functions within a plugin mechanism.

> I have yet to find an iostream package that is within 10% of stdio.
> I think iostream needs a complete rethink.

Ahem, IOStreams are a flexible formatting and parsing framework that uses a
plugin mechanism for the actual work. This is _by far_ not functionally
equivalent to C stdio, so you are comparing apples to oranges. Further,
there are several pitfalls for performance:
1. Disable synchronisation with C stdio (ios_base::sync_with_stdio(false);).
2. Don't use obsolete implementations, e.g. VC6 used to increase the size of
a stringbuffer in steps of 32 bytes, IIRC, which is a performance nightmare
when writing more than that.
3. Use the C locale. Since this uses a fixed formatting, some steps could be
optimised or skipped there.
4. If you know the formatting you want, you can also use e.g. num_put
directly instead of indirectly through a stringstream.

That said, there definitely are some design issues within the IOStreams,
e.g. the naming of functions.

Andre Kaufmann

unread,
Mar 20, 2009, 11:49:31 AM3/20/09
to
Ulrich Eckhardt wrote:
> Stephen Howe <sjhoweATdialDOTpipexDOTcom> wrote:
> [...]

> Ahem, IOStreams are a flexible formatting and parsing framework that uses a
> plugin mechanism for the actual work. This is _by far_ not functionally
> equivalent to C stdio, so you are comparing apples to oranges. Further,


It's flexible - for sure. But why do I have to pay for all that
flexibility ?
I think it's overkill for most of the daily tasks a C++ programmer has
to do.

E.g. I like the printf format more than the iostream format, so I wrote
my own type safe implementation:

E.g.:

"Num: {0} to directory: {1} drive: {2}", numFiles, dir, drive

is IMHO more readable as:

"Num: " << numFiles << " to directory: " << dir << " drive: " << driver

And it's even faster than iostream.

> there are several pitfalls for performance:
> 1. Disable synchronisation with C stdio (ios_base::sync_with_stdio(false);).

Doesn't have a significant effect (for my tests)

> 2. Don't use obsolete implementations, e.g. VC6 used to increase the size of
> a stringbuffer in steps of 32 bytes, IIRC, which is a performance nightmare
> when writing more than that.

Nobody should use VC6 anymore - really ;-)

> [...]

> 4. If you know the formatting you want, you can also use e.g. num_put
> directly instead of indirectly through a stringstream.
> That said, there definitely are some design issues within the IOStreams,
> e.g. the naming of functions.

I agree the function names, are an issue too, but definitively I would
complain more about the performance of iostreams than about the function
names. It's just a bad joke (for me) if the language, known to have one
of the best optimizing compilers, is outperformed by e.g. .NET IO in
such simple tasks like, string conversion / writing numbers to files.

> Uli

Andre

Ulrich Eckhardt

unread,
Mar 23, 2009, 5:35:52 AM3/23/09
to
Andre Kaufmann wrote:
> Ulrich Eckhardt wrote:
>> Stephen Howe <sjhoweATdialDOTpipexDOTcom> wrote:
>> [...]
>> Ahem, IOStreams are a flexible formatting and parsing framework that uses
>> a plugin mechanism for the actual work. This is _by far_ not functionally
>> equivalent to C stdio, so you are comparing apples to oranges. Further,
>
>
> It's flexible - for sure. But why do I have to pay for all that
> flexibility ?

You don't, just use something else. You could e.g. format the data with
dedicated functions and still use e.g. std::filebuf for writing.

> I think it's overkill for most of the daily tasks a C++ programmer has
> to do.

I regularly need to write different Unicode encodings or codepages. I
regularly redirect streams by changing their target streambuffer. I
regularly need to change the output format to the C locale for file IO
while I still need the local culture's output format for user IO. I
generally don't care much for formatting performance because IO throughput
is much (s)lower anyway.

Andre, I understand your point and I particularly agree that formatting with
iostreams tends to become unreadable (hence Boost.Format and similar
things). I don't think it's the only side though.

Greetings!

Andre Kaufmann

unread,
Mar 23, 2009, 12:27:31 PM3/23/09
to
Ulrich Eckhardt wrote:

> Andre Kaufmann wrote:
>> It's flexible - for sure. But why do I have to pay for all that
>> flexibility ?
>
> You don't, just use something else. You could e.g. format the data with
> dedicated functions and still use e.g. std::filebuf for writing.

That's the point. How do I convert e.g. an integer to a string without
using stringstreams in C++ ?
I can use C functions, but that was the point of the discussion - C++
offers me template abstraction, which should result in easier to write
and (nearly) as fast code as C - additionally it should be more flexible.

>> I think it's overkill for most of the daily tasks a C++ programmer has
>> to do.
>
> I regularly need to write different Unicode encodings or codepages. I
> regularly redirect streams by changing their target streambuffer. I
> regularly need to change the output format to the C locale for file IO

But io streams are template based. So writing an integer to a stream
should be a direct function call to a conversion function, which simply
converts the integer to a string and writes it to the stream buffer.
So by theory the io streams should be a fast as coding that stuff by
hand in C. But it isn't - I don't think locales are the reason for that
(since other stream libraries support locales too)

My point is simple: [ hope so ;-) ]
IMHO C++ streams could be flexible >and< fast.

> while I still need the local culture's output format for user IO. I
> generally don't care much for formatting performance because IO throughput
> is much (s)lower anyway.

I think I know what you mean - I think we are both right.

If IO performance would be always significant, I wouldn't experience
such >extreme< performance differences between for example C++ iostreams
and C# streams (e.g. writing integers to a file) ?

> Andre, I understand your point and I particularly agree that formatting with
> iostreams tends to become unreadable (hence Boost.Format and similar
> things). I don't think it's the only side though.

Yes, but without discussing / complaining nothing would change ;-)

> Greetings!
> Uli

Greetings too,
Andre

Ulrich Eckhardt

unread,
Mar 24, 2009, 4:12:36 AM3/24/09
to
Andre Kaufmann wrote:
> Ulrich Eckhardt wrote:
>> I regularly need to write different Unicode encodings or codepages. I
>> regularly redirect streams by changing their target streambuffer. I
>> regularly need to change the output format to the C locale for file IO
>
> But io streams are template based. So writing an integer to a stream
> should be a direct function call to a conversion function, which simply
> converts the integer to a string and writes it to the stream buffer.

The streambuffer is a plugin, the encoding used to convert characters to
bytes is a plugin (part of the locale) and the function to convert integers
to strings is too (num_put and numpunct facets, both part of the locale).


If all you need is to format a number like it would be written in sourcecode
(i.e. without culture-specific formatting), there really is nothing that
could help you in C++, even sprintf() is locale-aware. Maybe itoa() isn't,
but that doesn't lend itself to good C++ programming.

Martin T.

unread,
Mar 24, 2009, 4:41:00 AM3/24/09
to

It partly boils down to a Quality Of Implementation issue, doesn't it?
There's nothing preventing MS or other implementers from coming up with
a iostreams implementation that should be nearly as fast as the
corresponding C primitves.
For some unfathomable reason noone has done this yet. (For certain
values of noone, of course ;) )

I think part of the reason is that we *have* the C constructs (printf et
al.) and will use them if performance is at stake, so there is no
incentive for implementers to write an iostreams library that performs
as good.

0.02,
Martin

Andre Kaufmann

unread,
Mar 25, 2009, 1:54:57 AM3/25/09
to
Martin T. wrote:
> Andre Kaufmann wrote:
> [...]

> It partly boils down to a Quality Of Implementation issue, doesn't it?

I think so too. But besides that the design of C++ IO streams isn't that
perfect IMHO too.

> [...]


> For some unfathomable reason noone has done this yet. (For certain
> values of noone, of course ;) )

I really don't know why for an IO library performance isn't an issue.
It should IMHO, since it's one of the advantages of C++.

> I think part of the reason is that we *have* the C constructs (printf et
> al.) and will use them if performance is at stake, so there is no
> incentive for implementers to write an iostreams library that performs
> as good.

May be - therefore most of the C++ developers don't care about the bad
performance of the IO stream library. There are some fast(er)
implementations, but they don't get that much attention.

> 0.02,
> Martin

Andre

0 new messages