Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Problem with one-liner string conversion

Reply
Thread Tools

Problem with one-liner string conversion

 
 
jl_post@hotmail.com
Guest
Posts: n/a
 
      06-17-2008
Hi,

A few months back I remember reading through C++ newsgroups trying
to find a way to quickly convert a number to a C++ std::string. I
often see code like:

// Create a string that holds a number:
int num = 7; // for example
char tmp[24];
sprintf(tmp, "%d", num);
const std::string str = tmp;

but I wanted to see if there was a better way. I generally would use
this:

// Create a string that holds a number:
int num = 7;
std:stringstream outStream; // #include <sstream>
outStream << num;
const std::string str = outStream.str();

and this works great, but just like the first example, it declares and
uses a temporary variable/object. What I'd have liked to see was some
sort of method in std::string that handled the conversion in one line,
like this:

// NOTE: not real code!
int num = 7;
const std::string str = std::string::number(num);

While I didn't find what I was looking for, I did find an
interesting post, where someone posted this nice, simple function:

// Converts many things to a std::string:
#include <sstream>

template <typename T>
std::string toStdString(const T &thing)
{
std:stringstream os;
os << thing;
return os.str();
}

Using this function, I can now write code like this:

int num = 7;
const std::string str = toStdString(num);

This code is very clear, but it also has another benefit: Not only
can I easily convert integers and floats to a std::string, but I can
convert pretty much anything that I can send to std::cout.

But then I thought of something: Why even define a templated
function? I could write code like this:

int num = 7;
std::string str = (std:stringstream() << num).str();

It may not be as elegant as the toStdString() solution, but at least
it won't require me to define (or include a header file of) the
toStdString() function in every program I write. In addition, there's
no need to introduce a temporary variable to the current scope.

However, when I tried to compile this code, I got the following
error message:

testfile.cpp: In function `int main(int, char**)':
testfile.cpp:23: error: 'struct std::basic_ostream<char,
std::char_traits<char> >' has no member named 'str'

I can't figure out why I'm getting this error message. I mean, I'm
declaring a std:stringstream object, using the "<<" operator on it
(which, I believe, returns the very same std:stringstream object),
and then I call the ::str() method on it. std:stringstream HAS to
have ::str() defined, otherwise the toStdString() function above
wouldn't compile.

What puzzles me is that I've successfully compiled similar things
with std::strings, like this:

// Prints "Hello, world!":
const char* word1 = "Hello";
const char* word2 = "world";
printf("%s", (word1 + std::string(", ") + word2 + "!\n").c_str());

and have had no problems with it. (Basically, word1+std::string(", ")
+word2+"!\n" returns a std::string, and the ::c_str() method is called
on it, passing its internal data to printf() to use before the
std::string goes out of scope.)

I would think that what I'm trying to do with std:stringstream is
really no different, so it puzzles me why (std:stringstream() <<
num).str() generates a compiler error. Does anybody know why this
generates a compiler error?

Thanks in advance for any help.

-- Jean-Luc
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      06-17-2008
wrote:

> Hi,
>
> A few months back I remember reading through C++ newsgroups trying
> to find a way to quickly convert a number to a C++ std::string. I
> often see code like:
>
> // Create a string that holds a number:
> int num = 7; // for example
> char tmp[24];
> sprintf(tmp, "%d", num);
> const std::string str = tmp;
>
> but I wanted to see if there was a better way. I generally would use
> this:
>
> // Create a string that holds a number:
> int num = 7;
> std:stringstream outStream; // #include <sstream>
> outStream << num;
> const std::string str = outStream.str();
>
> and this works great, but just like the first example, it declares and
> uses a temporary variable/object. What I'd have liked to see was some
> sort of method in std::string that handled the conversion in one line,
> like this:
>
> // NOTE: not real code!
> int num = 7;
> const std::string str = std::string::number(num);
>
> While I didn't find what I was looking for, I did find an
> interesting post, where someone posted this nice, simple function:
>
> // Converts many things to a std::string:
> #include <sstream>
>
> template <typename T>
> std::string toStdString(const T &thing)
> {
> std:stringstream os;
> os << thing;
> return os.str();
> }
>
> Using this function, I can now write code like this:
>
> int num = 7;
> const std::string str = toStdString(num);
>
> This code is very clear, but it also has another benefit: Not only
> can I easily convert integers and floats to a std::string, but I can
> convert pretty much anything that I can send to std::cout.
>
> But then I thought of something: Why even define a templated
> function? I could write code like this:
>
> int num = 7;
> std::string str = (std:stringstream() << num).str();
>
> It may not be as elegant as the toStdString() solution, but at least
> it won't require me to define (or include a header file of) the
> toStdString() function in every program I write. In addition, there's
> no need to introduce a temporary variable to the current scope.
>
> However, when I tried to compile this code, I got the following
> error message:
>
> testfile.cpp: In function `int main(int, char**)':
> testfile.cpp:23: error: 'struct std::basic_ostream<char,
> std::char_traits<char> >' has no member named 'str'


