Re: String formating! Aarrrrgggh.
Your Name wrote:
Hi all,
I run a small engineering company, and our main project is a very
large C++ application -- it's actually multiple applications which
communicate with each other over various interfaces (USB, serial,
etc).
We're at the point now where we have several developers all working
on the various pieces of C++ code. Some of us are comfortable with
Boost, some use StringStream, and some still use sprintf() and
sscanf(). But things are very inconsistent, and there is too much
"glue" code converting between all the different string
representations.
If it matters, our application is largely mathematical, so the bulk
of the string handling that we do is converting floats, ints, and
doubles to and from strings, and we need precise control over the
formatting/precision. Much of this is to/from text files, but some of
it is from Win32 objects, like MFC controls (edit boxes, etc).
I want to choose a standard and convert all of our existing code. The
choices I'm considering are:
1) std::string, with Boost::format and Boost::tokenizer
2) std::string, with StringStream
3) MFC's CString (I don't know the sscanf() equivalent here)
4) The new sprintf_s() and sscanf_s() "secure" functions available in
Visual Studio
5) Writing a custom string class, along with formatting functions
6) Writing custom formatting functions that work with std::string
I'm sure there's no one-size-fits-all answer to this problem, so I'm
looking for general feedback. On the other hand, this is such a
fundamental problem in application development that I'm a little
surprised there's no universally accepted solution. Or maybe there
is and I just didn't get the memo.
Thanks for suggestions and opinions.
Whichever one you chose, build it into a function or template and have
everyone use it. Personally I use this:
template<typename T, typename F > T StrmConvert( const F from )
{
std::stringstream temp;
temp << from;
T to = T();
temp >> to;
return to;
}
template<typename F> std::string StrmConvert( const F from )
{
return StrmConvert<std::string>( from );
}
which uses stringstream. One of the advantages of this method is you can
convert from anything to anything. Notice there is no error checking in
this, that if something can't be converted a default intiialized value is
returned (0 for int, 0.0 for float, "" for string, etc..).
One of the things about this code, however, is that anything that has <<
defined and >> defined will work. But once you build a function or template
and decide later to do it some different way for whatever reason, you only
have to change the code in one place, as long as everyone uses what you
built.
If you wish to be more strict in the format coming in (std::string instead
of char* also for instance) you can use another layer of encapuslation.
Untested code:
templat<typename T> T ToNumber( const std::string from )
{
return StrmConvert<T> StrmConvert( from );
}
Then make sure everyone uses ToNumber such as:
std::string Number = "12345.678";
float Value = ToNumber<float>( Number );
The question if one is better than the other... the only one I would stay
away from is Microsoft specific CString. As you can probably tell my
preference is std::stringstream but mainly because I don't have to worry
about what I'm converting from and what I'm converting to I let stringstream
handle it for me. I don't have to worry about do I need atoi or atof or
atod or does atod even exist etc...
--
Jim Langston
tazmaster@rocketmail.com