+5  A: 

There's no good way to know if atoi fails. It always returns an integer. Is that integer a valid conversion? Or is the 0 or -1 or whatever indicating an error? Yes it could throw an exception, but that would change the original contract, and you'd have to update all your code to catch the exception (which is what the OP is complaining about).

If translation is too time consuming, write your own atoi:

int atoi(const std::string& str)
{
    std::istringstream stream(str);
    int ret = 0;
    stream >> ret;
    return ret;
}
Doug T.
The parameter should be a const reference instead.
hrnt
thanks you're correct. updated.
Doug T.
I decided to rewrite my comment. So if one uses lots of threads this implementation of atoi() is likely to cause performance problems. Here is a discussion about it: http://gcc.gnu.org/ml/gcc-bugs/2009-05/msg00798.html. Even though ostringstream is discussed istringstream has the same performance problem.
skwllsp
A: 

There are all sorts of ways to parse a number from a string, atoi can easily be used with a std::string via atoi(std.c_str()) if you really want, but atoi has a bad interface because there is no sure way to determine if an error occurred during parsing.

Here's one slightly more modern C++ way to get an int from a std::string:

std::istringstream tmpstream(str);
if (tmpstream >> intvar)
{
    // ... success! ...
}
Charles Bailey
`std::string` definitely cannot be used with atoi in this way. You can't take the internal buffer of a std::string and manipulate it directly, not via the string's interface.
UncleBens
Um, `atoi` parses a string, it takes a `const char*`, it doesn't mutate the passed string at all?
Charles Bailey
Sorry, my mistake...
UncleBens
A: 

The tongue in cheek answer is: Because STL is a half-hearted attempt to show how powerful C++ templates could be. Before they got to each corner of the problem space, time was up.

There are two reasons: Creating an API takes time and effort. Create a good API takes a lot of time and a huge effort. Creating a great API takes an insane amount of time and an incredible effort. When the STL was created, OO was still pretty new to the C++ people. They didn't have the ideas how to make fluent and simple API. Today, we think iterators are so 1990 but at the time, people thought "Bloody hell, why would I need that? for (int i=0; i<...) has been good enough for three decades!"

So STL didn't became the great, fluent API. This isn't all C++ fault because you can make good APIs with C++. But it was the first attempt to do that and it shows. Before the API could mature, it was turned into a standard and all the ugly shortcomings were set into stone. And on top of this, there was all this legacy code and all the libraries which already could do everything, so the pressure wasn't really there.

To solve your misery, give up on STL and have a look at the successors: Try boost and maybe Qt. Yeah, Qt is a UI library but it also has a pretty good standard library.

Aaron Digulla
+1 for mentioning Qt. It has a much easier to use interface than the STL.
milan1612
Huh? OO was new? The STL doesn't rely on OO. It came *after* years of painful attempts at OO libraries. And "iterators are 90's"? Hardly. No other language has picked up on the expressiveness they allow in C++. And far too many C++ programmers still think they're some kind of rocket science or useless academic navel-gazing with no practical applications.
jalf
It may also be worth mentioning that the STL *was* much more complete. During standardization a lot of corners had to be cut off to make the library smaller and easier to standardize. But that doesn't mean the library was immature.
jalf
@jalf: I said "OO was new for the C++ guys". If someone from the Smalltalk group would have designed it, it would have been better but the C++ wouldn't have understood the result. ;)
Aaron Digulla
@jalf: I don't say "immature". Maybe "clumsy" and "incomplete".
Aaron Digulla
STL and streams are rather different things, with completely different design ideas behind them (templates all the way vs multiple inheritance etc). Sure, things like sscanf and atoi can be used in C++, but a type-safe alternative is also needed, because you just can't use these functions in template code.
UncleBens
You said "before the API could mature". I think it's a pretty straightforward implication that if an API is not yet mature, it must be immature.UncleBens has a good point too. The STL has nothing to do with the IOStreams library. As for OO, it certainly wasn't new in C++ either. It had been around for ages, long enough to get discarded again when the STL was created.
jalf
"...Today, we think iterators are so 1990..." I hate to break it to you, but many C++, C#, and Java developers are still living in the 80's. If I have to explain one more time why int i=0; for(i=0;...) is bad, I'm going to scream!
James Schek
+1 for mentioning the drawback of STL.Acutally,I hate STL.
Jichao
I don't know about immature; the thing that frustrates most people about the STL (especially newcomers to C++) is that it's so damn *general*. It does everything you want, but it doesn't go out of its way to make common tasks easier. Where some new language like Java would just throw in specialized functions for common things like string tokenizing, case-insensitive comparisons, string-to-int conversions, etc., the STL makes you use more generalized interfaces, like streams, STL algorithms, etc. which, while very flexible and powerful, are hardly straightforward.
Charles Salvia
+3  A: 

For your example, you've got two options:

std::string mystring("4");
int myint = atoi(mystring.c_str());

Or something like:

std::string mystring("4");
std::istringstream buffer(mystring);
int myint = 0;
buffer >> myint;

The second option gives you better error management than the first.

luke
+1  A: 

You can write a more generic string to number convert as such:

template <class T>
T strToNum(const std::string &inputString,
           std::ios_base &(*f)(std::ios_base&) = std::dec)
{
    T t;
    std::istringstream stringStream(inputString);

    if ((stringStream >> f >> t).fail())
    {
        throw runtime_error("Invalid conversion");
    }
    return t;
}


// Example usage
unsigned long ulongValue = strToNum<unsigned long>(strValue);
int intValue             = strToNum<int>(strValue);

int intValueFromHex      = strToNum<int>(strHexValue,std::hex);
unsigned long ulOctValue = strToNum<unsigned long>(strOctVal, std::oct);
RC
+12  A: 

Another more general question is why do not STL reimplementate all the standard C libraries

Because the old C libraries do the trick. The C++ standard library only re-implements existing functionality if they can do it significantly better than the old version. And for some parts of the C library, the benefit of writing new C++-implementations just isn't big enough to justify the extra standardization work.

As for atoi and the like, there are new versions of these in the C++ standard library, in the std::stringstream class.

To convert from a type T to a type U:

T in;
U out;
std::stringstream sstr(in);
sstr >> out;

As with the rest of the IOStream library, it's not perfect, it's pretty verbose, it's impressively slow and so on, but it works, and usually it is good enough. It can handle integers of all sizes, floating-point values, C and C++ strings and any other object which defines the operator <<.

EDIT:In addition,I have heard many other libraries avaliable for C++ make a lot of enhancement and extensions to STL.So does there libraries support these functions?

Boost has a boost::lexical_cast which wraps std::stringstream. With that function, you can write the above as:

U out = boost::lexical_cast<U>(in);
jalf
+1 for answering the latter questions in a clear way.there are much more answers for the first question than i expected.
Jichao
I've always felt that there's no really good C++ way to convert a string to an integer. Streams come with a lot of machinery, and instantiating a stream object is slow. A nice global function would be better, in my opinion. Boost lexical cast is nice syntactically, but every time you call it you're instantiating a new stringstream object.
Charles Salvia
Yep, like I said, there's a lot to dislike about the IOStreams library, but at least it gets the job done, and *usually* the cost is acceptable.
jalf
I was going to say: Streams! Great job!
Seth Illgard
+5  A: 

Even in C, using atoi isn't a good thing to do for converting user input. It doesn't provide error checking at all. Providing a C++ version of it wouldn't be all that useful - considering that it wouldn't throw and do anything, you can just pass .c_str() to it and use it.

Instead you should use strtol in C code, which does do error checking. In C++03, you can use stringstreams to do the same, but their use is error-prone: What exactly do you need to check for? .bad(), .fail(), or .eof()? How do you eat up remaining whitespace? What about formatting flags? Such questions shouldn't bother the average user, that just want to convert his string. boost::lexical_cast does do a good job, but incidentally, C++0x adds utility functions to facilitate fast and safe conversions, through C++ wrappers that can throw if conversion failed:

int stoi(const string& str, size_t *idx = 0, int base = 10);
long stol(const string& str, size_t *idx = 0, int base = 10);
unsigned long stoul(const string& str, size_t *idx = 0, int base = 10);
long long stoll(const string& str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);

Effects: the first two functions call strtol(str.c_str(), ptr, base), and the last three functions call strtoul(str.c_str(), ptr, base), strtoll(str.c_str(), ptr, base), and strtoull(str.c_str(), ptr, base), respectively. Each function returns the converted result, if any. The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx. If the function does not throw an exception and idx != 0, the function stores in *idx the index of the first unconverted element of str.

Returns: the converted result.

Throws: invalid_argument if strtol, strtoul, strtoll, or strtoull reports that no conversion could be performed. Throws out_of_range if the converted value is outside the range of representable values for the return type.

Johannes Schaub - litb
You **can't** pass `c_str()`: it returns a `const char*` and more importantly: the string object wouldn't know its own size if its buffer gets manipulated externally.
UncleBens
@UncleBens, can you please elaborate? `atoi`'s parameter has type `const char*`, and doesn't modify the pointed to storage.
Johannes Schaub - litb
Oops, for some reason I thought about conversion *to* string... If you made a small edit to your post, I'd remove my downvote.
UncleBens
+1  A: 

I see that solutions are offered that use std::stringstream or std::istringstream. This might be perfectly OK for single threaded applications but if an application has lots of threads and often calls atoi(const std::string& str) implemented in this way that will result in performance degradation.

Read this discussion for example: http://gcc.gnu.org/ml/gcc-bugs/2009-05/msg00798.html. And see a backtrace of the constructor of std::istringstream:

#0  0x200000007eb77810:0 in pthread_mutex_unlock+0x10 ()
   from /usr/lib/hpux32/libc.so.1
#1  0x200000007ef22590 in std::locale::locale (this=0x7fffeee8)
    at gthr-default.h:704
#2  0x200000007ef29500 in std::ios_base::ios_base (this=<not available>)
    at /tmp/gcc-4.3.1.tar.gz/gcc-4.3.1/libstdc++-v3/src/ios.cc:83
#3  0x200000007ee8cd70 in std::basic_istringstream<char,std::char_traits<char>,std::allocator<char> >::basic_istringstream (this=0x7fffee4c,
    __str=@0x7fffee44, __mode=_S_in) at basic_ios.h:456
#4  0x4000f70:0 in main () at main.cpp:7

So every time you enter atoi() and create a local varibale of type std::stringstream you will lock a global mutex and in a multithreaded application it is likely to result in waiting on this mutex.

So, it's better in a multithreaded application not to use std::stringstream. For example simply call atoi(const char*):

inline int atoi(const std::string& str)
{
    return atoi(str.c_str());
}
skwllsp
That's a gcc performance bug, not a C++ issue.
Joe Gauterin
I agree. It is not a C++ issue. Just one thing to consider when one writes a program what requires performance. I think I had stated it in my post.
skwllsp
+1  A: 

For conversions I find simplest to use boost's lexical_cast (except it might be too rigorously checking the validity of the conversions of string to other types).

It surely isn't very fast (it just uses std::stringstream under the hood, but significantly more convenient), but performance is often not needed where you convert values (e.g to create error output messages and such). (If you do lots of these conversions and need extreme performance, chances are you are doing something wrong and shouldn't be performing any conversions at all.)

UncleBens
+1  A: 

Because the old C libraries still work with standard C++ types, with a very little bit of adaptation. You can easily change a const char * to a std::string with a constructor, and change back with std::string::c_str(). In your example, with std::string s, just call atoi(s.c_str()) and you're fine. As long as you can switch back and forth easily there's no need to add new functionality.

I'm not coming up with C functions that work on arrays and not container classes, except for things like qsort() and bsearch(), and the STL has better ways to do such things. If you had specific examples, I could consider them.

C++ does need to support the old C libraries for compatibility purposes, but the tendency is to provide new techniques where warranted, and provide interfaces for the old functions when there isn't much of an improvement. For example, the Boost lexical_cast is an improvement over such functions as atoi() and strtol(), much as the standard C++ string is an improvement over the C way of doing things. (Sometimes this is subjective. While C++ streams have considerable advantages over the C I/O functions, there's times when I'd rather drop back to the C way of doing things. Some parts of the C++ standard library are excellent, and some parts, well, aren't.)

David Thornley