如何检查一个C ++string是一个整数?

当我使用getline ,我会input一串string或者数字,但是如果它不是一个数字,我只希望while循环输出“word”。 那么有什么办法来检查“单词”是否是一个数字? 我知道我可以使用atoi()的Cstring,但如何处理string类的string?

 int main () { stringstream ss (stringstream::in | stringstream::out); string word; string str; getline(cin,str); ss<<str; while(ss>>word) { //if( ) cout<<word<<endl; } } 

另一个版本…

使用strtol ,将其包装在一个简单的函数中,以隐藏其复杂性:

 inline bool isInteger(const std::string & s) { if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ; char * p ; strtol(s.c_str(), &p, 10) ; return (*p == 0) ; } 

为什么strtol

就我喜欢C ++而言,有时C API是我所关心的最好答案:

  • 使用例外对于被授权失败的testing是过度的
  • 当C标准库具有一些已知的专用function来执行作业时,由词法转换创build的临时stream对象是过度杀伤和过度低效的。

它是如何工作的 ?

strtol乍一看似乎相当原始,所以一个解释会使代码更易于阅读:

strtol将parsingstring,停止在不能被视为整数的一部分的第一个字符。 如果你提供了p (就像我上面所做的那样),它将p设置在第一个非整数字符处。

我的推理是,如果p没有设置为string的末尾(0字符),那么在strings有一个非整数字符,这意味着s不是一个正确的整数。

第一个testing是在那里消除angular落案件(领先的空间,空的string等)。

当然,这个function应该根据你的需要定制(是否有领先的空格出错?等等)。

来源:

请参阅以下strtol的描述: http : //en.cppreference.com/w/cpp/string/byte/strtol 。

还请看strtol的妹妹function( strtodstrtoul等)的描述。

我最喜欢下面的版本,因为它是一个不需要定义函数的好的单行版本,只需要复制和粘贴就可以了。

 #include <string> ... string s; bool has_only_digits = (s.find_first_not_of( "0123456789" ) == string::npos); 

编辑:如果你喜欢这个实现,但你确实想使用它作为一个函数,那么这应该做的:

 bool has_only_digits(const string s){ return s.find_first_not_of( "0123456789" ) == string::npos; } 

你可以尝试boost::lexical_cast 。 如果失败,它会抛出一个bad_lexical_castexception。

在你的情况下:

 int number; try { number = boost::lexical_cast<int>(word); } catch(boost::bad_lexical_cast& e) { std::cout << word << "isn't a number" << std::endl; } 

如果你只是检查word是否是一个数字,那并不难:

 #include <ctype.h> 

 string word; bool isNumber = true; for(string::const_iterator k = word.begin(); k != word.end(); ++k) isNumber &&= isdigit(*k); 

根据需要进行优化。

你可以使用boost::lexical_cast ,正如所build议的那样,但是如果你有任何有关string的知识(例如,如果一个string包含一个整数字面值,它将不会有任何前导空间,或者那些整数永远不会被写成指数)那么滚动你自己的function应该更有效率,而不是特别困难。

好吧,我看到它有3个选项。

1:如果你只是想检查数字是否是一个整数,不关心转换,但只是希望保持它作为一个string,不关心潜在的溢出,检查它是否匹配一个正则expression式整数在这里是理想的。

2:你可以使用boost :: lexical_cast,然后捕获潜在的boost :: bad_lexical_castexception,看看转换是否失败。 如果您可以使用boost,并且如果转换失败是一个例外条件,这将工作得很好。

3:滚动你自己的函数,类似于lexical_cast,检查转换并根据是否成功返回true / false。 如果1&2不符合您的要求,这将工作。

使用全能的C stdio /string函数:

 int dummy_int; int scan_value = std::sscanf( some_string.c_str(), "%d", &dummy_int); if (scan_value == 0) // does not start with integer else // starts with integer 
 template <typename T> const T to(const string& sval) { T val; stringstream ss; ss << sval; ss >> val; if(ss.fail()) throw runtime_error((string)typeid(T).name() + " type wanted: " + sval); return val; } 

然后你可以这样使用它:

 double d = to<double>("4.3"); 

要么

 int i = to<int>("4123"); 

我已经修改了paercebal的方法来满足我的需求:

 typedef std::string String; bool isInt(const String& s, int base){ if(s.empty() || std::isspace(s[0])) return false ; char * p ; strtol(s.c_str(), &p, base) ; return (*p == 0) ; } bool isPositiveInt(const String& s, int base){ if(s.empty() || std::isspace(s[0]) || s[0]=='-') return false ; char * p ; strtol(s.c_str(), &p, base) ; return (*p == 0) ; } bool isNegativeInt(const String& s, int base){ if(s.empty() || std::isspace(s[0]) || s[0]!='-') return false ; char * p ; strtol(s.c_str(), &p, base) ; return (*p == 0) ; } 

注意:

  1. 你可以检查各种基地(二进制,十进制,hex等)
  2. 确保你没有通过1 ,负值或值>36作为基础。
  3. 如果你传递0作为基地,它会自动检测基地,即以0x开始的string将被视为hex,以0开始的string将被视为八。 字符不区分大小写。
  4. string中的任何空格将使其返回false。

这是另一个解决scheme。

 try { (void) std::stoi(myString); //cast to void to ignore the return value //Success! myString contained an integer } catch (const std::logic_error &e) { //Failure! myString did not contain an integer }