Como determinar se uma seqüência de caracteres é um número com C ++?

136

Eu tive muitos problemas ao tentar escrever uma função que verifica se uma string é um número. Para um jogo que estou escrevendo, só preciso verificar se uma linha do arquivo que estou lendo é um número ou não (saberei se é um parâmetro dessa maneira). Eu escrevi a função abaixo que acredito estar funcionando sem problemas (ou editei acidentalmente para pará-la ou sou esquizofrênico ou o Windows é esquizofrênico):

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

    return false;
}
Brendan Weinstein
fonte
184
Eu odeio ver if (expr) return true; return false;! Apenas escreva return expr;.
ephemient 11/01
17
@ephemient Meu estilo é fazer o mesmo que você. Mas isso é realmente um grande negócio?
Brennan Vincent
2
Seu protótipo de função não parece apropriado. Por que não usar bool isParam (const string & line)
MikimotoH
4
Sim. Eu tenho o péssimo hábito de codificar estilo longo ao aprender um novo idioma. Eu sou novo em C ++ e mais hesitante em "atalhos" (ou atalhos percebidos).
Brendan Weinstein
57
@Brennan Vincent: Sim, é um grande negócio. É a mesma classe de erros como if (expr) return expr; else return expr;, if (expr == true), (if expr != false), ou if ((expr == true) == true). Todos eles introduzem complexidade que não beneficia o gravador, leitor ou compilador do código. A eliminação da complexidade desnecessária não é um atalho; é a chave para escrever um software melhor.
MSalters

Respostas:

148

A maneira mais eficiente seria iterar a string até encontrar um caractere que não seja um dígito. Se houver caracteres que não sejam dígitos, considere a sequência como um número.

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

Ou se você quiser fazer isso da maneira 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();
}

Como apontado nos comentários abaixo, isso funciona apenas para números inteiros positivos. Se você precisar detectar números inteiros ou frações negativos, use uma solução mais robusta baseada em biblioteca. Embora, adicionar suporte para números inteiros negativos seja bastante trivial.

Charles Salvia
fonte
6
Também não lida com números negativos e números não inteiros. Não podemos saber quais são os requisitos com base na pergunta.
Brennan Vincent
76
Você também pode usar !s.empty() && s.find_first_not_of("0123456789") == std::string::npos;para uma linha única C ++ 03.
kbjorklu
8
Também não lidar com números decimais por exemplo: 1,23
littlecodefarmer758
3
@Remy Lebeau, sim. Na verdade, não está convertendo a string em um int. É apenas identificar se uma string é composta de dígitos numéricos. Não importa quanto tempo a string seja.
Charles Salvia
5
Não se esqueça de incluir <string> <algorithm>e <cctype>fazer o exemplo do C ++ 11 funcionar.
kR105
88

Por que reinventar a roda? A biblioteca padrão C (disponível também em C ++) possui uma função que faz exatamente isso:

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

Se você quiser lidar com frações ou notação científica, vá strtodem frente (você obterá um doubleresultado).

Se você deseja permitir constantes hexadecimais e octais no estilo C / C ++ ( "0xABC"), crie o último parâmetro 0.

Sua função pode ser escrita como

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
Ben Voigt
fonte
4
Esta função descarta o espaço em branco na frente. Portanto, você deve verificar o primeiro caractere para isdigit.
chmike
1
@chmike: Com base no meu entendimento da questão, descartar espaços em branco à esquerda é o comportamento correto ( atoiconforme usado na pergunta, isso também é feito).
precisa
1
A pergunta não a especificou explicitamente, mas meu entendimento do requisito "verifica se uma sequência é um número" significa que toda a sequência é o número, portanto, não há espaços. Senti a necessidade de salientar que sua resposta é diferente das outras a esse respeito. Sua resposta pode ser boa se estiver ok para a string ter espaços na frente do número.
chmike
1
@BenVoigt Você está dizendo que pserá definido como nullptrse strtolfor bem sucedido, certo? Não é isso que estou vendo :(
Jonathan Mee
2
@ JonathanMee: Não, pestará apontando para o NUL que termina a string. Então p != 0e *p == 0.
Ben Voigt
33

Com o compilador C ++ 11, para números inteiros não negativos, usaria algo parecido com isto (observe o em ::vez de std::):

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

http://ideone.com/OjVJWh

szx
fonte
1
Esta é a melhor resposta.
Martin Broadhurst
Se houver caracteres utf8 na cadeia, você receberá um erro de tempo de execução.
Rei Leão
29

Você pode fazer isso da maneira C ++ com boost :: lexical_cast. Se você realmente insiste em não usar o impulso, pode apenas examinar o que ele faz e faz. É bem simples.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
Edward Strange
fonte
21
Usando try{} catch{}uma boa ideia? Não devemos evitá-lo o máximo possível?
Nawaz 11/01
32
-1 por abusar de tentar pegar ... blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
NoSenseEtAl 28/12/12
14
try {} catch {} é apropriado aqui. No entanto, pegar (...) é apenas uma má prática. Nesse caso, use boost :: bad_lexical_cast para seu manipulador de exceções.
27413 NuSkooler
5
Eu sinto que isso está tentando ler de um arquivo. Não importa quanta verificação você faça no arquivo, você não saberá se é possível lê-lo até fazê-lo. Ou vai funcionar ou não. Nesse caso, você precisará capturar uma exceção. Então, neste caso, acho que é uma maneira completamente boa de fazer isso.
Casey #
4
@EarlGray - Eu certamente estaria interessado em ouvir o que as ações dependentes do SO executariam. O padrão é bastante claro sobre como esse código deve se comportar.
Edward Strange
16

Eu só queria lançar essa ideia que usa a iteração, mas algum outro código faz essa iteração:

#include <string.h>

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

Não é robusto como deveria ser ao verificar um ponto decimal ou sinal de menos, pois permite que haja mais de um de cada e em qualquer local. O bom é que é uma única linha de código e não requer uma biblioteca de terceiros.

Retire o '.' e '-' se números inteiros positivos são tudo o que é permitido.

David Rector
fonte
de erro: 'strspn' não foi declarada neste âmbito Eu acho que isso é porque eu estou faltando um "#include", mas o que se
Qwertie
4
Se você for usar std::string, use sua find_first_not_offunção de membro.
Ben Voigt
5
Isso falharia se você passasse uma seqüência de caracteres "12.3-4.55-", que obviamente não é um número válido
#
Buzzrick, a resposta proposta já afirma que isso falharia com o número não mencionado.
David Rector
se você o limitar apenas a "0123456789", a fórmula será perfeita para testar um número inteiro
não
16

Eu sugeriria uma abordagem regex. Uma correspondência completa de regex (por exemplo, usando boost :: regex ) com

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

mostraria se a sequência é um número ou não. Isso inclui números positivos e negativos, números inteiros e decimais.

Outras variações:

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

(apenas positivo)

-?[0-9]+

(apenas número inteiro)

[0-9]+

(apenas número inteiro positivo)

Mephane
fonte
Ahem, tentei usar std::regexcom o gcc 4.7, o gcc 4.8 - ambos exibem std::regex_errorqualquer sinal de [regexp, mesmo para um inocente "[abc]" (eu faço isso errado?). clang-3.4 não tem conhecimento de <regex>nada. De qualquer forma, esta parece ser a resposta mais correta, +1.
Dmytro Sirenko
3
@EarlGray: Regex está disponível apenas corretamente no GCC 4.9
Lightness Races in Orbit
13

Aqui está outra maneira de fazer isso usando a <regex>biblioteca:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}
mpataki14
fonte
Ah, assim seria. Eu atualizei com uma solução melhor. Obrigado.
mpataki14
Não deveria ser "[(- | +) |] [0-9] +" (mais em vez de estrela); caso contrário, sua regex poderá corresponder a "-" ou "+" como um número válido.
David Mulder
Agradável. Não sei o que os (, | e) estão fazendo nessa primeira classe de caracteres - esses metacaracteres perdem seu significado especial dentro de uma classe de caracteres, até onde eu saiba. Que tal "^ [- +]? [0-9] + $"?
U007D
Pode ser ineficiente. Cada vez que isso é chamado, ele chama o construtor std :: regex que compila o regex.
user31264
12

Com esta solução, você pode verificar tudo, desde números negativos a positivos e até números flutuantes. Quando você altera o tipo de numpara inteiro, você receberá um erro se a string contiver um ponto.

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

Prove: Programa C ++

tzwickl
fonte
10

Eu achei o código a seguir como o mais robusto (c ++ 11). Ele captura números inteiros e flutuantes.

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}
dk123
fonte
Parece que a linha using namespace std;é desnecessária.
Xam
5

Aqui está uma solução para verificar números inteiros positivos:

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

Tente o seguinte:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
Tomasz
fonte
1
Ele testa apenas números inteiros não assinados
ninguém especial
4

Brendan this

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

está quase bem.

supondo que qualquer sequência iniciada com 0 seja um número, basta adicionar uma verificação para este caso

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

ofc "123hello" retornará verdadeiro como Tony D notou.

Noam Geffen
fonte
3

O mais simples que consigo pensar em 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;
}

Exemplo de código de trabalho: https://ideone.com/nRX51Y

Abhijit Annaldas
fonte
3

Minha solução usando C ++ 11 regex ( #include <regex>), pode ser usada para uma verificação mais precisa, como unsigned int, doubleetc:

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

Você pode encontrar esse código em http://ideone.com/lyDtfi , que pode ser facilmente modificado para atender aos requisitos.

aniliitb10
fonte
Eu pediria que os downvoters me ajudassem a entender o problema, melhorarei minha resposta. Obrigado.
precisa saber é o seguinte
2

Uma solução baseada em um comentário de kbjorklu é:

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

Como na resposta de David Rector, não é robusto para cadeias de caracteres com vários pontos ou sinais de menos, mas você pode remover esses caracteres para verificar apenas números inteiros.


No entanto, sou parcial de uma solução, com base na solução de Ben Voigt , usando strtodno cstdlib para procurar valores decimais, notação científica / de engenharia, notação hexidecimal (C ++ 11) ou até INF / INFINITY / NAN (C ++ 11) é:

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

Podemos usar uma classe stringstream .

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

       stream<<str;
       stream>>number;

       return stream.eof();
    }
rashedcs
fonte
2

Usando <regex>. Este código foi testado!

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

Depois de consultar um pouco mais a documentação, vim com uma resposta que suporta minhas necessidades, mas provavelmente não será tão útil para outras pessoas. Aqui está (sem o retorno irritante true e retorne declarações falsas :-))

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}
Brendan Weinstein
fonte
4
Se o número for 0, você receberá um falso negativo.
Charles Salvia
3
Isso retornará qualquer número inicial e não avisará você sobre o lixo final (por exemplo, "123hello" ==> 123). @ Charles: Brendan menciona que ele só precisa reconhecer ints positivos em um comentário em outra resposta.
Tony Delroy
1

Eu acho que essa expressão regular deve lidar com quase todos os casos

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

para que você possa tentar a seguinte função que pode funcionar com ambos (Unicode e 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
}
Motaz
fonte
1
include <string>

Para validar duplas:

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;

}

Para validar entradas (com negativos)

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;

}

Para validar entradas não assinadas

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"

}

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

como funciona: a sobrecarga stringstream >> pode converter seqüências de caracteres em vários tipos aritméticos, fazendo isso lendo caracteres seqüencialmente da stringstream (ss neste caso) até ficar sem caracteres OU o próximo caractere não atender aos critérios a serem armazenados no tipo de variável de destino.

Exemplo 1:

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

example2:

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

example3:

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

a explicação da variável "garbage" ":

por que não apenas verificar se a extração para o dobro tem um valor válido e, em seguida, retornar verdadeiro, se houver?

observe que o exemplo 3 acima ainda lerá com êxito o número 11 na variável my_number, mesmo que a sequência de entrada seja "11ABCD" (que não é um número).

Para lidar com esse caso, podemos fazer outra extração em uma variável de string (que chamei de lixo), que pode ler qualquer coisa que tenha sobrado no buffer de strings após a extração inicial na variável do tipo double. Se sobrar alguma coisa, ela será lida em "lixo", o que significa que a cadeia completa passada não era um número (apenas começa com um). nesse caso, gostaríamos de retornar false;

a explicação "0" anexada ":

a tentativa de extrair um único caractere para um duplo falhará (retornando 0 ao nosso duplo), mas ainda moverá a posição do buffer de sequência para depois do caractere. Nesse caso, nossa leitura de lixo estará vazia, o que faria com que a função retornasse incorretamente true. Para contornar isso, acrescentei um 0 à string, de modo que, por exemplo, a string passada fosse "a", ela fosse alterada para "0a", de modo que o 0 fosse extraído para o dobro e "a" extraído para o lixo.

preceder um 0 não afetará o valor do número, portanto o número ainda será extraído corretamente em nossa variável dupla.

KorreyD
fonte
1
Embora esse código possa responder à pergunta, fornecer um contexto adicional a respeito de por que e / ou como esse código responde à pergunta melhora seu valor a longo prazo.
Ajean
1

para verificar se uma sequência é um número inteiro ou ponto flutuante ou se você pode usar:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}
MuhammadKhalifa
fonte
1
isso retornará 10 para uma sequência que contenha o valor "10_is_not_a_number".
KorreyD
1

Outra resposta, que usa stold(embora você também possa usar stof/ stodse não precisar da precisão).

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);
}
Tim Angus
fonte
1

Tente o seguinte:

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;
}
rrlinus
fonte
1

Você pode testar se uma string é convertível em número inteiro usando boost :: lexical_cast . Se ele lançar bad_lexical_cast exceção , a sequência não poderá ser convertida, caso contrário, poderá.

Veja o exemplo de um programa de teste abaixo:

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

Execução de amostra:

# ./a.out 12
12 YES
# ./a.out 12/3
NO
Łukasz Ślusarczyk
fonte
0

Alguns meses atrás, implementei uma maneira de determinar se alguma sequência é inteira, hexadecimal ou dupla.

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;


}

Em seu programa, você pode converter facilmente o número em função do seu tipo, se você fizer o seguinte,

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

Você pode perceber que a função retornará um 0 se o número não for detectado. O 0 pode ser tratado como falso (como booleano).

Jordi Espada
fonte
0

Proponho uma convenção simples:

Se a conversão para ASCII for> 0 ou começar com 0, será um número. Não é perfeito, mas rápido.

Algo assim:

string token0;

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

Esta função cuida de todos os casos possíveis:

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....
}
Vaibhav Gupta
fonte
0

Você poderia simplesmente usar o código de retorno do sscanf para determinar se é um int?

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