Pergunta

Usando apenas ANSI C, que é a melhor maneira, com certeza justo, determinar se um C cadeia de estilo é um número inteiro ou um número real (o eu.e float/double)?

Foi útil?

Solução

Não use atoi e atof como essas funções retornam 0 em caso de falha.A última vez que eu chequei 0 é um número inteiro válido e flutuante, portanto, não utilizar para a determinação do tipo.

use o strto{l,ul,ull,ll,d} funções, como o conjunto de errno em caso de falha, e também um relatório onde os dados convertidos terminou.

strtoul: http://www.opengroup.org/onlinepubs/007908799/xsh/strtoul.html

este exemplo assume que a cadeia contém um único valor a ser convertido.

#include <errno.h>

char* to_convert = "some string";
char* p = to_convert;
errno = 0;
unsigned long val = strtoul(to_convert, &p, 10);
if (errno != 0)
    // conversion failed (EINVAL, ERANGE)
if (to_convert == p)
    // conversion failed (no characters consumed)
if (*p != 0)
    // conversion failed (trailing data)

Graças a Jonathan Leffler para apontar que eu esqueci de definir errno para 0 primeiro.

Outras dicas

Usando sscanf, você pode estar certo se a seqüência de caracteres é um float ou int ou o que quer sem ter que caso especial 0, como é o caso com atoi e atof solução.

Eis alguns exemplo de código:

int i;
float f;
if(sscanf(str, "%d", &i) != 0) //It's an int.
  ...
if(sscanf(str "%f", &f) != 0)  //It's a float.
  ...

atoi e atof irá converter ou retornar 0 se ele não pode.

Concordo com Patrick_O que o strto{l,ul,ull,ll,d} funções são a melhor maneira de ir.Há um par de pontos de assistir embora.

  1. Defina errno para zero antes de chamar as funções;nenhuma função faz isso para você.
  2. Abrir página de Grupo de associado (que eu fui antes de perceber que Patrick havia ligado para ele também) aponta que errno não pode ser definido.Ele é definido para ERANGE se o valor está fora do intervalo;ele pode ser definido (mas, igualmente, pode não ser definido) para EINVAL se o argumento é inválido.

Dependendo do trabalho na mão, eu vou, por vezes, fazer saltar o espaço em branco à direita do final da conversão ponteiro retornado, e depois reclamar (rejeitar) se o último caractere é não nulo '\0'.Ou posso ser desleixado e deixe lixo aparecem no final, ou eu posso aceitar opcional multiplicadores como 'K', 'M', 'G', 'T' para kilobytes, megabytes, gigabytes, terabytes, ...ou qualquer outra exigência com base no contexto.

Eu suponho que você poderia passo da seqüência de caracteres e verificar se há alguma . personagens na mesma.Essa é apenas a primeira coisa que surgiu na minha cabeça que, assim que eu tenho certeza que existem outros (melhores) maneiras de ser mais certo.

Use strtol/strtoll (não atoi) para verificação de números inteiros.Use strtof/strtod (não atof) para verificar duplos.

atoi e atof converter a parte inicial da cadeia, mas não sei dizer se são ou não utilizado todo o seqüência de caracteres.strtol/strtod dizer-lhe se havia de lixo extra após os caracteres convertidos.

Assim, em ambos os casos, lembre-se de passar em um não-nulo CAUDA parâmetro, e verificar que ele aponta para o fim da cadeia de caracteres (isto é, **CAUDA == 0).Também verifique o valor de retorno para o underflow e overflow (veja as páginas do man ou padrão ANSI para detalhes).

Note-se também que strod/strtol ignorar inicial espaços em branco, por isso, se você quiser tratar seqüências de caracteres de espaço em branco inicial como mal-formatado, você também precisa verificar o primeiro caractere.

Ela realmente depende de qual você está pedindo em primeiro lugar.

Se você apenas deseja analisar um número e não sei se é um float ou um número inteiro, então é só analisar um float, que vai analisar corretamente um número inteiro assim.

Se você realmente quer saber o tipo, talvez para triagem e, em seguida, você realmente deve considerar os tipos de testes na ordem que você considere mais relevantes.Como tentar analisar um número inteiro e se você não pode, em seguida, tentar analisar um float.(O contrário só vai produzir um pouco mais flutua...)

atoi e atof irá converter o número, mesmo se são finais não caracteres numéricos.No entanto, se você usar strtol e strtod não só irá ignorar espaço em branco à esquerda e um sinal opcional, mas deixar você com um ponteiro para o primeiro caractere que não seja de número.Em seguida, você pode verificar que o resto é o espaço em branco.

Bem, se você não se sentir como a utilização de uma nova função, como strtoul, você pode simplesmente adicionar outro strcmp instrução para ver se a string é o 0.

i.e.

if(atof(token) != NULL || strcmp(token, "0") == 0)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top