当我使用getline
时,我会输入一串字符串或数字,但我只希望while循环输出“word”,如果它不是数字。
那么有没有办法检查“word”是否是一个数字?我知道我可以使用atoi()
C字符串,但字符串类的字符串怎么样?
int main () {
stringstream ss (stringstream::in | stringstream::out);
string word;
string str;
getline(cin,str);
ss<<str;
while(ss>>word)
{
//if( )
cout<<word<<endl;
}
}
答案 0 :(得分:66)
另一个版本......
使用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是最好的答案:
strtol
乍一看似乎非常原始,所以解释会使代码更易于阅读:
strtol
将解析字符串,停止在第一个不能被视为整数一部分的字符处。如果您提供p
(如上所述),则会在此第一个非整数字符处设置p
。
我的理由是,如果p
未设置为字符串的结尾(0字符),则字符串s
中有一个非整数字符,表示{{1} }不是一个正确的整数。
第一个测试用于消除拐角情况(前导空格,空字符串等)。
当然,这个功能应该根据您的需要进行定制(导致空格错误等等)。
请参阅s
的说明:http://en.cppreference.com/w/cpp/string/byte/strtol。
另请参阅strtol
姐妹函数(strtol
,strtod
等)的说明。
答案 1 :(得分:55)
如果输入是数字加文本,则接受的答案将给出误报,因为“stol”将转换第一个数字并忽略其余数字。
我最喜欢以下版本,因为它是一个不需要定义功能的漂亮的单行程,您只需复制并粘贴到任何需要的地方。
#include <string>
...
std::string s;
bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::string::npos);
编辑:如果你喜欢这个实现,但你确实想将它作为一个函数使用,那么应该这样做:
bool has_only_digits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
答案 2 :(得分:16)
您可以尝试boost::lexical_cast
。如果失败,则抛出bad_lexical_cast
异常。
在你的情况下:
int number;
try
{
number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << word << "isn't a number" << std::endl;
}
答案 3 :(得分:8)
如果您只是检查word
是否为数字,那就不太难了:
#include <ctype.h>
...
string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
isNumber &&= isdigit(*k);
根据需要进行优化。
答案 4 :(得分:4)
您可以按照建议使用boost::lexical_cast
,但如果您对字符串有任何先验知识(即,如果字符串包含整数文字,则不会有任何前导空格,或者从不写入整数使用exponents),然后滚动你自己的函数应该更高效,而不是特别困难。
答案 5 :(得分:4)
使用功能强大的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
答案 6 :(得分:3)
好的,我看到你的方式有3种选择。
1:如果您只是想检查数字是否为整数,并且不关心转换它,只是希望将其保留为字符串并且不关心潜在的溢出,请检查它是否与整数的正则表达式在这里是理想的。
2:您可以使用boost :: lexical_cast然后捕获潜在的boost :: bad_lexical_cast异常以查看转换是否失败。如果你可以使用boost,那么这将很有效,如果失败则转换是一种特殊情况。
3:滚动你自己的类似于lexical_cast的函数来检查转换并返回true / false,具体取决于它是否成功。这适用于案例1和案例1。 2不符合您的要求。
答案 7 :(得分:1)
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");
答案 8 :(得分:1)
我修改了paercebal's method以满足我的需求:
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
,负值或值>36
作为基础。0
作为基础,则会自动检测基数,即以0x
开头的字符串将被视为十六进制,以0
开头的字符串将被视为倍频程这些字符不区分大小写。答案 9 :(得分:1)
这是另一种解决方案。
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
}
答案 10 :(得分:1)
从C ++ 11开始,您可以使用std::all_of和::isdigit:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string_view>
int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[])
{
auto isInt = [](std::string_view str) -> bool {
return std::all_of(str.cbegin(), str.cend(), ::isdigit);
};
for(auto &test : {"abc", "123abc", "123.0", "+123", "-123", "123"}) {
std::cout << "Is '" << test << "' numeric? "
<< (isInt(test) ? "true" : "false") << std::endl;
}
return 0;
}
使用Godbolt查看结果。