std::String

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Beshr
Posts: 36
Joined: Mon Mar 12, 2007 3:34 pm
Location: Damascus, Syria

std::String

Post by Beshr »

Hello all

how can i compare a std::string to a number , whith out getting an error???

thx
(\__/)
(='.'=) Copy bunny into your signature to
(")_(") help him gain world domination.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Code: Select all

std::string numStr;
int cmpNum;

if( atoi( numStr.c_str() ) == cmpNum )
    std::cout << "numStr equals cmpNum" << std::end;
else
    std::cout << "numStr DOES NOT EQUAL cmpNum" << std::end;
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

If you want to use standard C++ features you would use stringstreams to read in the number to a string and compare the strings.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

NM, if I question what hybrid said, he'll argue with me until his fingers fall off....

Do it whichever way you'd like.
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ok, so what's the point with yours or mine solution?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The difference is the std::stringstream uses a locale which will leak memory like a sieve with some versions of the Dinkumware C++ Standard C++ Library [like the one that ships with VC7]. Personally, I prefer the C library calls for data conversion. atoi, sscanf or strtol. They don't involve making a temporary copy of the data like std::stringstream does. But that is just me. :)

Travis
Jiang
Posts: 77
Joined: Tue Feb 20, 2007 11:03 am

Post by Jiang »

@ vitek

But all the C library calls you mentioned are not type safe.
That means, if the string can not be convert/cast to a number,
it is quite possible that the program will crash for the bad
data casted. C++ stringstream is type safe and actually the
BOOST::numeric_cast use it as underlying implementation.
When bad cast or overflow occurs, BOOST::numeric_cast
will throw bad_numeric_cast and overflow exceptions for
us and we still have chance for a possible recovery. Even
if BOOST is too heavy we can still learn the basic idea
from it.

->
http://www.boost.org/libs/numeric/conve ... meric_cast

For OP's problem, IMHO, no one single solution fits all
situations. If type-safe is not an issue, C library call
maybe is the better choice.

BTW, for number cast, usually we use std::ostringstream
instead of std::stringstream, and the std::ostringstream does
not have the problem you mentioned, well, IIRC.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

That means, if the string can not be convert/cast to a number, it is quite possible that the program will crash for the bad data casted.
Bull****. Apparently you don't know the C library very well. The results are well defined for all of the C data conversion functions. If the input string is not a number, atoi returns 0, but there is no indicator for under or overflow. strtol returns 0 on under/overflow and sets the output parameter to the character that ended the scan. sscanf returns the number of conversions applied, so if you are scanning just one token and you get a value other than one, then something went wrong. You can try it for yourself...

Code: Select all

static const char nan[] = "not a number";

// none of these lines crash when you pass a non-numeric string
int i = atoi(nan);
long l = strtol(nan, 0, 10);
int c = sscanf(nan, "%d", &i);


I do agree hat the sscanf function is not type safe. You can pass a conversion string %d but pass an argument that is not of type int and that might cause a crash.

Also, the boost::numeric_cast template is not for converting strings to numbers, it is for converting one numeric type to another [i.e. 8-bit int to 16-bit int] and back and detecting overflow/underflow errors because of these conversions. The implementation does not use std::stringstream in any way, shape or form. It doesn't even use a single class from the lib.iostream part of the Standard C++ Library.

Travis
Jiang
Posts: 77
Joined: Tue Feb 20, 2007 11:03 am

Post by Jiang »

vitek wrote:
That means, if the string can not be convert/cast to a number, it is quite possible that the program will crash for the bad data casted.
Bull****.
Oops, what do you mean here? If you want to say it, then just say it out.
vitek wrote:
Apparently you don't know the C library very well. The results are well defined for all of the C data conversion functions. If the input string is not a number, atoi returns 0, but there is no indicator for under or overflow. strtol returns 0 on under/overflow and sets the output parameter to the character that ended the scan. sscanf returns the number of conversions applied, so if you are scanning just one token and you get a value other than one, then something went wrong. You can try it for yourself...
Apparently you did not get my point.

In my previous post, I said it is possible that the bad cast will
casue program crash since the wrong/unexcepted result can not
be handled correctly by client code. With a unexcepted 0 in hand,
tell me what will you do next?

No, C library calls themselves wont crash your problem,
they are designed to do their job, but I wonder the client code
can do the same job.

