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

时间:2011-01-11 05:51:31

标签: c++ visual-c++

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

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

    return false;
}

33 个答案:

答案 0 :(得分:114)

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

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

或者如果你想用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();
}

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

答案 1 :(得分:73)

为什么重新发明轮子? C标准库(也可以在C ++中使用)具有完全正确的功能:

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

如果您想处理分数或科学记数法,请改为使用strtod(您将获得double结果)。

如果要允许C / C ++样式("0xABC")中的十六进制和八进制常量,请改为使用最后一个参数0

您的功能可以写成

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

答案 2 :(得分:28)

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

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

答案 3 :(得分:22)

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

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

http://ideone.com/OjVJWh

答案 4 :(得分:15)

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

-?[0-9]+([.][0-9]+)?

将显示字符串是否为数字。这包括正数和负数,整数和小数。

其他变体:

[0-9]+([.][0-9]+)?

(仅为正面)

-?[0-9]+

(仅整数)

[0-9]+

(仅正整数)

答案 5 :(得分:15)

我只想提出这个使用迭代的想法,但其他一些代码会进行迭代:

#include <string.h>

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

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

取出'。'和' - '如果只允许正整数。

答案 6 :(得分: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;
      }             
}

证明:C++ Program

答案 7 :(得分:8)

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

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

答案 8 :(得分:5)

试试这个:

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

答案 9 :(得分:5)

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

bool isNumber( std::string token )
{
    using namespace std;
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}

答案 10 :(得分:5)

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

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

答案 11 :(得分:3)

布兰登这个

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

几乎没问题。

假设任何以0开头的字符串都是数字, 只需为此案例添加支票

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

ofc“123hello”将像Tony D所说的那样返回。

答案 12 :(得分:2)

基于a comment by kbjorklu的解决方案是:

bool isNumber(const std::string& s)
{
   return !s.empty() && s.find_first_not_of("-.0123456789") == std::string::npos;
}

David Rector's answer一样,它对具有多个点或减号的字符串不健壮,但您可以删除这些字符以仅检查整数。


但是,我偏向于基于Ben Voigt's solution的解决方案,使用cstdlib中的strtod来查看十进制值,科学/工程符号,十六进制表示法(C ++ 11),甚至INF / INFINITY / NAN(C ++ 11)是:

bool isNumberC(const std::string& s)
{
    char* p;
    strtod(s.c_str(), &p);
    return *p == 0;
}

答案 13 :(得分:2)

我能想到的最简单的c ++

bool isNumber(string s) {
    if(s.size()==0) return false;
    for(int i=0;i<s.size();i++) {
        if((s[i]>='0' && s[i]<='9')==false) {
            return false;
        }
    }
    return true;
}

工作代码示例:https://ideone.com/nRX51Y

答案 14 :(得分:1)

使用<regex>。此代码已经过测试!

bool isNumber(const std::string &token)
{
    return std::regex_match(token, std::regex("(\\+|-)?[0-9]*(\\.?([0-9]+))$"));
}

答案 15 :(得分:1)

我们可以使用stringstream课程。

Intent

答案 16 :(得分:1)

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

答案 17 :(得分:1)

我的解决方案使用C ++ 11正则表达式(#include <regex>),它可用于更精确的检查,如unsigned intdouble等:

static const std::regex INT_TYPE("[+-]?[0-9]+");
static const std::regex UNSIGNED_INT_TYPE("[+]?[0-9]+");
static const std::regex DOUBLE_TYPE("[+-]?[0-9]+[.]?[0-9]+");
static const std::regex UNSIGNED_DOUBLE_TYPE("[+]?[0-9]+[.]?[0-9]+");

bool isIntegerType(const std::string& str_)
{
  return std::regex_match(str_, INT_TYPE);
}

bool isUnsignedIntegerType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_INT_TYPE);
}

bool isDoubleType(const std::string& str_)
{
  return std::regex_match(str_, DOUBLE_TYPE);
}

bool isUnsignedDoubleType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_DOUBLE_TYPE);
}

您可以在http://ideone.com/lyDtfi找到此代码,可以轻松修改此代码以满足要求。

答案 18 :(得分:1)

bool is_number(const string& s, bool is_signed)
{
    if (s.empty()) 
        return false;

    auto it_begin = s.begin();
    if (is_signed && (s.front() == '+' || s.front() == '-'))
        ++it_begin;

    auto non_digit = std::find_if(it_begin, s.end(), [](const char& c) { return !std::isdigit(c); });
    return non_digit == s.end();
}

答案 19 :(得分:1)

include <string>

验证双打:

bool validateDouble(const std::string & input) {
int decimals = std::count(input.begin(), input.end(), '.'); // The number of decimals in the string
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == decimals + negativeSigns) // Consists of only decimals and negatives or is empty
    return false;
else if (1 < decimals || 1 < negativeSigns) // More than 1 decimal or negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-.0123456789") != input.size()) // The string contains a character that isn't in "-.0123456789"
    return false;
