
📌 매뉴얼 (Linux)
NAME
atoi - convert a string to an integer
: 문자열을 정수로 변환하는 함수
SYNOPSIS
#include <stdlib.h>
int atoi(const char *nptr);
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.
: atoi() 함수는 nptr가 가리키는 문자열의 처음 부분을 정수로 변환합니다.
동작 방식은 다음 코드와 동일합니다.
strtol(nptr, NULL, 10);
즉, strtol() 함수를 base 10(십진법)으로 사용한 것과 같습니다.
하지만 atoi()는 오류를 감지하지 않습니다.
(strtol()은 변환 과정에서 오류를 감지할 수 있지만, atoi()는 그렇지 않음.)
RETURN VALUE
The converted value or 0 on error.
: 변환된 정수 값을 반환합니다.
변환할 수 없는 경우 0을 반환합니다.
📌 작성 코드
int do_atoi(const char *nptr)
{
long long int sign;
long long int n;
int i;
sign = 1;
n = 0;
i = 0;
while (nptr[i] == 32 || (nptr[i] >= 9 && nptr[i] <= 13))
i ++;
if (nptr[i] == '+' || nptr[i] == '-')
{
if (nptr[i] == '-')
sign = -1;
i ++;
}
while (nptr[i] >= '0' && nptr[i] <= '9')
{
n = 10 * n + (nptr[i] - 48);
i ++;
}
return (sign * n);
}
📌 코드 리뷰
shell에서 어떤 프로그램을 실행할 때, 어떤 인자를 작성해서 받게 되면
char **argv를 통해 문자열로 받게 되어 있다보니, 문자열로 온 숫자값을 정수형으로 변환할 방법이 필요했다.
따라서 atoi 함수가 여기서 찰떡같이 쓰이게 되었다.
atoi 함수는 itoa와 반대로 alphabet to int 의 약자로, 문자열로 받은 인자를 정수로 변환하여 반환해주는 함수이다.
"12345" 라는 문자열을 정수값 12345로 바꿔 반환한다.
위의 코드를 하나하나 순차적으로 뜯어보자.
우선 while문을 통해 공백이나 tab과 같은 whitespace를 건너뛰는 작업을 해주었다.
그 후, +나 - 가 있으면 인덱스를 하나 건너 뛰기위한 if문을 작성했다.
또한 '-' 일때는 추후에 음수로 변환해줘야하므로, sign이라는 변수를 통해 부호값을 -1로 지정했다.
그 이후, while문을 통해 숫자값이 나올 동안 자리수를 높여가면서 값을 저장해주는 과정을 거쳤다.
long long int로 값들을 선언했고, 원래 atoi와 동일하게 따로 overflow에 대한 처리를 하지 않았다.
(반환이 int이므로, 값이 넘쳤을 때는 알아서 overflow 되도록 둠.)
그리 어렵지는 않은 코드이나, 나중에 다른 코드에 적용시켜보니,
overflow error handling이 없는게 너무 불편했다. (실제 atoi 함수도 없다. -> 대안: strtol 함수는 오류 감지 해준다.)
그러다보니 upgrade ver. 를 하나 만들어뒀다.
* atoi_upgrade
int do_atoi_upgrade(char *nptr, int *v)
{
long long int sign;
long long int n;
int i;
i = 0;
n = 0;
sign = 1;
if (nptr[i] == '-')
{
sign = -1;
i ++;
}
while (nptr[i] >= '0' && nptr[i] <= '9')
{
n = 10 * n + (nptr[i] - 48);
i ++;
if ((sign * n) > 2147483647 || (sign * n) < -2147483648)
{
(*v) = 1;
return (0);
}
}
return ((int)sign * (int)n);
}
우선, whitespace 부분은 내부에서 고려하지않고,
외부 코드에서 숫자값만 parsing해서 들어온다는 가정하에 작성했다.
따라서 시작 부분에 '-'가 있으면 sign값만 변경하고,
+로 시작하는 숫자는 parsing에서 +가 사라져서 들어오거나, 미리 걸러지게 뒀다.
다른 부분은 같지만, while문내에서 int값 overflow에 대한 error handling 파트를 하나 넣었다.
매번 자리수가 올라갈 때마다, 반환할 값이 int overflow가 되었는지 판별하게 만들어,
error flag인 v의 값을 1로 바꾸도록 설정해두었다.
기존에 만들때 while문 밖에 이를 적어뒀었는데, 이는 치명적인 문제가 있었다.
-> overflow 된 결과가 int 범위 안쪽이 되어버리는 상황에서, 이를 오류로 보지 못한다는 것.
(longlong MAX 보다 더 크면서 longlong MAX + int MAX 보다 작은 값이 들어가면 overflow인지 모름 ..)
따라서 while문 안에 넣어 int overflow 된 이후에 바로 return 해버리도록 탈출구를 마련했다.
이로써, int값이 넘어가는 값은 flag를 통해 걸러주는 atoi_upgrade 를 만들게 되었다..
+) 확실히 기존에 있는 함수를 넘어서서 가공하려니 쉽지않다고 생각이 들었고,
간단한 함수도 생각할 부분들이 정말 많다고 느꼈다. 아무래도 위의 코드도 부족한 부분이나 허점이 있을 수 있다..
최대한 다양한 관점에서 코딩을 해봐야할 듯함.
'프로그래밍 > C' 카테고리의 다른 글
[function] pthread_detach 함수 알아보기 (2) | 2024.09.18 |
---|---|
[function] pthread_join 함수 알아보기 (8) | 2024.09.07 |
[function] pthread_create 함수 알아보기 (5) | 2024.09.07 |
[utility] get_next_line 구현하기 (3) | 2024.08.31 |
[graphic] miniLibX Manual (0) | 2024.08.06 |