如何确定一个字符串是否是一个数字与 C + + ?

我在编写一个检查字符串是否为数字的函数时遇到了很多麻烦。对于我正在编写的一个游戏,我只需要检查我正在读取的文件中的一行是否是一个数字(通过这种方式,我将知道它是否是一个参数)。我写了下面的函数,我相信它工作得很顺利(或者我不小心编辑了它来停止它,或者我是精神分裂症患者,或者 Windows 是精神分裂症患者) :

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


return false;
}
466255 次浏览

你可以用 C + + 的方式来做: : lexical _ cast。如果你真的坚持不使用助推器,你可以只是检查它做了什么,并做到这一点。很简单。

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

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

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(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

正如下面的评论中指出的,这只适用于正整数。如果需要检测负整数或小数,则应该使用更健壮的基于库的解决方案。不过,添加对负整数的支持非常简单。

在查阅了更多的文档之后,我得出了一个支持我的需求的答案,但是对其他人可能没有那么有帮助。在这里(没有恼人的返回 true 和返回 false 语句: ——)

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

我建议使用正则表达式方法

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

将显示字符串是否为数字。这包括正数和负数,整数以及十进制。

其他变化:

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

(只有正面)

-?[0-9]+

(只有整数)

[0-9]+

(只有正整数)

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

#include <string.h>


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

它不像检查小数点或负号时那样健壮,因为它允许在任何位置都有多个小数点或负号。好的一面是,它只是一行代码,不需要第三方库。

如果只允许正整数,则删除’.’和’-’。

下面是一个检查正整数的解决方案:

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

为什么要重新发明轮子?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;
}

有了这个解决方案,您可以检查从负数到正数,甚至浮点数的一切。当您将 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 + + 程序

对于 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

下面是使用 <regex>库的另一种方法:

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

布兰登

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 说的那样返回真实。

基于 Kbjorklu 的评论的解决方案是:

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

David Rector 的回答一样,它对带有多个点或负号的字符串不是很健壮,但是您可以删除这些字符来检查整数。


然而,我倾向于基于 Ben Voigt 的解决方案的解决方案,在 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;
}

几个月前,我实现了一种确定字符串是整数、十六进制还是双精度的方法。

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可以被视为假值(如布尔值)。

我提议一个简单的惯例:

如果转换为 ASCII 大于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...
}

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

"^(\\-|\\+)?[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
}

检查一个字符串是否是一个数字整数或浮点数,或者你可以使用:

 #include <sstream>


bool isNumber(string str) {
double d;
istringstream is(str);
is >> d;
return !is.fail() && is.eof();
}
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;

}

用于验证整数(带否定式)

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;

}

用于验证无符号整数

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"

}

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

工作原理: 字符串流 > > 重载可以将字符串转换为各种算术类型 它通过从字符串流(本例中为 ss)顺序读取字符,直到用完字符或下一个字符不符合存储到目标变量类型的条件。

例子一:

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

例子二:

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

例子三:

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

“垃圾”变量解释”:

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

注意,即使输入字符串是“11ABCD”(这不是一个数字) ,上面的 example3仍然会成功地将数字11读入 my _ number 变量。

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

预设的“0”解释:

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

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

我发现下面的代码是最健壮的(c + + 11)。

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

试试这个:

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

我能想到的最简单的 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

我的解决方案使用 C + + 11 regex (#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找到这个代码,这个可以很容易地修改以满足要求。

还有一个答案是使用 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);
}

正如它透露给我在一个 回答对我的相关问题,我觉得你应该使用 Boost: : conversion: : try _ lexical _ convert

我们可以使用 弦流类。

    bool isNumeric(string str)
{
stringstream stream;
double number;


stream<<str;
stream>>number;


return stream.eof();
}

使用 <regex>。这个代码已经测试过了!

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

该职能处理所有可能的情况:

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

您能简单地使用 sScanf 的返回代码来确定它是否是一个整型数吗?

bool is_number(const std::string& s)
{
int value;
int result = sscanf(valueStr.c_str(), "%d", &value);
return (result != EOF && readResult != 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;
}

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

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

您可以使用 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
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();
}

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

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

验证数字的字符串。

#include<bits/stdc++.h>
using namespace std;
int main()
{
char input[100];
gets(input);
int l = strlen(input);
int flag = 0;
for(int i = 0; i<l; i++)
{
if(input[i] < '0' || input[i] > '9')
{
flag = 1;
break;
}
}
if(flag == 0)
cout << "Input is a Number! " ;
else
cout << "Input is Not a Number! " ;
return 0;
}

以下基于 regex 的函数支持标准和科学记数法(例如 423.14-1+58.4e21.e-2-12.34e-56.1E4)中的有符号整数文字和十进制文字。前缀为零的整数也是匹配的(例如 0001) :

#include <string_view>
#include <regex>
 

bool is_number(std::string_view s) {
static std::regex const re{
R"([-+]?((\.\d+)|(\d+\.)|(\d+))\d*([eE][-+]?\d+)?)"};
return std::regex_match(s.data(), re);
}

十六进制文字,二进制文字,单引号分隔符和后缀(fFlLuUllLLZ)不匹配。

下面是一些使用 gtest 的单元测试

TEST(IsNumber, True) {
char const *tests[]{"42",     "3.14",    "-0",   "+4",    ".3",
"+.5",    "-.23",    "7.",   "1e2",   "1.e2",
"1.0e-2", "8.e+09",  "2E34", "61e2",  "-0e1",
"+0E+10", "-.01E-5", "07",   "+01E1", "12.34"};
for (auto const &x : tests) {
EXPECT_TRUE(is_number(x));
}
}


TEST(IsNumber, False) {
char const *tests[]{"4e",      "xyz",    ".3.14",   "--0",   "2-4",
"..3",     ".+5",    "7 2",     "1f",    "1.0f",
"1e-2.0",  "8e+0e1", "2E.4",    "a",     "e15",
"-0e10.3", ".e2",    "+1.2E0e", "1.2+3", "e1"};
for (auto const &x : tests) {
EXPECT_FALSE(is_number(x));
}
}