Pregunta

Tengo un gran número almacenado en una cadena e intento extraer un solo dígito. ¿Pero cuáles son las diferencias entre esas llamadas?

#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;
}

Esto producirá el siguiente resultado.

  

dígito: 7

     

digit2: 2147483647

     

dígito3: 57230

El primero es el resultado deseado. El segundo me parece un número aleatorio, que no puedo encontrar en la cadena. El tercero es el final de la cadena, pero no solo un solo dígito como esperaba, sino desde el índice 12 hasta el final de la cadena. ¿Alguien puede explicarme las diferentes salidas?

EDITAR: ¿Sería una solución aceptable?

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

Solución

Todo es más o menos explicable.

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

Esta línea copia el carácter individual '5' en la variable de caracteres. atoi convertirá esto correctamente. atoi espera que el parámetro de cadena sea una cadena terminada en 0 válida. & amp; tmp es solo un puntero a la variable de caracteres: el comportamiento de esta llamada no está definido ya que la memoria que sigue inmediatamente al carácter en la memoria es desconocida. Para ser exactos, tendría que crear una cadena terminada en nulo y pasarla. *

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

Esta línea obtiene un puntero al carácter en la posición 5 de la cadena. Esto resulta ser un puntero en la cadena de números grandes original anterior, por lo que el parámetro de cadena a atoi se parece a la cadena "5720394857230". atoi claramente se desbordará tratando de convertir esto en un entero ya que ningún entero de 32 bits lo mantendrá.

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

Esta línea obtiene un puntero en la cadena en la posición 12. El parámetro para atoi es la cadena " 57230 " ;. Esto se convierte en el entero 57230 correctamente.

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

...     }

Dado que está utilizando C ++, existen mejores métodos para convertir cadenas de caracteres en enteros. Una de las que soy parcial es la biblioteca Boost lexical_cast. Lo usarías así:

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)));

* Estrictamente, atoi escaneará los caracteres numéricos hasta que se encuentre uno no numérico. Está claramente indefinido cuándo encontraría uno y qué hará al leer sobre ubicaciones de memoria no válidas.

Otros consejos

Sé por qué se muestra el segundo número.

De la referencia de atoi.

  

Si el valor correcto está fuera del rango de valores representables, se devuelve INT_MAX o INT_MIN.

2147483647 es INT_MAX

bigNumber.at () no devuelve una nueva cadena con un solo carácter sino la dirección de un carácter en la cadena. Entonces la segunda llamada es en realidad:

atoi("720394857230")

que hace que el algoritmo interno se desborde.

Además, la primera llamada es muy peligrosa ya que depende del valor (aleatorio) en la memoria en (& amp; tmp) +1 .

Debe asignar una cadena con dos caracteres, asignar el carácter único de bigNumber.at () al primero y \ 0 al segundo y luego llamar a < code> atoi () con la dirección de la cadena temporal.

El argumento para atoi debería ser una cadena terminada en cero.

La función en da el puntero a char en la cadena. La función atoi convierte la cadena a int, no solo un carácter.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top