Converter string para int com bool / fail em C ++

Eu tenho um std::string que poderia ser uma string ou poderia ser um valor (como 0 ).

Qual é a melhor ou mais fácil maneira de converter o std::string para int com a capacidade de falhar? Eu quero uma versão em C ++ do Int32.TryParse do c #.

Use boost :: lexical_cast . Se o casting não puder ser feito, ele lançará uma exceção .

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

Sem impulso:

 #include  #include  #include  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(...) { /* ... */ } } 

Impulso falso:

 #include  #include  #include  template  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(s); /* ... */ } catch(...) { /* ... */ } } 

Se você quiser versões no-throw destas funções, você terá que pegar as exceções apropriadas (eu não acho que boost::lexical_cast forneça uma versão no-throw), algo assim:

 #include  #include  #include  template  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  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(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; } } 

As outras respostas que usam streams serão bem-sucedidas mesmo que a string contenha caracteres inválidos após um número válido, por exemplo, “123abc”. Eu não estou familiarizado com o boost, então não posso comentar sobre o comportamento dele.

Se você quiser saber se a string contém um número e apenas um número, você deve usar o strtol:

 #include  #include  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 retorna um ponteiro para o caractere que finalizou a análise, para que você possa verificar facilmente se a string inteira foi analisada.

Note que strtol retorna um longo não um int, mas dependendo do seu compilador estes são provavelmente os mesmos. Não há function strtoi na biblioteca padrão, apenas atoi, que não retorna o caractere de terminação de análise.

Outra maneira de usar streams padrão:

 #include  #include  #include  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!"; } } 

Exceções não devem ser usadas para testes booleanos

A resposta aceita é realmente uma resposta terrível para a pergunta feita, pois viola o preceito “use exceções para casos excepcionais”.

As exceções são uma excelente ferramenta para lidar com casos excepcionais – casos em que algo realmente deu errado. Eles são ferramentas ruins para casos de uso existentes. Em parte porque jogar e pegar uma exceção é caro, e em parte porque é um código enganoso – quando um desenvolvedor vê uma exceção, deve razoavelmente ser capaz de assumir que algo está errado lá. Boas discussões sobre este princípio básico são abundantes, mas eu gosto de “O Programador Pragmático”, ou isto não é ruim: http://www.lohmy.de/2013/03/06/writing-use-cases-exception- ou-stream alternativo /

Use boost :: lexical_cast se você sempre espera um número

boost :: lexical_cast é uma ótima solução quando é uma exceção para receber um não-número.

Use boost :: try_lexical_convert se não-números fizerem parte do seu caso de uso

Se você está passando por uma string e quer fazer uma coisa se for um número, e outra se for um número, não use uma exceção para o teste booleano . Isso é apenas uma má programação.

Na verdade, o boost oferece o try_lexical_convert, que é usado na implementação do lexical_cast (extraído da documentação aqui: http://www.boost.org/doc/libs/1_58_0/doc/html/boost_lexical_cast/synopsis.html#boost_lexical_cast. synopsis.lexical_cast ).

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

Antes do lexical_cast do lexical_cast estar disponível, eu costumava fazer o seguinte:

 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 { static const T& stream_cast(const T& s) { return s; } }; template< typename Source > struct stream_caster { 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 { 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 { 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::stream_cast(s); }