atoi 구현해 보기
숫자처럼 보이는 문자열 다루기
atoi는 C 언어에서 문자열을 받아 int로 변환하는 함수다.
문자 하나를 숫자로 바꾸는 일은 단순하다.
char ch = '0';
int n = ch - '0';
숫자 0은 어떤 진법으로 표현하든 값 자체가 0이다.
하지만 문자 '0'은 숫자 0이 아니라 문자 코드로 저장된다.
ASCII 기준으로 문자 '0'은 48이고, 문자 '1'은 49처럼 차례대로 증가해 문자 '9'는 57이다.
그래서 문자 '0'을 실제 숫자 0으로 바꾸려면 문자 코드의 차이를 이용해 '0'을 빼면 된다.
문제는 여러 문자로 이루어진 숫자 문자열이다.
char *ch = "12";
우리는 1과 2가 이어져 있으면 12라고 생각한다.
앞의 1을 십의 자리로 보고, 뒤의 2를 일의 자리로 보기 때문이다.
하지만 C에서 ch[0]은 문자 '1'이고, ch[1]은 문자 '2'일 뿐이다.
문자 '1'과 문자 '2' 자체에는 각각 십의 자리와 일의 자리라는 정보가 들어 있지 않다.
그래서 이 문제는 문자를 하나씩 읽으면서 어떻게 자릿값을 부여할지가 구현의 핵심이다.
소스 코드
#include <assert.h>
int my_atoi(const char* str)
{
const char* current = str;
int sign = 1;
int result = 0;
while (*current == ' ')
{
current++;
}
if (*current == '+' || *current == '-')
{
sign = (*current == '-') ? -1 : 1;
current++;
}
while (*current >= '0' && *current <= '9')
{
int digit = *current - '0';
result = result * 10 + digit;
current++;
}
return sign * result;
}
int main(void)
{
assert(my_atoi("123") == 123);
assert(my_atoi("+123") == 123);
assert(my_atoi("-123") == -123);
assert(my_atoi(" -123") == -123);
assert(my_atoi(" 123 ") == 123);
assert(my_atoi("123abc") == 123);
}
구현 설명
숫자를 읽기 전에 먼저 처리해야 할 것은 앞쪽 공백과 부호다.
공백은 숫자 값에 영향을 주지 않으므로 숫자나 부호가 나올 때까지 포인터를 다음 위치로 이동한다.
그다음 + 또는 -가 나오면 부호를 따로 기억해 두고, 실제 숫자는 그다음 문자부터 읽기 시작한다.
자릿값을 부여하는 핵심은 result = result * 10 + digit; 한 줄이다.
새 숫자를 붙이기 전에 기존 값을 10배하면 지금까지 만든 숫자의 자리가 한 칸씩 왼쪽으로 밀린다.
그 상태에서 digit을 더하면 새 숫자가 일의 자리에 들어간다.
예를 들어 "-123"을 읽을 때 부호는 -1로 저장되고, result는 1, 12, 123 순서로 바뀐다.
반복이 끝난 뒤 sign과 result를 곱하면 문자열은 -123이라는 정수로 변환된다.