When I use getline
, I would input a bunch of strings or numbers, but I only want the while loop to output the "word" if it is not a number. So is there any way to check if "word" is a number or not? I know I could use atoi()
for C-strings but how about for strings of the string class?
当我使用getline时,我会输入一串字符串或数字,但如果不是数字,我只希望while循环输出“word”。那么有什么方法可以检验“word”是否是一个数字呢?我知道我可以对c -string使用atoi()但是字符串类的字符串呢?
int main () {
stringstream ss (stringstream::in | stringstream::out);
string word;
string str;
getline(cin,str);
ss<<str;
while(ss>>word)
{
//if( )
cout<<word<<endl;
}
}
10 个解决方案
#1
62
Another version...
另一个版本…
Use strtol
, wrapping it inside a simple function to hide its complexity :
使用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) ;
}
Why strtol
?
As far as I love C++, sometimes the C API is the best answer as far as I am concerned:
就我对c++的热爱而言,有时C API是我认为最好的答案:
- using exceptions is overkill for a test that is authorized to fail
- 对于授权为失败的测试,使用异常是多余的
- the temporary stream object creation by the lexical cast is overkill and over-inefficient when the C standard library has a little known dedicated function that does the job.
- 当C标准库有一个鲜为人知的专用函数来完成这项工作时,lexical cast所创建的临时流对象就会显得太过无效。
How does it work ?
strtol
seems quite raw at first glance, so an explanation will make the code simpler to read :
strtol乍一看似乎很生疏,所以一种解释会让代码更简单:
strtol
will parse the string, stopping at the first character that cannot be considered part of an integer. If you provide p
(as I did above), it sets p
right at this first non-integer character.
strtol将解析字符串,在不能被视为整数部分的第一个字符处停止。如果您提供p(如我上面所做的),它会在第一个非整数字符上设置p。
My reasoning is that if p
is not set to the end of the string (the 0 character), then there is a non-integer character in the string s
, meaning s
is not a correct integer.
我的推理是,如果没有将p设置为字符串的末尾(0字符),那么字符串s中就有一个非整数,这意味着s不是一个正确的整数。
The first tests are there to eliminate corner cases (leading spaces, empty string, etc.).
第一个测试是消除角落情况(前导空间、空字符串等)。
This function should be, of course, customized to your needs (are leading spaces an error? etc.).
当然,这个函数应该是根据您的需要定制的(前导空间是错误的吗?)等等)。
Sources :
See the description of strtol
at: http://en.cppreference.com/w/cpp/string/byte/strtol.
参见:http://en.cppreference.com/w/cpp/string/byte/strtol对strtol的描述。
See, too, the description of strtol
's sister functions (strtod
, strtoul
, etc.).
也可以看到斯特尔的姐妹函数的描述(strtod, strtoul,等等)。
#2
50
The accepted answer will give a false positive if the input is a number plus text, because "stol" will convert the firsts digits and ignore the rest.
如果输入是数字加文本,则接受的答案将给出一个错误的正数,因为“短距”将转换第一个数字并忽略其余数字。
I like the following version the most, since it's a nice one-liner that doesn't need to define a function and you can just copy and paste wherever you need it.
我最喜欢下面的版本,因为它是一个很好的一行程序,不需要定义函数,您可以在任何需要它的地方复制和粘贴。
#include <string>
...
string s;
bool has_only_digits = (s.find_first_not_of( "0123456789" ) == string::npos);
EDIT: if you like this implementation but you do want to use it as a function, then this should do:
编辑:如果你喜欢这个实现,但你确实想把它作为一个函数使用,那么它应该是:
bool has_only_digits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
#3
16
You might try boost::lexical_cast
. It throws an bad_lexical_cast
exception if it fails.
你可以尝试提高::lexical_cast。如果失败,它将抛出bad_lexical_cast异常。
In your case:
在你的例子:
int number;
try
{
number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << word << "isn't a number" << std::endl;
}
#4
8
If you're just checking if word
is a number, that's not too hard:
如果你只是检查单词是否是一个数字,这并不难:
#include <ctype.h>
...
…
string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
isNumber &&= isdigit(*k);
Optimize as desired.
根据需要优化。
#5
4
You can use boost::lexical_cast
, as suggested, but if you have any prior knowledge about the strings (i.e. that if a string contains an integer literal it won't have any leading space, or that integers are never written with exponents), then rolling your own function should be both more efficient, and not particularly difficult.
boost::lexical_cast可以使用,建议,但是如果你有任何关于琴弦的先验知识(即,如果一个字符串包含一个整数文字它不会有任何领导空间,或整数从不与指数),然后滚自己的函数应该更有效率,而不是特别困难。
#6
3
Ok, the way I see it you have 3 options.
我觉得你有3种选择。
1: If you simply wish to check whether the number is an integer, and don't care about converting it, but simply wish to keep it as a string and don't care about potential overflows, checking whether it matches a regex for an integer would be ideal here.
1:如果您只是想检查这个数字是否是一个整数,而不关心它的转换,而只想将它作为一个字符串保存,而不关心潜在的溢出,那么检查它是否与正则表达式匹配以获得一个整数在这里是理想的。
2: You can use boost::lexical_cast and then catch a potential boost::bad_lexical_cast exception to see if the conversion failed. This would work well if you can use boost and if failing the conversion is an exceptional condition.
2:您可以使用boost::lexical_cast,然后捕获一个潜在的boost::bad_lexical_cast异常,以查看转换是否失败。如果您可以使用boost,这将很好地工作,如果转换失败是一个例外情况。
3: Roll your own function similar to lexical_cast that checks the conversion and returns true/false depending on whether it's successful or not. This would work in case 1 & 2 doesn't fit your requirements.
3:滚动自己的函数,类似于lexical_cast,它检查转换并根据转换是否成功返回true/false。这适用于情况1和2不符合您的要求。
#7
3
Use the all-powerful C stdio/string functions:
使用全功能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
#8
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;
}
And then you can use it like that:
然后你可以这样使用:
double d = to<double>("4.3");
or
或
int i = to<int>("4123");
#9
1
Here is another solution.
这是另一个解决方案。
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
0
I have modified paercebal's method to meet my needs:
为了满足我的需要,我修改了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) ;
}
Note:
注意:
- You can check for various bases (binary, oct, hex and others)
- 您可以检查各种基(二进制、oct、十六进制等)
- Make sure you don't pass
1
, negative value or value>36
as base. - 确保你没有传递1、负值或>36作为基础。
- If you pass
0
as the base, it will auto detect the base i.e for a string starting with0x
will be treated as hex and string starting with0
will be treated as oct. The characters are case-insensitive. - 如果你通过0作为基数,它会自动检测基数i。以0x开头的字符串e将被视为十六进制,以0开头的字符串将被视为十月,这些字符是不区分大小写的。
- Any white space in string will make it return false.
- 字符串中的任何空格都会使它返回false。
#1
62
Another version...
另一个版本…
Use strtol
, wrapping it inside a simple function to hide its complexity :
使用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) ;
}
Why strtol
?
As far as I love C++, sometimes the C API is the best answer as far as I am concerned:
就我对c++的热爱而言,有时C API是我认为最好的答案:
- using exceptions is overkill for a test that is authorized to fail
- 对于授权为失败的测试,使用异常是多余的
- the temporary stream object creation by the lexical cast is overkill and over-inefficient when the C standard library has a little known dedicated function that does the job.
- 当C标准库有一个鲜为人知的专用函数来完成这项工作时,lexical cast所创建的临时流对象就会显得太过无效。
How does it work ?
strtol
seems quite raw at first glance, so an explanation will make the code simpler to read :
strtol乍一看似乎很生疏,所以一种解释会让代码更简单:
strtol
will parse the string, stopping at the first character that cannot be considered part of an integer. If you provide p
(as I did above), it sets p
right at this first non-integer character.
strtol将解析字符串,在不能被视为整数部分的第一个字符处停止。如果您提供p(如我上面所做的),它会在第一个非整数字符上设置p。
My reasoning is that if p
is not set to the end of the string (the 0 character), then there is a non-integer character in the string s
, meaning s
is not a correct integer.
我的推理是,如果没有将p设置为字符串的末尾(0字符),那么字符串s中就有一个非整数,这意味着s不是一个正确的整数。
The first tests are there to eliminate corner cases (leading spaces, empty string, etc.).
第一个测试是消除角落情况(前导空间、空字符串等)。
This function should be, of course, customized to your needs (are leading spaces an error? etc.).
当然,这个函数应该是根据您的需要定制的(前导空间是错误的吗?)等等)。
Sources :
See the description of strtol
at: http://en.cppreference.com/w/cpp/string/byte/strtol.
参见:http://en.cppreference.com/w/cpp/string/byte/strtol对strtol的描述。
See, too, the description of strtol
's sister functions (strtod
, strtoul
, etc.).
也可以看到斯特尔的姐妹函数的描述(strtod, strtoul,等等)。
#2
50
The accepted answer will give a false positive if the input is a number plus text, because "stol" will convert the firsts digits and ignore the rest.
如果输入是数字加文本,则接受的答案将给出一个错误的正数,因为“短距”将转换第一个数字并忽略其余数字。
I like the following version the most, since it's a nice one-liner that doesn't need to define a function and you can just copy and paste wherever you need it.
我最喜欢下面的版本,因为它是一个很好的一行程序,不需要定义函数,您可以在任何需要它的地方复制和粘贴。
#include <string>
...
string s;
bool has_only_digits = (s.find_first_not_of( "0123456789" ) == string::npos);
EDIT: if you like this implementation but you do want to use it as a function, then this should do:
编辑:如果你喜欢这个实现,但你确实想把它作为一个函数使用,那么它应该是:
bool has_only_digits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
#3
16
You might try boost::lexical_cast
. It throws an bad_lexical_cast
exception if it fails.
你可以尝试提高::lexical_cast。如果失败,它将抛出bad_lexical_cast异常。
In your case:
在你的例子:
int number;
try
{
number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << word << "isn't a number" << std::endl;
}
#4
8
If you're just checking if word
is a number, that's not too hard:
如果你只是检查单词是否是一个数字,这并不难:
#include <ctype.h>
...
…
string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
isNumber &&= isdigit(*k);
Optimize as desired.
根据需要优化。
#5
4
You can use boost::lexical_cast
, as suggested, but if you have any prior knowledge about the strings (i.e. that if a string contains an integer literal it won't have any leading space, or that integers are never written with exponents), then rolling your own function should be both more efficient, and not particularly difficult.
boost::lexical_cast可以使用,建议,但是如果你有任何关于琴弦的先验知识(即,如果一个字符串包含一个整数文字它不会有任何领导空间,或整数从不与指数),然后滚自己的函数应该更有效率,而不是特别困难。
#6
3
Ok, the way I see it you have 3 options.
我觉得你有3种选择。
1: If you simply wish to check whether the number is an integer, and don't care about converting it, but simply wish to keep it as a string and don't care about potential overflows, checking whether it matches a regex for an integer would be ideal here.
1:如果您只是想检查这个数字是否是一个整数,而不关心它的转换,而只想将它作为一个字符串保存,而不关心潜在的溢出,那么检查它是否与正则表达式匹配以获得一个整数在这里是理想的。
2: You can use boost::lexical_cast and then catch a potential boost::bad_lexical_cast exception to see if the conversion failed. This would work well if you can use boost and if failing the conversion is an exceptional condition.
2:您可以使用boost::lexical_cast,然后捕获一个潜在的boost::bad_lexical_cast异常,以查看转换是否失败。如果您可以使用boost,这将很好地工作,如果转换失败是一个例外情况。
3: Roll your own function similar to lexical_cast that checks the conversion and returns true/false depending on whether it's successful or not. This would work in case 1 & 2 doesn't fit your requirements.
3:滚动自己的函数,类似于lexical_cast,它检查转换并根据转换是否成功返回true/false。这适用于情况1和2不符合您的要求。
#7
3
Use the all-powerful C stdio/string functions:
使用全功能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
#8
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;
}
And then you can use it like that:
然后你可以这样使用:
double d = to<double>("4.3");
or
或
int i = to<int>("4123");
#9
1
Here is another solution.
这是另一个解决方案。
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
0
I have modified paercebal's method to meet my needs:
为了满足我的需要,我修改了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) ;
}
Note:
注意:
- You can check for various bases (binary, oct, hex and others)
- 您可以检查各种基(二进制、oct、十六进制等)
- Make sure you don't pass
1
, negative value or value>36
as base. - 确保你没有传递1、负值或>36作为基础。
- If you pass
0
as the base, it will auto detect the base i.e for a string starting with0x
will be treated as hex and string starting with0
will be treated as oct. The characters are case-insensitive. - 如果你通过0作为基数,它会自动检测基数i。以0x开头的字符串e将被视为十六进制,以0开头的字符串将被视为十月,这些字符是不区分大小写的。
- Any white space in string will make it return false.
- 字符串中的任何空格都会使它返回false。