Pergunta

Eu tenho um grande número armazenado em uma corda e tentar extrair um único dígito. Mas quais são as diferenças entre as chamadas?

#include <iostream>
#include <string>

int main(){
    std::string bigNumber = "93485720394857230";
    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
    int digit2 = atoi(&bigNumber.at(5))
    int digit3 = atoi(&bigNumber.at(12));
    std::cout << "digit: " << digit << std::endl;
    std::cout << "digit2: " << digit2 << std::endl;
    std::cout << "digit3: " << digit3 << std::endl;
}

Isto produzirá o seguinte resultado.

dígitos: 7

digit2: 2147483647

digit3: 57230

O primeiro é o resultado desejado. A segunda parece-me ser um número aleatório, o que eu não posso encontrar na seqüência. O terceiro é o fim da cadeia, mas não apenas um único dígito como eu esperava, mas a partir do índice de 12 a extremidade da corda. Alguém pode explicar as diferentes saídas para mim?

EDIT:? Será que isso é uma solução aceitável

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
Foi útil?

Solução

É tudo mais ou menos explicável.

int main(){
    std::string bigNumber = "93485720394857230";

Esta linha copia o caráter único '5' para a variável de caráter. atoi irá converter isso corretamente. espera atoi que o parâmetro de string é uma válida 0 string terminada. &tmp apenas um ponteiro para a variável de caráter - o comportamento desta chamada é indefinida já que a memória imediatamente após o personagem na memória é desconhecida. Para ser exato, você teria que criar uma cadeia nula terminada e passar isso em. *

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);

Esta linha recebe um ponteiro para o caractere na posição 5 na cadeia. Isto acontece por ser um ponteiro para a string grande número original acima - assim o parâmetro da sequência de olhares atoi como a string "5720394857230". atoi vai claramente oveflow tentando transformar isso em um inteiro desde há inteiro de 32 bit irá realizar isso.

    int digit2 = atoi(&bigNumber.at(5))

Esta linha recebe um ponteiro para a string na posição 12. O parâmetro para atoi é a string "57230". Esta é convertido para o número inteiro 57230 corretamente.

    int digit3 = atoi(&bigNumber.at(12));

... }

Uma vez que você estiver usando C ++, existem métodos mais agradável para cordas converter de caracteres em números inteiros. Um que eu sou parcial é o impulso lexical_cast biblioteca. Você poderia usá-lo como este:

char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));

// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));

* A rigor, atoi fará a varredura através dos caracteres numéricos até que um não-numérico é encontrado. é claramente indefinido-lo quando ele iria encontrar um e que ele vai fazer quando lê sobre locais de memória inválidos.

Outras dicas

Eu sei porque o segundo número é exibido.

Da referência atoi.

Se o valor correto está fora do intervalo de valores representáveis, INT_MAX ou INT_MIN é retornado.

2147483647 é INT_MAX

bigNumber.at() não retornar uma nova string com um único personagem, mas o endereço de um caractere na seqüência. Assim, a segunda chamada é realmente:

atoi("720394857230")

que faz com que o algoritmo interno para estouro.

Além disso, a primeira chamada é muito perigoso, uma vez que depende do valor (aleatório) na memória (&tmp)+1.

Você tem que alocar uma string com dois caracteres, atribuir o caráter único de bigNumber.at() ao primeiro e \0 para o segundo e, em seguida, chamar atoi() com o endereço da string temporário.

O argumento para atoi deve ser uma string terminada em zero.

at Função dá ponteiro para caractere na string. Função converte atoi string para int, não apenas um caractere.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top