Como posso saber se a função c atoi falhou ou se foi uma série de zeros?

StackOverflow https://stackoverflow.com/questions/1640720

  •  08-07-2019
  •  | 
  •  

Pergunta

Ao usar o atoi função (ou strtol ou funções semelhantes para que o assunto), como você pode dizer se a conversão inteiro falhou ou se o C-corda que estava sendo convertido era uma 0?

Para o que estou fazendo, 0 é um valor aceitável eo C-string a ser convertida pode conter qualquer número de 0s. Ele também pode ter os espaços em branco.

Foi útil?

Solução

Para C ++ 11 e posterior:

O go-to função para conversão de cadeia-a-inteiro está agora stoi , que leva um string e retorna um int, ou lança uma exceção em caso de erro.

Não há necessidade do detalhado istringstream corte mencionado na resposta aceita mais.

(Há também stol / stoll / stof / stod / stold para long / long long / float / double / long double conversões, respectivamente).

Outras dicas

A função adequada (desde que você está insistindo sobre o uso de funções de estilo C) é strtol e o código de conversão pode parecer da seguinte maneira

const char *number = "10"; /* for example */

char *end;
long value = strtol(number, &end, 10); 
if (end == number || *end != '\0' || errno == ERANGE)
  /* ERROR, abort */;

/* Success */
/* Add whatever range checks you want to have on the value of `value` */

Algumas observações:

strtol permite (significado: silenciosamente ignora) espaços em branco na frente do número real. Se você o que para tratar tais espaços de liderança como um erro, você tem que verificar por ele mesmo.

A verificação de *end != '\0' garante que não há nada após os dígitos. Se você quiser permitir que outros personagens após o número real (espaço em branco?), Essa verificação deve ser modificado em conformidade.

P.S. I adicionado a verificação end == number mais tarde para pegar sequências de entrada vazias. "Todos os espaços em branco" e "nenhum número em todos os" inputs teria sido capturado por cheque *end != '\0' sozinho. Pode fazer sentido para pegar de entrada vazia com antecedência embora. Em que o check caso end == number irá / poderá tornar desnecessário.

Uma vez que este é marcado :

template< typename T >
inline T convert(const std::string& str)
{
    std::istringstream iss(str);
    T obj;

    iss >> std::ws >> obj >> std::ws;

    if(!iss.eof())
        throw "dammit!";

    return obj; 
}

A partir da página de manual para strtol ():

Se endptr não é NULL, strtol () armazena o endereço do primeiro inválida personagem em * endptr. Se não houvesse dígitos em tudo, no entanto, strtol () armazena o valor original do nptr in * endptr. (Assim, se não é * nptr '\0' mas endptr ** é '\0' no retorno, toda a cadeia era válido.)

Uma alternativa para strtol é sscanf, embora seja um pouco pesado de peso:

const char *numStr = "12345";  // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
    ;  // parsing succeeded, use value
else
    ;  // error

No entanto, isso permite que os espaços em branco na cadeia (que pode ou não ser desejável), e permite que nada a trilhar o número, por isso "123abc" seria aceito e retornar 123. Se você quer ter um controle mais rígido, ir com strtol(), como AndreyT demonstra .

Tem sido um tempo desde que eu fiz e C / C ++, mas parece-me que o (excessivamente) solução simples seria a de verificar apenas a corda para "0".

int value = atoi(string_number.c_str());

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top