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.
if (expr) return true; return false;
! Apenas escrevareturn expr;
.