Implementieren eines Strings in int (atoi) in Java

Die Funktion verwirft zunächst so viele Leerzeichen wie nötig, bis Das erste Nicht-Leerzeichen wird gefunden. Ausgehend von diesem Zeichen wird dann ein optionales Plus- oder Minuszeichen gefolgt von möglichst vielen numerischen Ziffern verwendet und als numerischer Wert interpretiert.

Die Zeichenfolge kann nach denen, die das bilden, zusätzliche Zeichen enthalten Integralzahl, die ignoriert wird und keinen Einfluss auf das Verhalten dieser Funktion hat.

Wenn die erste Folge von Nicht-Leerzeichen in str keine gültige Ganzzahl ist oder wenn keine solche Folge existiert, weil auch nicht str ist leer oder enthält nur Leerzeichen. Es wird keine Konvertierung durchgeführt.

Wenn keine gültige Konvertierung durchgeführt werden konnte, wird ein Nullwert zurückgegeben. Wenn der korrekte Wert außerhalb des Bereichs der darstellbaren Werte liegt, wird INT_MAX (2147483647) oder INT_MIN (-2147483648) zurückgegeben.

Ich bin nicht sicher über meine Überprüfungen gegen Ganzzahlüberlauf, aber hier ist meine Implementierung:

public int myAtoi(String str) { int i = 0; while (i < str.length() && Character.isWhitespace(str.charAt(i))) { ++i; } if (i == str.length()) { return 0; } boolean isNegative = false; if (str.charAt(i) == "+" || str.charAt(i) == "-") { isNegative = str.charAt(i) == "-"; ++i; } int result = 0; while (i < str.length() && Character.isDigit(str.charAt(i))) { try { result = Math.multiplyExact(result, 10); result = Math.addExact(result, Character.getNumericValue(str.charAt(i))); } catch (ArithmeticException e) { return isNegative ? Integer.MIN_VALUE : Integer.MAX_VALUE; } ++i; } if (isNegative) { result = -result; } return result; } 

Antwort

Alles in allem ist dies eine ziemlich gute Implementierung in einer Reihe von Schlüsseldetails.

Verwenden von Character.isDigit() und Character.getNumericValue() -Methoden sind gut zu sehen.

Die Math.* -Methoden, die mit den Überlaufbedingungen umgehen, sind ebenfalls gut.

Ich bin nicht sicher Wenn Sie es beabsichtigt haben, aber auch einen obskuren Randfall in 32-Bit-Ganzzahlsystemen mit Vorzeichen (nicht nur Java) korrekt behandeln, wobei Integer.MIN_VALUE nicht mit - Integer.MAX_VALUE … und Ihr Code macht es tatsächlich richtig für eine genaue Eingabe des Textes „-2147483648“

Sie haben also gute Details in Ihrem Code …. und Ich kann keine Fälle mit gebrochenen Kanten sehen.

Meine einzige Empfehlung wäre, dass eine Zustandsmaschine die Dinge einfacher macht … mit nur einer Schleife … aber die Zustandsmaschine kann auch ein bisschen chaotisch sein, obwohl ich denke, dass sie in besser funktioniert auf lange Sicht …

public static int rlAtoi(String str) { boolean started = false; boolean negative = false; int result = 0; try { for (char c : str.toCharArray()) { if (!started && Character.isWhitespace(c)) { // great, ignore it. } else if (!started && (c == "+" || c == "-")) { // great, a sign negative = c == "-"; started = true; } else if (Character.isDigit(c)) { result = Math.multiplyExact(result, 10); result = Math.addExact(result, Character.getNumericValue(c)); started = true; } else { // done.... break; } } } catch (ArithmeticException e) { return negative ? Integer.MIN_VALUE : Integer.MAX_VALUE; } return negative ? -result : result; } 

Beachten Sie, dass Ihre Lösung in einem Rohleistungs-Benchmark (etwas) schneller sein wird, aber ich bevorzuge die Lesbarkeit gegenüber kleinen inkrementelle Leistungssteigerungen, es sei denn, die Leistung ist äußerst kritisch.

Kommentare

  • +1 für die Zustandsmaschine, da dies viel einfacher, fast immer schneller und viel ist einfacher zu debuggen / zu erweitern.

Antwort

Es gibt einen doppelten Test für das Zeichen „-„. Ich würde

boolean isNegative = false; if (str.charAt(i) == "+" || str.charAt(i) == "-") { isNegative = str.charAt(i) == "-"; ++i; } 

als

boolean isNegative = false; if (str.charAt(i) == "-") { isNegative= true; ++i; } else if (str.charAt(i) == "+") ++i; 

umschreiben. Ich würde auch Unterstützung für Hexadezimal hinzufügen Zahlen.

Kommentare

  • Ein switch Block würde auch hier gut funktionieren.
  • Ah, das ' ist wahr. Ein switch mit Durchfall hätte wahrscheinlich die geringste Duplizierung.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.