Implementering af streng til int (atoi) i Java

Funktionen kasserer først så mange hvide mellemrumstegn, indtil det er nødvendigt det første tegn, der ikke er mellemrum, findes. Fra dette tegn tager det derefter et valgfrit plus- eller minustegn efterfulgt af så mange numeriske cifre som muligt og fortolker dem som en numerisk værdi.

Strengen kan indeholde yderligere tegn efter dem, der danner integralt nummer, som ignoreres og ikke har nogen indflydelse på denne funktions opførsel.

Hvis den første række af ikke-hvide mellemrumstegn i str ikke er et gyldigt integralt tal, eller hvis der ikke findes en sådan sekvens, fordi enten str er tom, eller den indeholder kun tegn i mellemrum, der udføres ingen konvertering.

Hvis der ikke kunne udføres nogen gyldig konvertering, returneres en nulværdi. Hvis den korrekte værdi er uden for området for repræsentative værdier, returneres INT_MAX (2147483647) eller INT_MIN (-2147483648).

Jeg er ikke sikker om mine kontroller mod heltalsoverløb, men her er min implementering:

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

Svar

Alt i alt er det “en ret god implementering i et antal nøgledetaljer.

Brug af Character.isDigit() og Character.getNumericValue() metoder er gode at se.

Math.* -metoderne, der håndterer overløbsbetingelserne, er også gode.

Jeg er ikke sikker hvis du har tænkt dig det, men du også håndterer korrekt en obskur edge-case i 32-bit signerede heltalssystemer (ikke kun Java), hvor Integer.MIN_VALUE ikke er det samme som - Integer.MAX_VALUE … og din kode får det rigtigt til en nøjagtig indtastning af teksten “-2147483648”

Så du har gode detaljer i din kode …. og Jeg kan ikke se brudte kantsager.

Min eneste anbefaling ville være, at en statsmaskine kan gøre tingene enklere … med kun en sløjfe ….. men statsmaskinen kan også være lidt rodet, selvom jeg synes, det fungerer bedre i i det lange løb …

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

Bemærk, at i en rå performance-benchmark, formoder jeg, at din løsning vil være (lidt) hurtigere, men jeg foretrækker læsbarhed frem for lille inkrementelle præstationsgevinster, medmindre ydeevne er ekstremt kritisk.

Kommentarer

  • +1 for statsmaskine, da dette er meget lettere, næsten altid hurtigere og meget lettere at fejle / udvide.

Svar

Der er en duplikatest for tegnet “-“. Jeg “omskriver

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

som

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

Jeg vil også tilføje understøttelse til hexadecimal numre.

Kommentarer

  • En switch blok ville også fungere godt her.
  • Ah, at ' er sandt. En switch med gennemslag ville sandsynligvis have mindst duplikering.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *