For a specific example, consider atoi(const std::string &)
. This is very frustrating, since we as programmers would need to use it so much.
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.)
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());
}
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);
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 callstrtoul(str.c_str(), ptr, base)
,strtoll(str.c_str(), ptr, base)
, andstrtoull(str.c_str(), ptr, base)
, respectively. Each function returns the converted result, if any. The argumentptr
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 andidx != 0
, the function stores in*idx
the index of the first unconverted element of str.Returns: the converted result.
Throws:
invalid_argument
ifstrtol
,strtoul
,strtoll
, orstrtoull
reports that no conversion could be performed. Throwsout_of_range
if the converted value is outside the range of representable values for the return type.
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.)
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! ...
}