vitek wrote:
I do agree hat the sscanf function is not type safe. You can pass a conversion string %d but pass an argument that is not of type int and that might cause a crash.

Also, the boost::numeric_cast template is not for converting strings to numbers, it is for converting one numeric type to another [i.e. 8-bit int to 16-bit int] and back and detecting overflow/underflow errors because of these conversions. The implementation does not use std::stringstream in any way, shape or form. It doesn't even use a single class from the lib.iostream part of the Standard C++ Library.

Travis
In my previous post, the BOOST::numeric_cast should read
BOOST::lexcial_cast, I apologize for the possible confusion.

And if you want to discuss the typesafe/unsafe number cast,
we can go to lang.c++.moderate.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I don't know how much you know about the iostreams, but I'll let you in on a little secret. The stream classes use locale for formatting data. The locale has a facet for getting and putting numeric types into a stream [num_put and num_get]. Several of the Standard C++ Library implementations I've looked at use the Standard C Library data conversion routines [sprintf, strtol, strtod, ...] to write them.

I still stand by my original comments. The stream classes on some versions of the C++ library leak like a sieve, and I prefer to just use the C library data conversion routines.

Travis
Last edited by vitek on Mon Apr 16, 2007 1:25 am, edited 1 time in total.
Rytz
Posts: 249
Joined: Wed Oct 25, 2006 6:05 am
Location: IL, USA
Contact:

Post by Rytz »

vitek wrote:I don't know how much you know about the iostreams, but I'll let you in on a little secret. The stream classes use locale for formatting data. The locale has a facet for getting and putting numeric types into a stream [num_put and num_get]. Several of the Standard C++ Library implementations I've looked at use the Standard C Library data conversion routines [[sprintf[/i], strtol, strtod, ...] to write them.

Travis
Image

Nothin' but love Vitek :D.
Image
Jiang
Posts: 77
Joined: Tue Feb 20, 2007 11:03 am

Post by Jiang »

vitek wrote:I don't know how much you know about the iostreams, but I'll let you in on a little secret.

How much I know about the iostream is not that important,
just show your points here, no mater it is so-called "secret"
or not. Making unnecessary assumption is meaningless.
vitek wrote: The stream classes use locale for formatting data. The locale has a facet for getting and putting numeric types into a stream [num_put and num_get]. Several of the Standard C++ Library implementations I've looked at use the Standard C Library data conversion routines [sprintf, strtol, strtod, ...] to write them.

You totally missed the point here in my mind.

To repeat myself again, I am talking about the type-safe issues
here. The type-safe conversion provides a way for possible
recovery from bad cast, which is not available for the old
C library calls.

And, the particular standard library implementation which leaks
memory is an different (well, related) issue. As to the leak issue,
it is because some implementation (Vs2005 without SP1) failed
to handle multi-inheritance correctly, and as I said in the very
beginning, using std::ostringstream (does not have MI problem)
for conversion will solve the problem.
vitek wrote:
I still stand by my original comments. The stream classes on some versions of the C++ library leak like a sieve, and I prefer to just use the C library data conversion routines.

Travis
Sound like FUD for me, Irrlicht also has bug reported, do you
use it or not ?

Instead of keep from using your C++ iostream, you can simply

1. Get the latest service pack (Vs2005 SP1, for example),
which solved the problem already.

2. Stay with ostringstream for the string-number conversion.

Of course, actually I do not care which method will you use,
I just want to show my point when we do string-number
conversions. That's all.

BTW, words like BULL**** won't help at all in technical discussion
here, English is not my native language but I am sure you can find
other, better way to express your idea/point.

Jiang
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I am talking about the type-safe issues here.
And I'm ignoring the type safety issues. There is no type safety issue if you want to convert a string to an long using strtol. The type safety issue only appears when you want to write code independent of the type and have it work correctly. If this is the case, throw a template specialization around a call to strtol.

You also missed one of my points. Using the stringstream to convert a string to an integer involves an additional, and unnecessary memory allocation and string copy. Call me an unnecessary optimizer. That is not to mention the problem with the leaking streams.