Note that the operator<< you are invoking is inherited from the
std::basic_ostream<char>. Its return type is std::basic_ostream&. At that
point, all information about the underlying object being a string stream is
lost. An std::basic_ostream<char> object does not have a str() member
function. You need to cast back:

std::string str =
static_cast< std:stringstream& >( std:stringstream() << num ).str();


[snip]


BTW: you should just put toStdString into your library and use it. It is
much better than writing a cryptic line every time you want to convert
something. Also, you are creating a stringstream object in either case.
Whether it is a named local variable of a temporary doesn't really matter
all that much.


Best

Kai-Uwe Bux
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      06-17-2008
Kai-Uwe Bux wrote:

> wrote:
>
>> Hi,


[snip]
>> int num = 7;
>> std::string str = (std:stringstream() << num).str();
>>
>> It may not be as elegant as the toStdString() solution, but at least
>> it won't require me to define (or include a header file of) the
>> toStdString() function in every program I write. In addition, there's
>> no need to introduce a temporary variable to the current scope.
>>
>> However, when I tried to compile this code, I got the following
>> error message:
>>
>> testfile.cpp: In function `int main(int, char**)':
>> testfile.cpp:23: error: 'struct std::basic_ostream<char,
>> std::char_traits<char> >' has no member named 'str'

>
> Note that the operator<< you are invoking is inherited from the
> std::basic_ostream<char>. Its return type is std::basic_ostream&. At that
> point, all information about the underlying object being a string stream
> is lost. An std::basic_ostream<char> object does not have a str() member
> function. You need to cast back:
>
> std::string str =
> static_cast< std:stringstream& >( std:stringstream() << num ).str();
>

[snip]

Ah, and just for kicks, now try:

#include <sstream>
#include <iostream>

int main ( void ) {
char const * message = "Hello world.\n";
std::cout <<
static_cast< std:stringstream& >
( std:stringstream() << message ).str();
}

and interpret the output.


I re-iterate: go with the toStdString() solution.


Best

Kai-Uwe Bux
 
Reply With Quote
 
Martin York
Guest
Posts: n/a
 
      06-17-2008
On Jun 17, 3:28*pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> Kai-Uwe Bux wrote:
> > jl_p...@hotmail.com wrote:

>
> >> Hi,

>
> [snip]
>
> >> * *int num = 7;
> >> * *std::string str = (std:stringstream() << num).str();

>
> >> It may not be as elegant as the toStdString() solution, but at least
> >> it won't require me to define (or include a header file of) the
> >> toStdString() function in every program I write. *In addition, there's
> >> no need to introduce a temporary variable to the current scope.

>
> >> * *However, when I tried to compile this code, I got the following
> >> error message:

>
> >> testfile.cpp: In function `int main(int, char**)':
> >> testfile.cpp:23: error: 'struct std::basic_ostream<char,
> >> std::char_traits<char> >' has no member named 'str'

>
> > Note that the operator<< you are invoking is inherited from the
> > std::basic_ostream<char>. Its return type is std::basic_ostream&. At that
> > point, all information about the underlying object being a string stream
> > is lost. An std::basic_ostream<char> object does not have a str() member
> > function. You need to cast back:

>
> > * std::string str =
> > * static_cast< std:stringstream& >( std:stringstream() << num ).str();

>
> [snip]
>
> Ah, and just for kicks, now try:
>
> #include <sstream>
> #include <iostream>
>
> int main ( void ) {
> * char const * message = "Hello world.\n";
> * std::cout <<
> * * static_cast< std:stringstream& >
> * * ( std:stringstream() << message ).str();
>
> }
>
> and interpret the output.
>
> I re-iterate: go with the toStdString() solution.
>
> Best
>
> Kai-Uwe Bux



Or get a hold of the boost libraries (boost.org) and use its
lexical_cast<>(). It not only converts from string to number and
number to string. But from anything to anything. As long as you can
use a stream to convert them. Even better boost is the semi-offical
testing ground for stuff that will be considered for the next
standard. So it is highly tested and widely addopted.

#include <boost/lexical_cast.hpp>

int main()
{
std::string val("567");
int num = boost::lexical_cast<int>(val);
}
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-18-2008
On Jun 18, 1:03 am, Martin York <Martin.YorkAma...@gmail.com> wrote:
> On Jun 17, 3:28 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> > Kai-Uwe Bux wrote:
> > > jl_p...@hotmail.com wrote:

> > [snip]


> Or get a hold of the boost libraries (boost.org) and use its
> lexical_cast<>(). It not only converts from string to number
> and number to string. But from anything to anything.


I'm not sure that I'd consider that an advantage. It doesn't
make sense to convert anything to anything (and going through
the textual representation, which boost::lexical_cast does, is
not necessarily the correct way to convert x to y).

Even in the case of conversion to string, I'm not sure just how
often a generic solution is appropriate; you probably don't want
to format a value representing an interest rate (percent) in the
same way you'd format a value representing a monetary value.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Martin York
Guest
Posts: n/a
 
      06-18-2008
