Skip to content

Commit 046f5a4

Browse files
authored
refactor: atoi (#5324)
1 parent 134b42c commit 046f5a4

File tree

2 files changed

+64
-75
lines changed

2 files changed

+64
-75
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,65 @@
1-
// Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer
2-
// (similar to C/C++'s atoi function). Here is my implementation
3-
41
package com.thealgorithms.strings;
52

3+
/**
4+
* A utility class that provides a method to convert a string to a 32-bit signed integer (similar to C/C++'s atoi function).
5+
*/
66
public final class MyAtoi {
77
private MyAtoi() {
88
}
9-
public static int myAtoi(String s) {
10-
s = s.trim();
11-
char[] char1 = s.toCharArray();
12-
String number = "";
13-
boolean negative = false;
14-
boolean zero = false;
15-
boolean isDigit = false;
169

17-
for (char ch : char1) {
18-
if (Character.isDigit(ch)) {
19-
if (number.length() > 1 && !isDigit) {
20-
number = "0";
21-
break;
22-
}
23-
isDigit = true;
24-
if (zero) {
25-
number = "0";
26-
break;
27-
}
28-
if (ch >= '0' && ch <= '9') {
29-
number += ch;
30-
}
31-
} else if (ch == '-' && !isDigit) {
32-
number += "0";
33-
negative = true;
34-
} else if (ch == '+' && !isDigit) {
35-
number += "0";
36-
} else if (ch == '.' && isDigit) {
37-
break;
38-
} else if (ch == '.') {
39-
zero = true;
40-
} else {
41-
if (!isDigit) {
42-
number = "0";
43-
}
44-
break;
45-
}
10+
/**
11+
* Converts the given string to a 32-bit signed integer.
12+
* The conversion discards any leading whitespace characters until the first non-whitespace character is found.
13+
* Then, it takes an optional initial plus or minus sign followed by as many numerical digits as possible and interprets them as a numerical value.
14+
* The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
15+
*
16+
* If the number is out of the range of a 32-bit signed integer:
17+
* - Returns {@code Integer.MAX_VALUE} if the value exceeds {@code Integer.MAX_VALUE}.
18+
* - Returns {@code Integer.MIN_VALUE} if the value is less than {@code Integer.MIN_VALUE}.
19+
*
20+
* If no valid conversion could be performed, a zero is returned.
21+
*
22+
* @param s the string to convert
23+
* @return the converted integer, or 0 if the string cannot be converted to a valid integer
24+
*/
25+
public static int myAtoi(String s) {
26+
if (s == null || s.isEmpty()) {
27+
return 0;
4628
}
4729

48-
if (!isDigit) {
30+
s = s.trim();
31+
int length = s.length();
32+
if (length == 0) {
4933
return 0;
5034
}
5135

52-
number = number.replaceFirst("^0+(?!$)", "");
36+
int index = 0;
37+
boolean negative = false;
38+
39+
// Check for the sign
40+
if (s.charAt(index) == '-' || s.charAt(index) == '+') {
41+
negative = s.charAt(index) == '-';
42+
index++;
43+
}
5344

54-
if (number.length() > 10 && negative) {
55-
return -2147483648;
56-
} else if (number.length() > 10) {
57-
return 2147483647;
58-
} else if (number.length() == 10 && negative) {
59-
double db1 = Double.parseDouble(number);
60-
if (db1 >= 2147483648d) {
61-
return -2147483648;
45+
int number = 0;
46+
while (index < length) {
47+
char ch = s.charAt(index);
48+
if (!Character.isDigit(ch)) {
49+
break;
6250
}
63-
} else if (number.length() == 10) {
64-
double db1 = Double.parseDouble(number);
65-
if (db1 > (2147483647)) {
66-
return 2147483647;
51+
52+
int digit = ch - '0';
53+
54+
// Check for overflow
55+
if (number > (Integer.MAX_VALUE - digit) / 10) {
56+
return negative ? Integer.MIN_VALUE : Integer.MAX_VALUE;
6757
}
68-
}
6958

70-
if (negative) {
71-
return Integer.parseInt(number) * -1;
59+
number = number * 10 + digit;
60+
index++;
7261
}
7362

74-
return Integer.parseInt(number);
63+
return negative ? -number : number;
7564
}
7665
}

src/test/java/com/thealgorithms/strings/MyAtoiTest.java

+18-18
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,41 @@
33
import static org.junit.jupiter.api.Assertions.assertEquals;
44

55
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.CsvSource;
68

79
public class MyAtoiTest {
810

9-
@Test
10-
void testOne() {
11-
assertEquals(42, MyAtoi.myAtoi("42"));
12-
}
13-
14-
@Test
15-
void testTwo() {
16-
assertEquals(-42, MyAtoi.myAtoi(" -42"));
11+
@ParameterizedTest
12+
@CsvSource({"'42', 42", "' -42', -42", "'4193 with words', 4193", "'words and 987', 0", "'-91283472332', -2147483648", "'21474836460', 2147483647", "' +123', 123", "'', 0", "' ', 0", "'-2147483648', -2147483648", "'+2147483647', 2147483647", "' -0012a42', -12",
13+
"'9223372036854775808', 2147483647", "'-9223372036854775809', -2147483648", "'3.14159', 3", "' -0012', -12", "' 0000000000012345678', 12345678", "' -0000000000012345678', -12345678", "' +0000000000012345678', 12345678", "'0', 0", "'+0', 0", "'-0', 0"})
14+
void
15+
testMyAtoi(String input, int expected) {
16+
assertEquals(expected, MyAtoi.myAtoi(input));
1717
}
1818

1919
@Test
20-
void testThree() {
21-
assertEquals(4193, MyAtoi.myAtoi("4193 with words"));
20+
void testNullInput() {
21+
assertEquals(0, MyAtoi.myAtoi(null));
2222
}
2323

2424
@Test
25-
void testFour() {
26-
assertEquals(0, MyAtoi.myAtoi("0"));
25+
void testSinglePlus() {
26+
assertEquals(0, MyAtoi.myAtoi("+"));
2727
}
2828

2929
@Test
30-
void testFive() {
31-
assertEquals(5678, MyAtoi.myAtoi("5678"));
30+
void testSingleMinus() {
31+
assertEquals(0, MyAtoi.myAtoi("-"));
3232
}
3333

3434
@Test
35-
void testSix() {
36-
assertEquals(42, MyAtoi.myAtoi("+42"));
35+
void testIntegerMinBoundary() {
36+
assertEquals(Integer.MIN_VALUE, MyAtoi.myAtoi("-2147483648"));
3737
}
3838

3939
@Test
40-
void testSeven() {
41-
assertEquals(0, MyAtoi.myAtoi(" +0 "));
40+
void testIntegerMaxBoundary() {
41+
assertEquals(Integer.MAX_VALUE, MyAtoi.myAtoi("2147483647"));
4242
}
4343
}

0 commit comments

Comments
 (0)