Skip to content

Instantly share code, notes, and snippets.

@insidegui
Last active August 10, 2022 12:30
Show Gist options
  • Save insidegui/6a46659bbd15a516c8462d3f4cb2c036 to your computer and use it in GitHub Desktop.
Save insidegui/6a46659bbd15a516c8462d3f4cb2c036 to your computer and use it in GitHub Desktop.
Implementation of the "atoi" function in Swift (just an exercise, not for use in production)
/**
Implementation of the "atoi" function in Swift.
This implementation is an exercise and should not be used in production,
Swift has built-in types and functions that can do this sort of conversion.
*/
/// Parses the input string as a 32-bit integer.
/// Returns `nil` if the input contains non-ASCII characters, or is not a valid number.
func myAtoi(_ input: String) -> Int32? {
/// The base ASCII code, where the numbers begin.
let base = UInt8(48)
/// This function will be applied to the number before the function returns.
/// It's used to change the sign according to the input.
var signfn: ((Int32) -> Int32) = { $0 }
/// This will be updated as the input is parsed and returned from the function.
/// It is an `Int` instead of an `Int32` because the value can extrapolate the maximum value
/// that `Int32` can hold depending upon the input.
/// We'll clamp this value before returning it as an `Int32`.
var output: Int = 0
for (index, char) in input.enumerated() {
/// We only work with ASCII characters, an input
/// that contains non-ASCII characters is invalid.
guard let ascii = char.asciiValue else { return nil }
/// If the character is not a number.
guard ascii >= base else {
/// The only position where a non-number character
/// is acceptable is in the first position (for the sign).
guard index == 0 else { return nil }
/// The only acceptable non-number character in the first
/// position is ASCII code 45 (the minus sign).
guard ascii == 45 else { return nil }
/// Found the minus sign in front of the number string,
/// set the sign function to multiply the number by -1.
signfn = { $0 * -1 }
continue
}
/// Compute the current digit by subtracting the base
/// ASCII code from the current digit's ASCII code.
let digit = Int(ascii - base)
/// Since we're working with the decimal system, each time
/// we find a new digit to the right, we multiply the
/// current number by 10, then add the new digit to the result.
output = (output * 10) + digit
}
/// The nested max/min ensures the final value
/// lies between Int32.min and Int32.max.
let clamped = Int32(max(min(output, Int(Int32.max)), Int(Int32.min)))
/// Run signfn, which will multiply the number by -1
/// if a minus sign was found in the first position.
return signfn(clamped)
}
myAtoi("0") == 0
myAtoi("123") == 123
myAtoi("2048") == 2048
myAtoi("-999") == -999
myAtoi("99999999999999") == Int32.max
myAtoi("-🤡123") == nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment