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;
}
c++
visual-c++
Brendan Weinstein
fonte
fonte
if (expr) return true; return false;
! Apenas escrevareturn expr;
.if (expr) return expr; else return expr;
,if (expr == true)
,(if expr != false)
, ouif ((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.Respostas:
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.
Ou se você quiser fazer isso da maneira C ++ 11:
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.
fonte
!s.empty() && s.find_first_not_of("0123456789") == std::string::npos;
para uma linha única C ++ 03.int
. É apenas identificar se uma string é composta de dígitos numéricos. Não importa quanto tempo a string seja.<string>
<algorithm>
e<cctype>
fazer o exemplo do C ++ 11 funcionar.Por que reinventar a roda? A biblioteca padrão C (disponível também em C ++) possui uma função que faz exatamente isso:
Se você quiser lidar com frações ou notação científica, vá
strtod
em frente (você obterá umdouble
resultado).Se você deseja permitir constantes hexadecimais e octais no estilo C / C ++ (
"0xABC"
), crie o último parâmetro0
.Sua função pode ser escrita como
fonte
atoi
conforme usado na pergunta, isso também é feito).p
será definido comonullptr
sestrtol
for bem sucedido, certo? Não é isso que estou vendo :(p
estará apontando para o NUL que termina a string. Entãop != 0
e*p == 0
.Com o compilador C ++ 11, para números inteiros não negativos, usaria algo parecido com isto (observe o em
::
vez destd::
):http://ideone.com/OjVJWh
fonte
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.
fonte
try{} catch{}
uma boa ideia? Não devemos evitá-lo o máximo possível?Eu só queria lançar essa ideia que usa a iteração, mas algum outro código faz essa iteração:
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.
fonte
std::string
, use suafind_first_not_of
função de membro.Eu sugeriria uma abordagem regex. Uma correspondência completa de regex (por exemplo, usando boost :: regex ) com
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:
(apenas positivo)
(apenas número inteiro)
(apenas número inteiro positivo)
fonte
std::regex
com o gcc 4.7, o gcc 4.8 - ambos exibemstd::regex_error
qualquer 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.Aqui está outra maneira de fazer isso usando a
<regex>
biblioteca:fonte
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
num
para inteiro, você receberá um erro se a string contiver um ponto.Prove: Programa C ++
fonte
Eu achei o código a seguir como o mais robusto (c ++ 11). Ele captura números inteiros e flutuantes.
fonte
using namespace std;
é desnecessária.Aqui está uma solução para verificar números inteiros positivos:
fonte
Tente o seguinte:
fonte
Brendan this
está quase bem.
supondo que qualquer sequência iniciada com 0 seja um número, basta adicionar uma verificação para este caso
ofc "123hello" retornará verdadeiro como Tony D notou.
fonte
O mais simples que consigo pensar em c ++
Exemplo de código de trabalho: https://ideone.com/nRX51Y
fonte
Minha solução usando C ++ 11 regex (
#include <regex>
), pode ser usada para uma verificação mais precisa, comounsigned int
,double
etc:Você pode encontrar esse código em http://ideone.com/lyDtfi , que pode ser facilmente modificado para atender aos requisitos.
fonte
Uma solução baseada em um comentário de kbjorklu é:
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
strtod
no cstdlib para procurar valores decimais, notação científica / de engenharia, notação hexidecimal (C ++ 11) ou até INF / INFINITY / NAN (C ++ 11) é:fonte
Podemos usar uma classe stringstream .
fonte
Usando
<regex>
. Este código foi testado!fonte
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 :-))
fonte
0
, você receberá um falso negativo.Eu acho que essa expressão regular deve lidar com quase todos os casos
para que você possa tentar a seguinte função que pode funcionar com ambos (Unicode e ANSI)
fonte
Para validar duplas:
}
Para validar entradas (com negativos)
}
Para validar entradas não assinadas
}
fonte
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:
example2:
example3:
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.
fonte
para verificar se uma sequência é um número inteiro ou ponto flutuante ou se você pode usar:
fonte
Outra resposta, que usa
stold
(embora você também possa usarstof
/stod
se não precisar da precisão).fonte
Como me foi revelado em resposta à minha pergunta relacionada, acho que você deve usar o boost :: conversion :: try_lexical_convert
fonte
Tente o seguinte:
fonte
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:
Execução de amostra:
fonte
Alguns meses atrás, implementei uma maneira de determinar se alguma sequência é inteira, hexadecimal ou dupla.
Em seu programa, você pode converter facilmente o número em função do seu tipo, se você fizer o seguinte,
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).
fonte
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:
fonte
Esta função cuida de todos os casos possíveis:
fonte
Você poderia simplesmente usar o código de retorno do sscanf para determinar se é um int?
fonte