On Jun 18, 1:34*am, James Kanze <james.ka...@gmail.com> wrote:
> On Jun 18, 1:03 am, Martin York <Martin.YorkAma...@gmail.com> wrote:
> > Or get a hold of the boost libraries (boost.org) and use its
> > lexical_cast<>(). It not only converts from string to number
> > and number to string. But from anything to anything.

>
> I'm not sure that I'd consider that an advantage. *It doesn't
> make sense to convert anything to anything (and going through
> the textual representation, which boost::lexical_cast does, is
> not necessarily the correct way to convert x to y).


Context is everything.
I hope (and imagine) other readers did not read into my last reply
that I was suggesting that lexical_cast<>() should be used to convert
from a type to any other arbitory type. Where appropriate stream can
be used (via lexical_cast<>()) in a type safe way to convert types
appropriately (Its usage will ALWAYS depend on the context of the
problem). 'Normally' this will be <Type> => String or String =>
<Type>. But as with all rules and complex systems it usage is not
limited to just that.

Martin
 
Reply With Quote
 
jl_post@hotmail.com
Guest
Posts: n/a
 
      06-18-2008

Thank you all for all your help. I really appreciate it.

But before I end this post, let me answer a question some have been
asking:

On Jun 17, 3:21 pm, Paavo Helde <nob...@ebi.ee> wrote:
>
> What's wrong with the helper function approach?


Nothing, really. I just wanted to know why the line:

std::string str = (std:stringstream() << num).str();

wouldn't compile. That line to me is fairly simple (even thought some
might call it "ugly"), that if I were to find a just-as-simple
approach, I'd use that.

However, I agree that the fix that uses the static_cast:

std::string str =
static_cast<std:stringstream&>
(std:stringstream() << num).str();

is not that "pretty" and that there are more readable ways to do the
same thing.

(Basically, I wanted to know why the code wouldn't compile. I
didn't mean to imply that I rejected the helper-function approach.
Sorry for the confusion.)

Again, thanks for all your help.

-- Jean-Luc
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      06-18-2008
On Jun 18, 8:22 pm, Martin York <Martin.YorkAma...@gmail.com> wrote:
> On Jun 18, 1:34 am, James Kanze <james.ka...@gmail.com> wrote:


> > On Jun 18, 1:03 am, Martin York <Martin.YorkAma...@gmail.com> wrote:
> > > Or get a hold of the boost libraries (boost.org) and use
> > > its lexical_cast<>(). It not only converts from string to
> > > number and number to string. But from anything to
> > > anything.


> > I'm not sure that I'd consider that an advantage. It
> > doesn't make sense to convert anything to anything (and
> > going through the textual representation, which
> > boost::lexical_cast does, is not necessarily the correct way
> > to convert x to y).


> Context is everything.
> I hope (and imagine) other readers did not read into my last
> reply that I was suggesting that lexical_cast<>() should be
> used to convert from a type to any other arbitory type. Where
> appropriate stream can be used (via lexical_cast<>()) in a
> type safe way to convert types appropriately (Its usage will
> ALWAYS depend on the context of the problem). 'Normally' this
> will be <Type> => String or String => <Type>. But as with all
> rules and complex systems it usage is not limited to just
> that.


Yes. The problem with lexical_cast is that it is too
convenient; it sort of works in a large number of cases where it
probably shouldn't (and then fails for some particular values
which you forgot to test).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Vidar Hasfjord
Guest
Posts: n/a
 
      06-19-2008
On Jun 18, 9:50*pm, jl_p...@hotmail.com wrote:
> * *std::string str = (std:stringstream() << num).str();
>
> wouldn't compile. *That line to me is fairly simple (even thought some
> might call it "ugly"), that if I were to find a just-as-simple
> approach, I'd use that.


Using a utility class, a string builder, you can achieve this terse
solution:

string s = SB << num;

See here for discussion, description and limitations:

http://groups.google.com/group/comp....00421feca71ea1

Regards,
Vidar Hasfjord
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
PSD to XHTML Conversion Services and PSD to HTML CSS ConversionServices, PSD to Joomla, Drupal, Wordpress Conversion xhtml champs Python 0 06-21-2011 11:59 AM
PSD to XHTML Conversion Services and PSD to HTML CSS ConversionServices, PSD to Joomla, Drupal, Wordpress Conversion PSD to XHTML Conversion Services and PSD to HTML CSS Conversion Services, PSD to Joomla, Drupal, Wor VHDL 0 04-25-2011 06:43 AM
conversion operator and conversion ctor subramanian100in@yahoo.com, India C++ 2 09-15-2009 12:46 PM
Problem with string and base64binary conversion =?ISO-8859-1?Q?Hel=E9ne?= ASP .Net 1 08-07-2003 07:31 PM
data conversion question (binary string to 'real string') Alexander Eisenhuth Python 5 07-25-2003 06:42 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57