[libft] ft_atoi
atoi?
#include <string.h>
int atoi(const char *nptr);
Linux manpage description
: The atoi() function converts the initial portion of the string pointed to by nptr to int. The behavior is the same as strtol(nptr, NULL, 10); except that atoi() does not detect errors.
해석 및 부연설명
: 포인터 nptr이 가리키는 문자열을 int
로 변환하여 반환한다.
ex)
char str[] = "-1535abcd";
printf("%d\n", atoi(str));
코드 실행 결과
-1535
’-‘부호가 적용되고, int
로 표현할 수 있는 1535까지만 변환되어 반환되었다.
의문점 및 생각해볼점
atoi
는 어떻게 작동하는가
atoi
함수에는 여러가지 고려할 점이 있다.
- 처리하는 문자열의 범위 문자열을 앞에서부터 읽으면서 부호(+-)와 whitespace(space와 ascii기준 9~13)을 건너 띈 후 나오는 숫자부터 처리를 시작하며 숫자가 아닌 문자가 나오는 순간 끊는다.
- 부호 및 whitespace 처리 +나 -가 한번 나올 때 이를 반영하고, 또다시 부호가 등장한다면 이는 그냥 숫자가 아닌 여타 문자로 취급하여 끊어버린다. 이 때 순서는 무조건 whitespace > 부호 > 숫자여야 하며 부호 뒤에 whitespace가 온다면 이 또한 올바르지 않은 케이스가 되어 끊긴다.
- 정상적인 숫자가 들어오지 않았을 경우 변환될 숫자가 없이 문자열 읽기가 끊긴다면 0이 반환된다.
오버플로우/언더플로우시
int
형 범위 2147483647을 넘어가면 오버플로우가 발생되어 엉뚱한 값이 나온다.
반대로 -2147483648보다 작으면 언더플로우가 발생해 엉뚱한 값이 나온다.
결론적으로 atoi 함수에서는 오버/언더플로우시에 따로 처리하는 기능이 없다.
단, long long
형 범위를 넘어갈 시에는 조금 처리가 달라지는데 이는 atoi
함수 내부적으로 strtol
함수를 거친 값을 가지고 처리하기 때문이라고 한다.
즉, strtol
함수에서는 long long
형 범위 이외의 값이 들어올 경우 오버플로우가 되면 최댓값인 9,223,372,036,854,775,807을, 언더플로우가 되면 최솟값인 -9,223,372,036,854,775,808를 고정적으로 반환하며 이 값들을 atoi
에서 처리할 경우 또 오버플로우와 언더플로우가 발생해 각각 -1과 0이 반환된다.
ft_atoi 구현
#include <limits.h>
int ft_atoi(const char *str)
{
unsigned long long result;
int flag;
result = 0;
flag = 1;
while ((*str >= 9 && *str <= 13) || *str == ' ')
str++;
if (*str == '-' || *str == '+')
{
if (*str == '-')
flag = -1;
str++;
}
while (*str)
{
if (*str >= '0' && *str <= '9')
result = result * 10 + *str - '0';
else
break ;
str++;
}
if (result > LONG_MAX)
return (-1 + (flag < 0));
return (flag * (int)result);
}
원본 atoi
함수와 같은 결과값이 나오도록, 읽어들인 값이 long long
형의 범위를 넘어갔을 때는 limits.h
헤더에서 long long
형의 최대값과 같은 LONG_MAX
가 고정적으로 적용되도록 처리하였다.