String to int (atoi) bevezetése a Java-ban

A függvény először annyi szóköz karaktert vet el, amennyire szükséges az első nem fehér szóköz karakter található. Ezután ebből a karakterből kiindulva felvesz egy opcionális kezdő plusz vagy mínusz előjelet, amelyet a lehető legtöbb számjegy követ, és ezeket számértékként értelmezi.

A karakterlánc további karaktereket is tartalmazhat azok után, amelyek a integrálszám, amelyeket figyelmen kívül hagynak, és nincsenek hatással ennek a függvénynek a viselkedésére.

Ha az str-ben nem fehér szóköz nélküli karakterek első sorozata nem érvényes integrálszám, vagy ha nincs ilyen szekvencia, mert egyik sem Az str üres vagy csak szóköz karaktereket tartalmaz, konverzió nem kerül végrehajtásra.

Ha nem sikerült érvényes konverziót végrehajtani, akkor egy nulla érték kerül visszaadásra. Ha a helyes érték az ábrázolható értékek tartományán kívül esik, az INT_MAX (2147483647) vagy az INT_MIN (-2147483648) értéket adja vissza.

Nem vagyok biztos benne az egész számok túlcsordulásával kapcsolatos ellenőrzéseimről, de itt van a megvalósításom:

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

Válasz

Összességében ez “nagyon jó megvalósítás számos kulcsfontosságú részletben.

A Character.isDigit() és a Character.getNumericValue() módszereket jó látni.

A túlcsordulási feltételeket kezelő Math.* módszerek is jók.

Nem vagyok biztos benne ha szándékában állt, de helyesen kezel egy homályos edge-case-t is 32 bites előjelű egész számrendszerekben (nem csak a Java-ban), ahol az Integer.MIN_VALUE nem azonos a - Integer.MAX_VALUE … és a kódod valóban megfelelő a “-2147483648” szöveg pontos beviteléhez.

Tehát jó részletek vannak a kódodban …. és Nem látok törött éles eseteket.

Az egyetlen javaslatom az lenne, hogy egy állam-gép egyszerűbbé tegye a dolgokat … csak egy hurokkal ….. de lehet, hogy az állam-gép is kissé rendetlen, bár szerintem ez jobban működik hosszú távon …

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

Ne feledje, hogy egy nyers teljesítmény benchmarkban gyanítom, hogy a megoldása (kissé) gyorsabb lesz, de inkább az olvashatóságot kedvelem növekszik a teljesítménynövekedés, kivéve, ha a teljesítmény rendkívül kritikus.

Megjegyzések

  • +1 az államgép számára, mivel ez sokkal könnyebb, szinte mindig gyorsabb és sokkal könnyebb hibakeresés / kiterjesztés.

Válasz

A “-” karakternek van egy duplikált tesztje. Újraírnám

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

mint

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

A hexadecimálisok támogatását is hozzáadnám számok.

Megjegyzések

  • A switch blokk itt is jól működne.
  • Ah, ez ' igaz. A zuhanással rendelkező switch valószínűleg a legkevesebb duplikációval rendelkezik.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük