Domanda

Ho un grande numero memorizzato in una stringa e provo ad estrarre una singola cifra. Ma quali sono le differenze tra queste chiamate?

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

Questo produrrà il seguente output.

  

cifra: 7

     

digit2: 2147483647

     

digit3: 57230

Il primo è il risultato desiderato. Il secondo mi sembra un numero casuale, che non riesco a trovare nella stringa. La terza è la fine della stringa, ma non solo una singola cifra come mi aspettavo, ma sale dal 12 ° indice alla fine della stringa. Qualcuno può spiegarmi le diverse uscite?

EDIT: sarebbe una soluzione accettabile?

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

Soluzione

È tutto più o meno spiegabile.

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

Questa riga copia il singolo carattere '5' nella variabile carattere. atoi lo convertirà correttamente. atoi si aspetta che il parametro string sia una stringa con terminazione 0 valida. & amp; tmp è solo un puntatore alla variabile carattere - il comportamento di questa chiamata non è definito poiché la memoria immediatamente successiva al carattere in memoria è sconosciuta. Per l'esattezza, dovresti creare una stringa terminata null e passarla in. *

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

Questa riga ottiene un puntatore al carattere in posizione 5 nella stringa. Questo sembra essere un puntatore nella stringa di numeri grandi originale sopra - quindi il parametro stringa in atoi sembra la stringa " 5720394857230 " ;. atoi chiaramente scorrerà cercando di trasformarlo in un numero intero poiché nessun numero a 32 bit lo terrà.

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

Questa riga ottiene un puntatore nella stringa nella posizione 12. Il parametro per atoi è la stringa & Quot; 57230 " ;. Questo viene convertito correttamente nell'intero 57230.

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

...     }

Dato che stai usando C ++, ci sono metodi migliori per convertire stringhe di caratteri in numeri interi. Uno dei quali sono parziale è la libreria lexical_cast di Boost. Lo useresti così:

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

* In senso stretto, atoi scansiona i caratteri numerici fino a quando non ne viene trovato uno non numerico. È chiaramente indefinito quando ne troverà uno e cosa farà quando rileggerà posizioni di memoria non valide.

Altri suggerimenti

So perché viene visualizzato il 2 ° numero.

Dal riferimento atoi.

  

Se il valore corretto non rientra nell'intervallo dei valori rappresentabili, viene restituito INT_MAX o INT_MIN.

2147483647 è INT_MAX

bigNumber.at () non restituisce una nuova stringa con un singolo carattere ma l'indirizzo di un carattere nella stringa. Quindi la seconda chiamata è in realtà:

atoi("720394857230")

che causa l'overflow dell'algoritmo interno.

Inoltre, la prima chiamata è molto pericolosa poiché dipende dal valore (casuale) in memoria su (& amp; tmp) +1 .

Devi assegnare una stringa con due caratteri, assegnare il singolo carattere da bigNumber.at () al primo e \ 0 al secondo e quindi chiamare < code> atoi () con l'indirizzo della stringa temporanea.

L'argomento per atoi dovrebbe essere una stringa con terminazione zero.

La funzione in fornisce il puntatore al carattere nella stringa. La funzione atoi converte la stringa in int, non solo un carattere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top