Wie kann ich feststellen, ob die atoi c Funktion fehlgeschlagen ist oder wenn es eine Reihe von Nullen?

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

  •  08-07-2019
  •  | 
  •  

Frage

Wenn Sie die Funktion atoi (oder strtol oder ähnliche Funktionen für diese Angelegenheit), wie kann man sagen, ob die Integer-Konvertierung fehlgeschlagen ist oder wenn der C-String, ist ein 0 umgewandelt wurde?

Für das, was ich tue, 0 ist ein akzeptabler Wert und die C-String umgewandelt wird eine beliebige Anzahl von 0s enthalten. Es kann auch führende Leerzeichen haben.

War es hilfreich?

Lösung

Für ++ 11 C und höher:

Die Go-to-Funktion für String-to-Integer-Konvertierung ist jetzt stoi , die eine string nimmt und eine int zurückgibt, oder eine Ausnahme auf Fehler führt.

Keine Notwendigkeit für den ausführlichen istringstream Hack in der akzeptierten Antwort erwähnte mehr.

(Es gibt auch stol / stoll / stof / stod / stold für long / long long / float / double / long double Umwandlungen sind.)

Andere Tipps

Die richtige Funktion (so lange, wie Sie C-Stil-Funktionen zur Verwendung von beharren) ist strtol und der Conversion-Code könnte wie folgt aussehen

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

Einige Bemerkungen:

strtol erlaubt (was bedeutet: leise springt) Leerzeichen vor der tatsächlichen Zahl. Wenn Sie, was eine solche führende Leerzeichen als Fehler zu behandeln, haben Sie es selbst überprüfen.

Die Prüfung auf *end != '\0' stellt sicher, dass nichts nach den Ziffern gibt. Wenn Sie andere Zeichen nach der tatsächlichen Anzahl (Leerzeichen?) Zulassen möchten, diese Prüfung entsprechend werden muss geändert werden.

P. S. Ich fügte hinzu, die end == number Prüfung später leere Eingabesequenzen zu fangen. „Alle Leerzeichen“ und „keine Zahl an alle“ Eingaben von *end != '\0' Check allein gefangen worden wäre. Es könnte sinnvoll sein, wenn leere Eingabe im Voraus zu fangen. In diesem Fall end == number Prüfung wird / könnte überflüssig werden.

Da diese markiert :

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

Aus der Manpage für strtol ():

  

Wenn endptr nicht NULL ist, strtol () speichert die Adresse des ersten ungültigen        Charakter in * endptr. Wenn es überhaupt keine Ziffern waren jedoch strtol ()        speichert den ursprünglichen Wert von nptr in * endptr. (Wenn also * nptr nicht        '\0' aber ** endptr ist '\0' auf Rückkehr, die gesamte Zeichenfolge gültig war.)

Eine Alternative zu strtol ist sscanf, obwohl es ein wenig schwer Gewicht ist:

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

Dies ist jedoch erlaubt in der Zeichenfolge Leerzeichen führt, (die kann oder auch nicht wünschenswert sein) und es erlaubt alles um die Nummer zu schleppen, so „123abc“ angenommen und zurück würde 123. Wenn Sie eine strengere Kontrolle haben wollen, geht mit strtol(), wie AndreyT zeigt .

Es ist eine Weile her, dass ich getan habe und C / C ++, aber es würde mir scheint, dass die (zu) einfache Lösung für die „0“ nur die Zeichenfolge zu überprüfen wäre.

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

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top