In addition, using std::ostringstream only solves the type safe problem. It does nothing for underflow or overflow.
With a unexcepted 0 in hand, tell me what will you do next?
Well, you would write code to do some error checking. The same exact thing you would do if lexical_cast threw a bad_lexical_cast exception. I mean you would have to write at least 4 lines of code to catch and process the exception, you can check for an error from strtol just as easily.
C library calls themselves wont crash your problem, they are designed to do their job, but I wonder the client code can do the same job.
If you can't expect the client code to do proper error checking on the result of a C function call, can you expect it to be exception safe?

The bottom line is that I misunderstood your original post, probably because of our language issues. And then I jumped down your throat for saying things that you hadn't actually said. For that, I appologize.

Travis
Jiang
Posts: 77
Joined: Tue Feb 20, 2007 11:03 am

Post by Jiang »

vitek wrote:
And I'm ignoring the type safety issues. There is no type safety issue if you want to convert a string to an long using strtol. The type safety issue only appears when you want to write code independent of the type and have it work correctly. If this is the case, throw a template specialization around a call to strtol.

Roger that, I said if type safe is not an issue, then C library calls
are just fine. No problem here.
vitek wrote:
[snip]

Using the stringstream to convert a string to an integer involves an additional, and unnecessary memory allocation and string copy. Call me an unnecessary optimizer.

[snip]
Partly true in my mind.

Yes, using the std::ostringstream will cause a temp object creation
and destruction, which costs a little bit more, compared with the
C library calls ( raw pointer operations ). However, it provides a
safe method and it is possible for us to find the design balance here:
fast, non-recovery method or prepare for the possible recovery.
No one single method fits all needs.
vitek wrote:
In addition, using std::ostringstream only solves the type safe problem. It does nothing for underflow or overflow.
This is true. Without numeric limits checking, even BOOST::lexical_cast
can not detect the underflow or overflow.

But I think it is possible to learn from BOOST::numeric_cast and
build our own string-number converter, well, if the cost is not
an issue.
vitek wrote:
With a unexcepted 0 in hand, tell me what will you do next?
Well, you would write code to do some error checking. The same exact thing you would do if lexical_cast threw a bad_lexical_cast exception. I mean you would have to write at least 4 lines of code to catch and process the exception, you can check for an error from strtol just as easily.

I doubt they are in same situation.

For atoi, according to the C99 standard (7.20.1 p1),

7.20.1 Numericconversion functions

1 The functions atof, atoi, atol, and atoll need not affect the value of the
integer expression errno on an error.Ifthe value of the result cannot
be represented, the behavior is undefined.

[end quote C99]

Here undefined behavior means the compiler can do whatever it like:
return 0 for you, or format your harddisk immediately.

I am not language lawer, but I would like to say the above situation is
quite serious and even some implementations will return an
not-so-meaningful integer for you, it is still an QoS and C/C++
language do not guarantee this behavior at all.

And, even we are lucky enough that all compilers we use do return a
0 when bad cast occurred, it is still difficult to do error checking/handling
using C library calls. For example, what about if the string we used is
exactly "0"?

Code: Select all


    int i = atoi("0");
    int j = atoi("xxxxDEADBEEFxxxx");

Here i and j are possible both 0, for this case, we can not tell apart
whether bad cast occurred or not.

For the above reason, the C/C++ language just make it undefined
behavior and who wrote the bad cast code will be responsible for the
possible consequences.
vitek wrote:
C library calls themselves wont crash your problem, they are designed to do their job, but I wonder the client code can do the same job.
If you can't expect the client code to do proper error checking on the result of a C function call, can you expect it to be exception safe?


For above reason, IMHO, it is near to impossible to do practical systematical error number conversion checking using C library calls.
Since one of the spirits of C language is "Trust the programmer",
here nothing strange at all. However, compared with C language,
C++'s 's typing system was improved quite a lot to avoid such kind of problems.
vitek wrote:
The bottom line is that I misunderstood your original post, probably because of our language issues. And then I jumped down your throat for saying things that you hadn't actually said. For that, I appologize.

Travis
No problem.

I read my OP again and I realized that my points were not so clear
at the first glance. Sorry for that, I wish I had made my points clearer.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Well, Hybrid, even you and I don't have to post for the post to get out of hand!!! :P


I was simply going to point out, that it's faster to compare the number and the number generated from atoi, then it was to convert to a string, and then do a string comparison.

But I like Vitek's and Jihang's argument better. They are more lively than us as well!!! :twisted:
Image
Post Reply