Como posso saber se a função c atoi falhou ou se foi uma série de zeros?
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 0
s. Ele também pode ter os espaços em branco.
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 c ++ :
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!
}