Forzare la funzione da stringa a int per consumare l'intera stringa

Forzare la funzione da stringa a int per consumare l'intera stringa

Modifica: In c++17 o versioni successive from_chars è preferito. Per ulteriori informazioni, vedere qui:https://topanswers.xyz/cplusplus?q=724#a839

Per un dato string str ci sono diversi modi per farlo, ciascuno con vantaggi e svantaggi. Ho scritto un esempio dal vivo qui:https://ideone.com/LO2Qnq e ne discuto di seguito:

strtol

Come suggerito qui strtol Il parametro out di ' può essere utilizzato per ottenere il numero di caratteri letti. strtol restituisce effettivamente un long non un int quindi al ritorno sta succedendo un cast.

char* size;
const int num = strtol(str.c_str(), &size, 10);

if(distance(str.c_str(), const_cast<const char*>(size)) == str.size()) {
    cout << "strtol: " << num << endl;
} else {
    cout << "strtol: error\n";
}

Nota che questo utilizza str.c_str() per fare riferimento alla stessa stringa. c_str Restituisce il puntatore all'array sottostante che funge da memoria di caratteri non temporanea se si dispone di C++11:

Nota anche che il puntatore restituito da c_str sarà valido tra il strtol e distance chiamate a meno che:

Se violi uno di questi casi, dovrai fare una copia temporanea di i 's sottostante const char* ed eseguire il test su quello.

sscanf

sscanf può usare %zn per restituire il numero di caratteri letti che potrebbe essere più intuitivo rispetto a un confronto del puntatore. Se la base è importante, sscanf potrebbe non essere una buona scelta. A differenza di strtol e stoi che supportano le basi 2 - 36, sscanf fornisce specificatori solo per ottale (%o ), decimale (%d ) ed esadecimale (%x ).

size_t size;
int num;

if(sscanf(str.c_str(), "%d%zn", &num, &size) == 1 && size == str.size()) {
    cout << "sscanf: " << num << endl;
} else {
    cout << "sscanf: error\n";
}

stoi

Come suggerito qui stoi il parametro di output funziona come sscanf è %n restituendo il numero di caratteri letti. In armonia con C++ questo richiede un string ea differenza delle implementazioni C sopra stoi lancia un invalid_argument se il primo carattere non di spazi bianchi non è considerato una cifra per la base corrente, e questo purtroppo significa che a differenza delle implementazioni C questo deve verificare la presenza di un errore sia nel try e catch blocchi.

try {
    size_t size;
    const auto num = stoi(str, &size);

    if(size == str.size()) {
        cout << "stoi: " << num << endl;
    } else {
        throw invalid_argument("invalid stoi argument");
    }
} catch(const invalid_argument& /*e*/) {
    cout << "stoi: error\n";
}