Come faccio a sapere se la funzione c atoi non è riuscita o se era una stringa di zeri?

StackOverflow https://stackoverflow.com/questions/1640720

  •  08-07-2019
  •  | 
  •  

Domanda

Quando si utilizza la funzione atoi (o strtol o funzioni simili), come si può sapere se la conversione di numeri interi non è riuscita o se la stringa C che era in fase di conversione era un 0 ?

Per quello che sto facendo, 0 è un valore accettabile e la stringa C convertita può contenere qualsiasi numero di 0 . Potrebbe anche avere spazi bianchi di testa.

È stato utile?

Soluzione

Per C ++ 11 e versioni successive:

La funzione go-to per la conversione da stringa a intero è ora stoi , che accetta una stringa e restituisce un int o genera un'eccezione in caso di errore.

Non è più necessario l'hacking dettagliato istringstream menzionato nella risposta accettata.

(C'è anche stol / stoll / stof / stod / stold per le conversioni long / long long / float / double / long double , rispettivamente .)

Altri suggerimenti

La funzione corretta (fintanto che insisti sull'uso delle funzioni di tipo C) è strtol e il codice di conversione potrebbe apparire come segue

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` */

Alcune osservazioni:

strtol consente (ovvero: salta silenziosamente) gli spazi bianchi di fronte al numero effettivo. Se vuoi trattare un simile spazio bianco come un errore, devi verificarlo da solo.

Il controllo per * end! = '\ 0' si assicura che non ci sia nulla dopo le cifre. Se si desidera consentire altri caratteri dopo il numero effettivo (spazi bianchi?), Questo controllo deve essere modificato di conseguenza.

P.S. Ho aggiunto il end == number più tardi per catturare sequenze di input vuote. " Tutti gli spazi bianchi " e "nessun numero" " gli input sarebbero stati catturati da * end! = '\ 0' da solo. Tuttavia, potrebbe essere utile acquisire in anticipo input vuoti. In tal caso il controllo end == number diventerà / potrebbe non essere necessario.

Poiché questo è etichettato :

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

Dalla pagina man di strtol ():

  

Se endptr non è NULL, strtol () memorizza l'indirizzo del primo non valido        carattere in * endptr. Se non c'erano affatto cifre, tuttavia, strtol ()        memorizza il valore originale di nptr in * endptr. (Pertanto, se * nptr non lo è         '\ 0' ma ** endptr è '\ 0' al ritorno, l'intera stringa era valida.)

Un'alternativa a strtol è sscanf , sebbene sia un po 'pesante:

const char *numStr = "12345";  // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
    ;  // parsing succeeded, use value
else
    ;  // error

Tuttavia, ciò consente di inserire spazi bianchi nella stringa (che può essere o meno desiderabile) e consente a qualsiasi cosa di trascinare il numero, quindi "123abc". verrebbe accettato e restituito 123. Se vuoi avere un controllo più stretto, vai con strtol () , come AndreyT dimostra .

È passato un po 'di tempo da quando ho fatto e C / C ++, ma mi sembrerebbe che la soluzione (eccessivamente) semplice sarebbe quella di controllare solo la stringa per " 0 " ;.

int value = atoi(string_number.c_str());

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top