如何检查一个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( strtod
, strtoul
等)的描述。
我最喜欢下面的版本,因为它是一个不需要定义函数的好的单行版本,只需要复制和粘贴就可以了。
#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_cast
exception。
在你的情况下:
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) ; }
注意:
- 你可以检查各种基地(二进制,十进制,hex等)
- 确保你没有通过
1
,负值或值>36
作为基础。 - 如果你传递
0
作为基地,它会自动检测基地,即以0x
开始的string将被视为hex,以0
开始的string将被视为八。 字符不区分大小写。 - 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 }