Wie kann ich feststellen, ob die atoi c Funktion fehlgeschlagen ist oder wenn es eine Reihe von Nullen?
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 0
s enthalten. Es kann auch führende Leerzeichen haben.
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 c ++ :
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!
}