Implement Atoi - Convert String to Integer
Problem and examples
You are given a string that may contain a number. Your task is to convert this string into a valid integer, just like the C/C++ function atoi() does.
However, the conversion should follow these rules:
- Ignore leading whitespaces.
- The first non-whitespace character may be '+' or '-' to indicate sign.
- Only read the digits after the optional sign.
- If any non-digit character appears after the digits, stop reading further.
- If the converted number exceeds the 32-bit signed integer range (
[-231, 231-1]), clamp it to the nearest bound.
If the string does not contain a valid number, return 0.
| Input String | Output | Description |
|---|---|---|
| "42" | 42 | Normal case with valid positive number |
| " -42" | -42 | Leading spaces and negative sign handled |
| "4193 with words" | 4193 | Number ends before non-digit characters |
| "words and 987" | 0 | Invalid as it doesn't start with a number |
| "+123" | 123 | Valid positive number with explicit sign |
| "-91283472332" | -2147483648 | Below 32-bit signed int range, clamped to INT_MIN |
| "91283472332" | 2147483647 | Above 32-bit signed int range, clamped to INT_MAX |
| "" | 0 | Empty string returns 0 |
| " " | 0 | Whitespace only returns 0 |
| "-" | 0 | Only sign with no digits returns 0 |
| "+0 123" | 0 | Only 0 is read before space, rest ignored |
How it works
Understanding the Problem
We are given a string, and our goal is to convert it into an integer — similar to the C-style atoi function. However, this isn’t as simple as it sounds. The string might have:
- Leading whitespaces
- Optional '+' or '-' signs
- Digits that form the number
- Trailing or interleaved invalid characters
- Very large or very small values that cause overflow
We must carefully extract a valid integer from the string, character by character, while following strict rules. If the string doesn't begin with a valid number after skipping whitespace, we must return 0.
Step-by-Step Solution with Example
step 1: Skip leading whitespaces
We start scanning from the beginning of the string and ignore all spaces. These don’t affect the number.
Example: For input " -42", we skip the three spaces and move to '-'.
step 2: Handle optional '+' or '-' sign
After whitespace, the first character might be a '+' or '-'. This sets the sign of the final result.
Example: In " -42", we detect '-', so the number will be negative.
step 3: Convert consecutive digits into a number
Now we read digits (0 to 9) one by one. For each digit, we multiply the current number by 10 and add the digit.
Example: From "-42", we convert '4' and '2' into the number 42. Since the sign was '-', the final result becomes -42.
step 4: Stop at the first non-digit character
If we encounter a non-digit (like a letter or symbol), we stop parsing there. We only consider the valid numeric prefix.
Example: In "4193 with words", we stop reading at the space before "with" → result is 4193.
step 5: Clamp the value to fit within 32-bit signed integer range
The valid range is from -2147483648 to 2147483647. If the number exceeds this, we must cap it to the closest boundary.
Example: For "91283472332", the value exceeds 2147483647, so we return 2147483647.
step 6: Return 0 if nothing can be converted
If there's no valid digit after trimming spaces and signs, we simply return 0.
Example: For " " or "words and 987", no conversion is possible → result is 0.
Edge Cases
- Empty string:
""→ nothing to parse → return 0. - Only spaces:
" "→ becomes empty after trim → return 0. - Starts with letters:
"abc123"→ no digits at start → return 0. - Only sign:
"+"or"-"with no digits → return 0. - Overflow:
"9999999999"→ exceeds max → return 2147483647. - Underflow:
"-9999999999"→ exceeds min → return -2147483648.
Finally
This problem teaches us how to break a real-world task into safe, logical steps. By handling each character carefully and accounting for edge cases like signs, invalid input, and overflow, we make our solution reliable and beginner-friendly. Always remember: start small, handle edge cases, and test with multiple scenarios.
- Trim leading whitespaces from the input string
- Check if the next character is '+' or '-'. Store the sign
- Iterate through each character:
- → If it's a digit, convert and add to result
- → If not a digit, break the loop
- → Before each step, check if result will overflow/underflow
- Return result multiplied by sign
Implementation and efficiency
C implementation
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
int myAtoi(const char* s) {
while (isspace(*s)) s++;
int sign = 1;
int result = 0;
if (*s == '+' || *s == '-') {
sign = (*s == '-') ? -1 : 1;
s++;
}
while (isdigit(*s)) {
int digit = *s - '0';
if (result > (INT_MAX - digit) / 10)
return (sign == 1) ? INT_MAX : INT_MIN;
result = result * 10 + digit;
s++;
}
return result * sign;
}
int main() {
const char* input = " -42";
printf("Converted Integer: %d\n", myAtoi(input));
return 0;
}C++ implementation
#include <iostream>
#include <climits>
#include <cctype>
using namespace std;
int myAtoi(string s) {
int i = 0, sign = 1, result = 0;
while (i < s.length() && isspace(s[i])) i++;
if (i < s.length() && (s[i] == '+' || s[i] == '-')) {
sign = (s[i] == '-') ? -1 : 1;
i++;
}
while (i < s.length() && isdigit(s[i])) {
int digit = s[i] - '0';
if (result > (INT_MAX - digit) / 10)
return (sign == 1) ? INT_MAX : INT_MIN;
result = result * 10 + digit;
i++;
}
return result * sign;
}
int main() {
string input = " -42";
cout << "Converted Integer: " << myAtoi(input) << endl;
return 0;
}Python implementation
def myAtoi(s):
s = s.strip()
if not s:
return 0
sign = 1
result = 0
i = 0
INT_MAX = 2**31 - 1
INT_MIN = -2**31
if s[0] in ['+', '-']:
sign = -1 if s[0] == '-' else 1
i += 1
while i < len(s) and s[i].isdigit():
digit = int(s[i])
if result > (INT_MAX - digit) // 10:
return INT_MAX if sign == 1 else INT_MIN
result = result * 10 + digit
i += 1
return sign * result
input_str = " -42"
print("Converted Integer:", myAtoi(input_str))Java implementation
public class AtoiConverter {
public static int myAtoi(String s) {
if (s == null || s.isEmpty()) return 0;
s = s.trim();
if (s.isEmpty()) return 0;
int sign = 1, i = 0, result = 0;
int INT_MAX = Integer.MAX_VALUE;
int INT_MIN = Integer.MIN_VALUE;
if (s.charAt(i) == '+' || s.charAt(i) == '-') {
sign = (s.charAt(i) == '-') ? -1 : 1;
i++;
}
while (i < s.length() && Character.isDigit(s.charAt(i))) {
int digit = s.charAt(i) - '0';
if (result > (INT_MAX - digit) / 10) {
return (sign == 1) ? INT_MAX : INT_MIN;
}
result = result * 10 + digit;
i++;
}
return result * sign;
}
public static void main(String[] args) {
String input = " -42";
System.out.println("Converted Integer: " + myAtoi(input));
}
}JavaScript implementation
function myAtoi(s) {
s = s.trim();
if (s.length === 0) return 0;
let sign = 1;
let i = 0;
let result = 0;
const INT_MAX = 2 ** 31 - 1;
const INT_MIN = -(2 ** 31);
if (s[i] === '+' || s[i] === '-') {
sign = s[i] === '-' ? -1 : 1;
i++;
}
while (i < s.length && s[i] >= '0' && s[i] <= '9') {
const digit = s[i].charCodeAt(0) - '0'.charCodeAt(0);
if (result > Math.floor((INT_MAX - digit) / 10)) {
return sign === 1 ? INT_MAX : INT_MIN;
}
result = result * 10 + digit;
i++;
}
return result * sign;
}
console.log("Converted Integer:", myAtoi(" -42"));Go implementation
package main
import (
"fmt"
"math"
"strings"
"unicode"
)
func myAtoi(s string) int {
s = strings.TrimSpace(s)
if len(s) == 0 {
return 0
}
sign := 1
i := 0
result := 0
if s[i] == '+' || s[i] == '-' {
if s[i] == '-' {
sign = -1
}
i++
}
for i < len(s) && unicode.IsDigit(rune(s[i])) {
digit := int(s[i] - '0')
if result > (math.MaxInt32-digit)/10 {
if sign == 1 {
return math.MaxInt32
}
return math.MinInt32
}
result = result*10 + digit
i++
}
return result * sign
}
func main() {
input := " -42"
fmt.Println("Converted Integer:", myAtoi(input))
}Rust implementation
fn my_atoi(s: &str) -> i32 {
let s = s.trim_start();
if s.is_empty() {
return 0;
}
let mut sign = 1;
let mut i = 0;
let s_bytes = s.as_bytes();
let mut result: i32 = 0;
if s_bytes[0] == b'+' || s_bytes[0] == b'-' {
if s_bytes[0] == b'-' {
sign = -1;
}
i += 1;
}
while i < s.len() && s_bytes[i].is_ascii_digit() {
let digit = (s_bytes[i] - b'0') as i32;
if result > (i32::MAX - digit) / 10 {
return if sign == 1 { i32::MAX } else { i32::MIN };
}
result = result * 10 + digit;
i += 1;
}
result * sign
}
fn main() {
let input = " -42";
println!("Converted Integer: {}", my_atoi(input));
}Kotlin implementation
fun myAtoi(s: String): Int {
val str = s.trim()
if (str.isEmpty()) return 0
var sign = 1
var i = 0
var result = 0
val INT_MAX = Int.MAX_VALUE
val INT_MIN = Int.MIN_VALUE
if (str[i] == '+' || str[i] == '-') {
sign = if (str[i] == '-') -1 else 1
i++
}
while (i < str.length && str[i].isDigit()) {
val digit = str[i] - '0'
if (result > (INT_MAX - digit) / 10)
return if (sign == 1) INT_MAX else INT_MIN
result = result * 10 + digit
i++
}
return result * sign
}
fun main() {
val input = " -42"
println("Converted Integer: ${myAtoi(input)}")
}TypeScript implementation
function myAtoi(s: string): number {
s = s.trim();
if (s.length === 0) return 0;
let sign = 1;
let i = 0;
let result = 0;
const INT_MAX = 2 ** 31 - 1;
const INT_MIN = -(2 ** 31);
if (s[i] === '+' || s[i] === '-') {
sign = s[i] === '-' ? -1 : 1;
i++;
}
while (i < s.length && s[i] >= '0' && s[i] <= '9') {
const digit = s.charCodeAt(i) - '0'.charCodeAt(0);
if (result > Math.floor((INT_MAX - digit) / 10)) {
return sign === 1 ? INT_MAX : INT_MIN;
}
result = result * 10 + digit;
i++;
}
return result * sign;
}
console.log("Converted Integer:", myAtoi(" -42"));Time complexity
| Case | Time | Explanation |
|---|---|---|
| best case | O(1) | When the string is empty or contains only whitespaces, the function exits early. |
| average case | O(n) | Where n is the number of characters to parse through until a non-digit or end is encountered. |
| worst case | O(n) | Involves scanning through the entire valid digit portion of the string for parsing. |
Space complexity
O(1)
Only a fixed number of variables are used for computation, regardless of input size.