如何确定字符串是否是带C++的数字?

Bre*_*ein 117 c++ visual-c++

我在编写一个检查字符串是否为数字的函数时遇到了很多麻烦.对于我正在编写的游戏,我只需要检查我正在阅读的文件中的一行是否是一个数字(我会知道这是一个参数).我编写了以下功能,我相信它工作顺利(或者我不小心编辑了以阻止它,或者我是精神分裂症或Windows是精神分裂症):

bool isParam (string line)
{
    if (isdigit(atoi(line.c_str())))
        return true;

    return false;
}
Run Code Online (Sandbox Code Playgroud)

Cha*_*via 128

最有效的方法是迭代字符串,直到找到一个非数字字符.如果有任何非数字字符,您可以认为该字符串不是数字.

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}
Run Code Online (Sandbox Code Playgroud)

或者如果你想用C++ 11方式做到这一点:

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
}
Run Code Online (Sandbox Code Playgroud)

正如下面的评论中所指出的,这仅适用于正整数.如果您需要检测负整数或分数,则应该使用更强大的基于库的解决方案.虽然,添加对负整数的支持是非常微不足道的.

  • 你也可以使用`!s.empty()&& s.find_first_not_of("0123456789")== std :: string :: npos;`用于C++ 03单线程. (68认同)
  • 也不处理十进制数,例如:1.23 (7认同)
  • 也不处理负数和非整数.我们无法根据问题知道要求是什么. (5认同)
  • 不要忘记包含`<string>``<algorithm>`和`<cctype>`来使C++ 11示例工作. (4认同)
  • @Remy Lebeau,是的。它实际上并没有将字符串转换为`int`。它只是在确定字符串是否由数字组成。字符串有多长都没关系。 (3认同)
  • 并且不处理不适合`int`的大数字. (2认同)

Ben*_*igt 76

为什么重新发明轮子?C标准库(也可以在C++中使用)有一个函数可以完成这个:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}
Run Code Online (Sandbox Code Playgroud)

如果你想处理分数或科学记数法,请strtod改为(你会得到一个double结果).

如果要在C/C++ style("0xABC")中允许十六进制和八进制常量,则0改为生成最后一个参数.

