C++ 如何检查C++;字符串是整数吗?

C++ 如何检查C++;字符串是整数吗?,c++,string,types,stringstream,C++,String,Types,Stringstream,当我使用getline时,我会输入一组字符串或数字,但我只希望while循环在“word”不是数字时输出它。 那么,有没有办法检查“单词”是不是一个数字?我知道我可以使用atoi() C-strings但是string类的strings呢 int main () { stringstream ss (stringstream::in | stringstream::out); string word; string str; getline(cin,str); ss<&

当我使用
getline
时,我会输入一组字符串或数字,但我只希望while循环在“word”不是数字时输出它。 那么,有没有办法检查“单词”是不是一个数字?我知道我可以使用
atoi()
C-strings但是string类的strings呢

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

cout您可以尝试
boost::lexical\u cast
。如果失败,它将抛出一个
bad\u lexical\u 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;
}
整数;
尝试
{
number=boost::词法转换(word);
}
捕获(boost::bad_词法_cast&e)
{

好的,依我看,你有三个选择

1:如果您只是希望检查数字是否为整数,而不关心转换它,而只是希望将其保留为字符串,而不关心潜在的溢出,那么检查它是否与整数的正则表达式匹配将是理想的选择

2:您可以使用boost::lexical\u cast,然后捕获一个潜在的boost::bad\u lexical\u cast异常,以查看转换是否失败。如果您可以使用boost,并且转换失败是一种异常情况,那么这将很好地工作


3:使用类似于词法转换的函数来检查转换,并根据转换是否成功返回true/false。如果情况1和2不符合您的要求,这将起作用。

您可以按照建议使用
boost::lexical\u cast
,但前提是您事先了解字符串(也就是说,如果一个字符串包含一个整数文字,它将没有任何前导空格,或者整数永远不会用指数来写),那么滚动您自己的函数应该更有效,也不会特别困难。

template
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;
}
常量T至(常量字符串和sval) { T值; 细流ss; ss>val; if(ss.fail()) 抛出运行时错误((字符串)typeid(T).name()+“需要类型:”+sval); 返回val; }
然后你可以这样使用它:

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

inti=to(“4123”);

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

#include <ctype.h>
根据需要进行优化。

另一个版本

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

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是最好的答案:

  • 对于被授权失败的测试来说,使用异常是过分的
  • 当C标准库有一个鲜为人知的专用函数来完成这项工作时,由词法转换创建的临时流对象就显得过于简单和低效了
它是如何工作的?
strtol
乍一看似乎很原始,因此解释会使代码更易于阅读:

strtol
将解析字符串,在不能被视为整数一部分的第一个字符处停止。如果提供
p
(如上所述),它将在第一个非整数字符处设置
p

我的推理是,如果未将
p
设置为字符串的结尾(0字符),则字符串
s
中有一个非整数字符,这意味着
s
不是正确的整数

第一个测试是为了消除角点情况(前导空格、空字符串等)

当然,这个函数应该根据您的需要进行定制(前导空格是错误吗?等等)

资料来源: 有关strtol的说明,请参见:


另请参见
strtol
的姐妹函数(
strtod
strtoul
等)的说明。

使用功能强大的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
我已修改以满足我的需要:

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) ;
}

注意:

  • 您可以检查各种基数(二进制、oct、十六进制和其他)
  • 确保您没有传递
    1
    、负值或值
    >36
    作为基数
  • 如果将
    0
    作为基数传递,它将自动检测基数,即以
    0x
    开头的字符串将被视为十六进制,以
    0
    开头的字符串将被视为oct。字符不区分大小写
  • 字符串中的任何空格都将使其返回false

  • 如果输入是数字加文本,则接受的答案将给出假阳性,因为“stol”将转换第一个数字,而忽略其余数字


    我最喜欢下面的版本,因为它是一个很好的单行程序,不需要定义函数,您可以在任何需要的地方复制和粘贴它

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

    这是另一个解决方案

    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
    }
    

    由于C++11,您可以使用和:


    #include.

    选择一个。Regex不会告诉你它是否溢出了整数的范围。原始问题没有提到想要检查溢出,甚至想要使用一个数字作为整数。据我所知,他们计划将数字保留在一个字符串中以避免这样的限制。好吧,我尝试将回答更改为包含3个选项我最初列出的ons,每个ons都有一个原因。重复?我宁愿使用boost::lexical_cast。@SebastianMach对原始示例也是如此。+1,到目前为止是最好的答案。lexical_cast是过度使用,几乎是坏的做法。@David Titarenco:
    lexical_cast是过度使用,几乎是坏的做法。
    :仅当不小心使用时,对于任何其他功能也是如此。boost::lexical_cast的真正用途是用于泛型代码或快速脏代码。泛型代码:当您有未知类型T时,使用开关来使用strtol、strtol等是错误的。使用boost::lexical_cast是正确的,为正确的T提供boost::lexical_cast专门化高效使用的类型。快速脏代码:如果
    #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;
    }
    
    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
    }
    
    #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;
    }