用bool / fail在C ++中将string转换为int

我有一个std::string可能是一个string或可能是一个值(如0 )。

什么是最好的或最简单的方式来将std::string转换为具有失败能力的int ? 我想要一个C#版本的Int32.TryParse

使用boost :: lexical_cast 。 如果演员不能完成,它会抛出一个exception 。

 #include <boost/lexical_cast.hpp> #include <iostream> #include <string> int main(void) { std::string s; std::cin >> s; try { int i = boost::lexical_cast<int>(s); /* ... */ } catch(...) { /* ... */ } } 

没有提升:

 #include <iostream> #include <sstream> #include <string> int main(void) { std::string s; std::cin >> s; try { std::stringstream ss(s); int i; if ((ss >> i).fail() || !(ss >> std::ws).eof()) { throw std::bad_cast(); } /* ... */ } catch(...) { /* ... */ } } 

伪装提升:

 #include <iostream> #include <sstream> #include <string> template <typename T> T lexical_cast(const std::string& s) { std::stringstream ss(s); T result; if ((ss >> result).fail() || !(ss >> std::ws).eof()) { throw std::bad_cast(); } return result; } int main(void) { std::string s; std::cin >> s; try { int i = lexical_cast<int>(s); /* ... */ } catch(...) { /* ... */ } } 

如果你想要这些函数的无抛出版本,你必须捕捉适当的exception(我不认为boost::lexical_cast提供了一个无抛出的版本),如下所示:

 #include <iostream> #include <sstream> #include <string> template <typename T> T lexical_cast(const std::string& s) { std::stringstream ss(s); T result; if ((ss >> result).fail() || !(ss >> std::ws).eof()) { throw std::bad_cast(); } return result; } template <typename T> bool lexical_cast(const std::string& s, T& t) { try { // code-reuse! you could wrap // boost::lexical_cast up like // this as well t = lexical_cast<T>(s); return true; } catch (const std::bad_cast& e) { return false; } } int main(void) { std::string s; std::cin >> s; int i; if (!lexical_cast(s, i)) { std::cout << "Bad cast." << std::endl; } } 

另一种使用标准stream的方法:

 #include <sstream> #include <iostream> #include <string> int main() { std::stringstream convertor; std::string numberString = "Not a number!"; int number; convertor << numberString; convertor >> number; if(convertor.fail()) { // numberString is not a number! std::cout << "Not a Number!"; } } 

即使string包含无效字符(例如“123abc”)后,使用stream的其他答案也会成功。 我不熟悉boost,所以不能评论它的行为。

如果你想知道这个string是否包含一个数字并且只有一个数字,你必须使用strtol:

 #include <iostream> #include <string> int main(void) { std::string s; std::cin >> s; char *end; long i = strtol( s.c_str(), &end, 10 ); if ( *end == '\0' ) { // Success } else { // Failure } } 

strtol返回一个指向结束parsing的字符的指针,所以你可以很容易地检查整个string是否被parsing。

请注意,strtol返回一个不是一个整型,但取决于你的编译器,这些可能是相同的。 标准库中没有strtoi函数,只有atoi,它不返回parsing结束字符。

例外不应该用于布尔testing

被接受的答案实际上是一个问题的可怕答案,因为它违反了“对例外情况使用例外”的规定。

例外情况是处理exception情况的一个很好的工具,即真正发生问题的情况。 它们是现有使用案例的糟糕工具。 部分原因是抛出和捕获exception是昂贵的,部分是因为它是误导性的代码 – 当一个开发人员看到一个exception时,他们应该可以合理地假设出现了问题。 这个基本原则很好的讨论比比皆是,但是我喜欢“实用程序员”,或者这个不错: http : //www.lohmy.de/2013/03/06/writing-use-cases-exception-或-备用stream/

如果你总是期望一个数字,使用boost :: lexical_cast

boost :: lexical_cast是一个最佳解决scheme,当它真的是一个例外,它是接收一个非数字。

如果非数字是你的用例的一部分,使用boost :: try_lexical_convert

如果你正在浏览一个string,并且想要做一件事情,如果它是一个数字,而另一个,如果它是一个数字, 不要使用布尔testing的例外 。 这只是糟糕的编程。

实际上,boost提供了用于实现lexical_cast的try_lexical_convert(摘自这里的文档: http : //www.boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/synopsis.html#boost_lexical_cast。 synopsis.lexical_cast )。

 template <typename Target, typename Source> inline Target lexical_cast(const Source &arg) { Target result; if (!conversion::try_lexical_convert(arg, result)) throw bad_lexical_cast(); return result; } 

在boost的lexical_cast可用之前,我曾经这样做过:

 namespace detail { template< typename Target, typename Source > struct stream_caster { static Target stream_cast(const Source& s) { std::stringstream ss; if( (ss << s).fail() ) { throw std::bad_cast("could not stream from source"); } Target t; if( (ss >> t).fail() || !(ss >> ws).eof) { throw std::bad_cast("could not stream to target"); } return t; } }; template< typename T > struct stream_caster<T,T> { static const T& stream_cast(const T& s) { return s; } }; template< typename Source > struct stream_caster<std::string,Source> { static std::string stream_cast(const Source& s) { std::ostringstream oss; if( (oss << s).fail() ) { throw std::bad_cast("could not stream from source"); } return oss.str(); } }; template< typename Target > struct stream_caster<Target,std::string> { static Target stream_cast(const std::string& s) { std::stringstream ss(s); Target t; if( (ss >> t).fail() || !(ss >> ws).eof) { throw std::bad_cast("could not stream to target"); } return t; } }; template<> struct stream_caster<std::string,std::string> { static const std::string& stream_cast(const std::string& s) { return s; } }; } template< typename Target, typename Source > inline Target stream_cast(const Source& s) { return detail::stream_caster<Target,Source>::stream_cast(s); }