然后你的功能可以写成

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 此功能会丢弃前面的空白区域.因此,您必须检查isdigit的第一个char. (3认同)
  • 这个问题没有明确指定它,但我对要求“检查字符串是否是数字”的理解意味着整个字符串是数字,因此没有空格。我觉得有必要指出,在这方面你的答案与其他人的答案不同。如果字符串可以在数字前面有空格,那么您的答案可能没问题。 (2认同)
  • @BenVoigt 你是说如果 `strtol` 成功,`p` 将被设置为 `nullptr`,对吗?这不是我看到的:( (2认同)
  • @JonathanMee:不,`p`指向终止字符串的NUL。因此,“ p!= 0”和“ * p == 0”。 (2认同)

Edw*_*nge 27

您可以使用boost :: lexical_cast以C++方式完成.如果你真的坚持不使用boost,你可以检查它的作用并做到这一点.这很简单.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
Run Code Online (Sandbox Code Playgroud)

  • -1滥用try catch ... https://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx?Redirected=true (31认同)
  • 使用`try {} catch {}`一个好主意?我们应该尽可能避免吗? (20认同)
  • try {} catch {}在这里是合适的.然而,捕获(...)只是不好的做法.在这种情况下,请使用boost :: bad_lexical_cast作为异常处理程序. (14认同)
  • 我觉得这是试图从文件中读取.无论您对文件执行多少检查,您都不会知道在执行此操作之前是否可以从中读取.它要么工作要么不工作.在这种情况下,您将需要捕获异常.所以在这种情况下,我认为这是一种完美的方式. (5认同)
  • @EarlGray - 我当然有兴趣听听Windows操作系统依赖的操作.该标准非常清楚该代码的行为方式. (4认同)
  • 纳瓦兹 - 这里没有办法避免它.如果你想避免它,那么你需要重写lexical_cast.实际上,lexical_cast表现正常.如果字符串中的值不是数字,则它无法完成其工作.这是该功能的特殊情况. (3认同)
  • @Nawaz:不.有一个原因,它是C++语言的一部分.像所有C++构造一样,它应该在适当的地方使用.鉴于文件读取操作无论如何都是I/O绑定,这似乎并不过分. (2认同)
  • 这是滥用异常,在Windows上这将导致依赖于操作系统的操作,这对于简单的数字解码任务是不可接受的. (2认同)

szx*_*szx 22

使用C++ 11编译器,对于非负整数,我会使用类似的东西(注意::代替std::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}
Run Code Online (Sandbox Code Playgroud)

http://ideone.com/OjVJWh


Mep*_*ane 16

我建议采用正则表达式方法.一个完整的正则表达式匹配(例如,使用boost :: regex)

-?[0-9]+([.][0-9]+)?
Run Code Online (Sandbox Code Playgroud)

会显示字符串是否为数字.这包括正数和负数,整数以及小数.

其他变化:

[0-9]+([.][0-9]+)?
Run Code Online (Sandbox Code Playgroud)

(只有正面)

-?[0-9]+
Run Code Online (Sandbox Code Playgroud)

(仅整数)

[0-9]+
Run Code Online (Sandbox Code Playgroud)

(只有正整数)

  • @EarlGray:正则表达式仅适用于GCC 4.9 (2认同)

Dav*_*tor 15

我只是想抛出这个使用迭代的想法,但其他一些代码执行迭代:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}
Run Code Online (Sandbox Code Playgroud)

它在检查小数点或减号时应该是不健壮的,因为它允许每个和任何位置有多个.好消息是它只是一行代码,不需要第三方库.

取出'.' ' - '如果允许正整数.

  • 如果你打算使用`std :: string`,请使用它的`find_first_not_of`成员函数. (4认同)
  • 如果您传入一个"12.3-4.55-"字符串,这显然不是有效数字,这将失败 (4认同)

tzw*_*ckl 12

使用此解决方案,您可以检查从负数到正数甚至浮点数的所有内容.当您将类型更改num为整数时,如果字符串包含一个点,您将收到错误.

#include<iostream>
#include<sstream>
using namespace std;


int main()
{
      string s;

      cin >> s;

      stringstream ss;
      ss << s;

      float num = 0;

      ss >> num;

      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}
Run Code Online (Sandbox Code Playgroud)

证明:C++程序


mpa*_*i14 12

这是使用<regex>库执行此操作的另一种方法:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}
Run Code Online (Sandbox Code Playgroud)


dk1*_*123 7

我发现以下代码是最可靠的(c ++ 11)。它同时捕获整数和浮点数。

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}
Run Code Online (Sandbox Code Playgroud)


Jai*_*oto 5

这是检查正整数的解决方案:

bool isPositiveInteger(const std::string& s)
{
    return !s.empty() && 
           (std::count_if(s.begin(), s.end(), std::isdigit) == s.size());
}
Run Code Online (Sandbox Code Playgroud)


Noa*_*fen 5

布伦丹这个

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}
Run Code Online (Sandbox Code Playgroud)

差不多就可以了。

假设任何以 0 开头的字符串都是数字,只需添加此情况的检查

bool isNumber(const string &line) 
{
 if (line[0] == '0') return true;
 return (atoi(line.c_str()));
}
Run Code Online (Sandbox Code Playgroud)

ofc“123hello”将返回 true,就像 Tony D 指出的那样。


小智 5

尝试这个:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
Run Code Online (Sandbox Code Playgroud)


NoS*_*tAl 5

正如在回答我的相关问题时向我透露的那样,我觉得你应该使用boost::conversion::try_lexical_convert