return true;

}

用于验证Ints(带负片)

bool validateInt(const std::string & input) {
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == negativeSigns) // Consists of only negatives or is empty
    return false;
else if (1 < negativeSigns) // More than 1 negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-0123456789") != input.size()) // The string contains a character that isn't in "-0123456789"
    return false;
return true;

}

用于验证无符号的Ints

bool validateUnsignedInt(const std::string & input) {
return (input.size() != 0 && strspn(input.c_str(), "0123456789") == input.size()); // The string is not empty and contains characters only in "0123456789"

}

答案 20 :(得分:1)

bool isNumeric(string s){
    if ( !s.empty() && s[0] != '-' )
        s = "0" + s; //prepend 0

    string garbage;

    stringstream ss(s); 
    ss >> *(auto_ptr<double>(new double)) >> garbage;
/*
//the line above extracts the number into an anonymous variable. it could also be done like this:
double x;
ss >> x >> garbage;
*/
    //if there is no garbage return true or else return false
    return garbage.empty(); 
}

工作原理: stringstream&gt;&gt; overload可以将字符串转换为各种算术类型 它通过从字符串流(在本例中为ss)中顺序读取字符直到字符用完或者下一个字符不符合要存储到目标变量类型的条件来完成此操作。

例1:

stringstream ss("11");
double my_number;
ss >> my_number; //my number = 11

例2:

stringstream ss("011");
double my_number;
ss >> my_number; //my number = 11

示例3:

stringstream ss("11ABCD");
double my_number;
ss >> my_number; //my number = 11 (even though there are letters after the 11)

&#34;垃圾&#34;变量解释&#34;:

为什么不检查提取到我的double中是否有有效值,然后返回true,如果有的话?

注意上面的例子3仍然会成功地将数字11读入my_number变量,即使输入字符串是&#34; 11ABCD&#34; (这不是数字)。

为了处理这种情况,我们可以对字符串变量(我命名为garbage)进行另一次提取,它可以读取在初始提取到double类型变量后可能在字符串缓冲区中遗留的任何内容。如果剩下任何东西,它将被读入&#34;垃圾&#34;这意味着传入的完整字符串不是数字(它只是以一个开头)。在这种情况下,我们想要返回false;

前置&#34; 0&#34;说明&#34;:

尝试将单个字符提取到double中会失败(将0返回到我们的double中),但仍会将字符串缓冲区位置移动到字符后面。在这种情况下,我们的垃圾读取将为空,这将导致函数错误地返回true。 为了解决这个问题,我在字符串前加了一个0,这样如果传入的字符串是&#34; a&#34;它被改为&#34; 0a&#34;这样0将被提取到double和&#34; a&#34;被提取到垃圾中。

前置0不会影响数字的值,因此数字仍然可以正确地提取到我们的双变量中。

答案 21 :(得分:1)

检查字符串是否为数字整数或浮点数,或者您可以使用:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}

答案 22 :(得分:1)

我认为这个正则表达式几乎可以处理所有情况

"^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"

因此您可以尝试以下可以同时使用(Unicode和ANSI)

的函数
bool IsNumber(CString Cs){
Cs.Trim();

#ifdef _UNICODE
std::wstring sr = (LPCWSTR)Cs.GetBuffer(Cs.GetLength());
return std::regex_match(sr, std::wregex(_T("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?")));

#else
    std::string s = (LPCSTR)Cs.GetBuffer();
return std::regex_match(s, std::regex("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"));
#endif
}

答案 23 :(得分:1)

在更多地查阅文档之后,我想出了一个支持我需求的答案,但可能对其他人没有帮助。这是(没有恼人的返回true并返回虚假陈述:-))

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

答案 24 :(得分:0)

另一个答案是,使用stold(如果您不需要精确度,也可以使用stof / stod。)

bool isNumeric(const std::string& string)
{
    std::size_t pos;
    long double value = 0.0;

    try
    {
        value = std::stold(string, &pos);
    }
    catch(std::invalid_argument&)
    {
        return false;
    }
    catch(std::out_of_range&)
    {
        return false;
    }

    return pos == string.size() && !std::isnan(value);
}

答案 25 :(得分:0)

我提出了一个简单的约定:

如果转换为ASCII是&gt; 0或者从0开始然后它是一个数字。它不是完美而是快速。

这样的事情:

string token0;

if (atoi(token0.c_str())>0 || isdigit(token0.c_str()[0]) ) { //this is a value
    // do what you need to do...
}

答案 26 :(得分:0)

几个月前,我实现了一种方法来确定是否有任何字符串是整数,十六进制或双精度。

enum{
        STRING_IS_INVALID_NUMBER=0,
        STRING_IS_HEXA,
        STRING_IS_INT,
        STRING_IS_DOUBLE
};

bool isDigit(char c){
    return (('0' <= c) && (c<='9'));
}

bool isHexaDigit(char c){
    return ((('0' <= c) && (c<='9')) || ((tolower(c)<='a')&&(tolower(c)<='f')));
}


char *ADVANCE_DIGITS(char *aux_p){

    while(CString::isDigit(*aux_p)) aux_p++;
    return aux_p;
}

char *ADVANCE_HEXADIGITS(char *aux_p){

    while(CString::isHexaDigit(*aux_p)) aux_p++;
    return aux_p;
}


int isNumber(const string & test_str_number){
    bool isHexa=false;
    char *str = (char *)test_str_number.c_str();

    switch(*str){
    case '-': str++; // is negative number ...
               break;
    case '0': 
              if(tolower(*str+1)=='x')  {
                  isHexa = true;
                  str+=2;
              }
              break;
    default:
            break;
    };

    char *start_str = str; // saves start position...
    if(isHexa) { // candidate to hexa ...
        str = ADVANCE_HEXADIGITS(str);
        if(str == start_str)
            return STRING_IS_INVALID_NUMBER;

        if(*str == ' ' || *str == 0) 
            return STRING_IS_HEXA;

    }else{ // test if integer or float
        str = ADVANCE_DIGITS(str);
        if(*str=='.') { // is candidate to double
            str++;
            str = ADVANCE_DIGITS(str);
            if(*str == ' ' || *str == 0)
                return STRING_IS_DOUBLE;

            return STRING_IS_INVALID_NUMBER;
        }

        if(*str == ' ' || *str == 0)
            return STRING_IS_INT;

    }

    return STRING_IS_INVALID_NUMBER;


}

然后在您的程序中,如果执行以下操作,您可以轻松地将函数中的数字转换为其类型

string val; // the string to check if number...

switch(isNumber(val)){
   case STRING_IS_HEXA: 
   // use strtol(val.c_str(), NULL, 16); to convert it into conventional hexadecimal
   break;
   case STRING_IS_INT: 
   // use (int)strtol(val.c_str(), NULL, 10); to convert it into conventional integer
   break;
   case STRING_IS_DOUBLE:
   // use atof(val.c_str()); to convert it into conventional float/double
   break;
}

如果未检测到该数字,您可以意识到该函数将返回0。 0它可以被视为假(如布尔值)。

答案 27 :(得分:0)

此功能负责处理所有可能的情况:

bool AppUtilities::checkStringIsNumber(std::string s){
    //Eliminate obvious irritants that could spoil the party
    //Handle special cases here, e.g. return true for "+", "-", "" if they are acceptable as numbers to you
    if (s == "" || s == "." || s == "+" || s == "-" || s == "+." || s == "-.") return false;

    //Remove leading / trailing spaces **IF** they are acceptable to you
    while (s.size() > 0 && s[0] == ' ') s = s.substr(1, s.size() - 1);
    while (s.size() > 0 && s[s.size() - 1] == ' ') s = s.substr(0, s.size() - 1);


    //Remove any leading + or - sign
    if (s[0] == '+' || s[0] == '-')
        s = s.substr(1, s.size() - 1);

    //Remove decimal points
    long prevLength = s.size();

    size_t start_pos = 0;
    while((start_pos = s.find(".", start_pos)) != std::string::npos) 
        s.replace(start_pos, 1, "");

    //If the string had more than 2 decimal points, return false.
    if (prevLength > s.size() + 1) return false;

    //Check that you are left with numbers only!!
    //Courtesy selected answer by Charles Salvia above
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();

    //Tada....
}

答案 28 :(得分:0)

您可以简单地使用sscanf的返回码来确定它是否为int吗?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}

答案 29 :(得分:0)

尝试一下:

bool checkDigit(string str)
{  
   int n=str.length();

   for(int i=0;    i   < n ;   i++)
   {
     if(str[i]<'0' || str[i]>'9')
       return false;
   }

   return true;
}

答案 30 :(得分:0)

无符号整数的C / C ++样式,使用基于范围的for C ++ 11:

int isdigits(const std::string & s)
{
    for (char c : s) if (!isdigit(c)) return (0);
    return (1);
}

答案 31 :(得分:0)

您可以使用 boost :: lexical_cast 测试字符串是否可转换为整数。 如果抛出 bad_lexical_cast 异常,则无法转换字符串,否则可以转换。

请参见下面的此类测试程序示例:

#include <boost/lexical_cast.hpp>
#include <iostream>

int main(int, char** argv)
{
        try
        {
                int x = boost::lexical_cast<int>(argv[1]);
                std::cout << x << " YES\n";
        }
        catch (boost::bad_lexical_cast const &)
        {
                std:: cout << "NO\n";
        }
        return 0;
}

示例执行:

# ./a.out 12
12 YES
# ./a.out 12/3
NO

答案 32 :(得分:0)

确定字符串是否为数字的最简单和最基本的方法是仅检查字符串的第一个字符。然后用isdigit()正常检查。

string token = "99"
if(isdigit(token[0])) // CHECK FIRST CHAR OF THE STRING FOR NUMBER
        cout << token <<"\n";