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.

  1. Trim leading whitespaces from the input string
  2. Check if the next character is '+' or '-'. Store the sign
  3. Iterate through each character:
  4. → If it's a digit, convert and add to result
  5. → If not a digit, break the loop
  6. → Before each step, check if result will overflow/underflow
  7. 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

CaseTimeExplanation
best caseO(1)When the string is empty or contains only whitespaces, the function exits early.
average caseO(n)Where n is the number of characters to parse through until a non-digit or end is encountered.
worst caseO(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.