如何检查 C++ 字符串是否为 int?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2844817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:15:15  来源:igfitidea点击:

How do I check if a C++ string is an int?

c++stringtypesstringstream

提问by user342231

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 循环输出不是数字的“单词”。那么有没有办法检查“单词”是否是数字?我知道我可以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;
    }
}

回答by paercebal

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?

为什么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 标准库有一个鲜为人知的专用函数来完成这项工作时,由词法转换创建的临时流对象是过度杀伤和效率低下的。

How does it work ?

它是如何工作的 ?

strtolseems quite raw at first glance, so an explanation will make the code simpler to read :

strtol乍一看似乎很原始,因此解释将使代码更易于阅读:

strtolwill 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 pright at this first non-integer character.

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

My reasoning is that if pis not set to the end of the string (the 0 character), then there is a non-integer character in the string s, meaning sis 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 strtolat: http://en.cppreference.com/w/cpp/string/byte/strtol.

请参阅strtol以下网址的说明:http: //en.cppreference.com/w/cpp/string/byte/strtol

See, too, the description of strtol's sister functions (strtod, strtoul, etc.).

见,也的描述strtol的姐姐函数(strtodstrtoul等)。

回答by Ferdinando Randisi

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.

如果输入是数字加文本,则接受的答案将给出误报,因为“stol”将转换第一位数字并忽略其余数字。

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>

...

std::string s;

bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::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;
}

回答by Karl von Moor

You might try boost::lexical_cast. It throws an bad_lexical_castexception if it fails.

你可以试试boost::lexical_castbad_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;
}

回答by Mike DeSimone

If you're just checking if wordis a number, that's not too hard:

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

#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.

根据需要进行优化。

回答by cmo

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

回答by Jacob

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 的函数,它检查转换并根据它是否成功返回真/假。如果 1 和 2 不符合您的要求,这将起作用。

回答by James

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按照建议使用,但是如果您对字符串有任何先验知识(即,如果字符串包含整数文字,则它不会有任何前导空格,或者整数永远不会用指数书写),然后滚动您自己的函数应该既高效又不特别难。

回答by Nicolas Viennot

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

回答by Jahid

I have modified paercebal's methodto 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:

笔记:

  1. You can check for various bases (binary, oct, hex and others)
  2. Make sureyou don't pass 1, negative value or value >36as base.
  3. If you pass 0as the base, it will auto detect the base i.e for a string starting with 0xwill be treated as hex and string starting with 0will be treated as oct. The characters are case-insensitive.
  4. Any white space in string will make it return false.
  1. 您可以检查各种基数(二进制、八进制、十六进制等)
  2. 制作确保你不及格1,负值或价值>36为基础。
  3. 如果您0作为基数传递,它将自动检测基数,即以 开头的字符串0x将被视为十六进制,而以 开头的字符串0将被视为八进制。字符不区分大小写。
  4. 字符串中的任何空格都会使其返回 false。

回答by Phidelux

Since C++11 you can make use of std::all_ofand ::isdigit:

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

Check out the result with Godbolt.

使用Godbolt查看结果。