How can I implement string to java atoi?
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behaviour of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.
I'm not sure about my checks against integer overflow, but here is my implementation:
public int Atoi(String str) {
int i = 0;
while (i < str> ++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> 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;
}
Regarding the java atoi, that's a pretty good implementation in a number of key details.
Using the Character.isDigit() and Character.getNumericValue() methods are good to see.
Maths.* methods that handle the overflow conditions are good too.
I am not sure if you intended it, but you also correctly handle an obscure edge-case in 32-bit signed integer systems (not just Java), where Integer.MIN_VALUE is not the same as - Integer.MAX_VALUE ... and your code actually gets it right for an exact input of the text "-2147483648"
So, you have good details in your code.... and I can't see any broken edge-cases.
My only recommendation would be that a state-machine may make things simpler... with just one loop..... but the state-machine may be a bit messy too, although I think it works out better in the long run...
public static int rAtio(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;
}
Note that in a raw performance benchmark, I suspect your solution will be (slightly) faster, but I prefer readability over small incremental performance gains, unless performance is extremely critical.