[C] itoa / atoi 구현
본문 바로가기

C

[C] itoa / atoi 구현

728x90
반응형

지금은 printf가 있어서 현재 값이 정상적으로 입력이 되었는지 %d나 %s로 쉽게 확인할 수 있습니다.

 

하지만 과거엔 printf가 없었고 write함수로 출력했었죠

write함수는 문자열만 출력이 가능했었는데요

 

이때 정수를 write로 출력할 수 없었기에 정수를 문자열로 변환시켜 출력하곤 했습니다.

그래서 주로 itoa함수를 사용해 정수를 문자열로 변환시켜 출력을 했었습니다.

 

그리고 반대로 사용자 입력 argv로 사용자 입력을 받은 문자열을 정수로 변환시켜야 할 때도 있습니다.

이때는 보통 atoi 함수를 사용해서 문자열을 정수로 변환시켜 변수를 초기화 하곤 합니다.

 

이번 페이지에서는 itoa와 atoi함수를 보다 확실하게 이해하기 위해 구현하는 방법까지 살펴 보겠습니다.

구현하기 앞서 우리는 ascii코드에서 문자0이 어디에 위치해 있는지 알아야 할 필요가 있습니다.

 

출처 : https://stepbystep1.tistory.com/10

주목할 곳은 0, 48~57 입니다.

0은 문자열의 끝을 알리는 NUL이 들어가 있고(NULL과 NUL은 서로 다름)

48부터 57 까지가 0부터 9가 되겠습니다.

 

그럼 문자 '0'은 - 48을 하면 정수 0이 되는것과 같죠

 

굉장히 중요한 부분이니 꼭 이해하시고 함수를 구현하셨으면 좋겠습니다.

 

 

반응형

itoa (int to ascii)

약자 뜻만 봐도 쉽게 알수 있듯이 int 자료형을 ascii 즉 문자열로 변환 시켜주는 함수입니다.

c언어에서 비 표준 함수이다 보니 man에 검색을 해도 나오지 않는 함수이죠

 

저희가 구현할 itoa는 10진수 기준으로 만들겠습니다.

어차피 10진수를 제외한 나머지 진수들을 실제로 별로 사용하지 않습니다.

그렇기에 10진수 기준으로 itoa를 구현하겠습니다.

#include <unistd.h>
#include <stdlib.h>
#include <string.h>

char	*ft_itoa(int n)
{
    int tmp = n;
    int len = 1;
    
    while ((tmp /= 10)) len++;
    
    char *ret = malloc(len + 1);
    if (!ret) return NULL;
    for (int i = len - 1; i >= 0; i--)
    {
    	ret[i] = n % 10 + '0';
        n /= 10;
    }
    ret[len] = 0;
    return ret;
}

int	main(void)
{
	char	*max = ft_itoa(2147483647);
	char	*min = ft_itoa(-2147483648);
	char	*zero = ft_itoa(0);
	char	*m_zero = ft_itoa(-0);

	write(1, "int max : ", 10);
	write(1, max, strlen(max));
	write(1, "\n", 1);

	write(1, "int min : ", 10);
	write(1, min, strlen(min));
	write(1, "\n", 1);

	write(1, "int 0 : ", 8);
	write(1, zero, strlen(zero));
	write(1, "\n", 1);

	write(1, "int -0 : ", 9);
	write(1, m_zero, strlen(m_zero));
	write(1, "\n", 1);

	free(max);
	free(min);
	return (0);
}

출력 결과

경계값 모두 정상적으로 출력이 되네요

 

기존값 n을 잠깐 복사해서 길이를 측정해준뒤 할당하고 for문으로 len - 1 만큼 n % 10으로 뒤 숫자부터 채워주는걸 반복합니다.

 

문자열 마지막에 0을 넣어준뒤 반환하면 간단하게 구현할 수 있어요.

 

주의! ('\0'과 NULL은 서로 다릅니다)

 

 

atoi (ascii to int)

#include <stdlib.h>

int	atoi(const char *str)

 

잠깐! ascii를 모르시다면 윗 부분에 ascii 코드표를 보고 와주세요!

약자 뜻만 봐도 알 수 있듯이  ascii 즉 문자열을 int 자료형으로 변환 시키는 함수입니다.

구현 난이도 면에서 itoa보다 쉬운편입니다.

 

우선 atoi의 경우 모든 예외처리를 0으로 처리하게 됩니다.

예) "zero" -> 0, "영" -> 0, "ff" -> 0

이런식으로 예외처리를 하는데 10진수가 나오다 문자가 나오면 0이 아닌

이전에 나오던 10진수의 값을 반환하는것을 잊으시면 안됩니다.

예) "1234hello" -> 1234, "00312" -> 312, "213  92" -> 213

참고로 부호가 2번 이상 나오면 오류 처리 됩니다.

예) "--1234" -> 0, "+-1234" -> 0, "++1234" -> 0

 

그리고 atoi함수는 모든 오버플로우 처리를 따로 하지 않습니다.

int자료형의 최대값인 2147483647 에서 1을 더한

2147483648을 넣은 경우 -2147483648로 반환하게 된다는 점을 잊으시면 안됩니다. 

 

atoi 함수는 원본에서도 10진수 기준으로 만들어 졌기에 16진수의 256(ff)로 문자열을 넣었을 때 오류처리 해주어야 합니다.

 

 

#include <stdio.h>

int	ft_atoi(const char *str)
{
	int		result = 0;
	int		i = 0;
	int		m = 1;

	if (str == NULL)
		return (0);
    // 음수 양수 부호 처리
	if (str[i] == '-' || str[i] == '+')
	{
		if (str[i] == '-')
			m = -1;
		i++;
	}
    // 현재 인데스가 10진수 문자 일때까지
	while (str[i] && '0' <= str[i] && str[i] <= '9')
	{
		result *= 10;
		result += str[i] - 48; // 48 == '0'
		i++;
	}
	return (result * m);
}

int	main(void)
{
	printf("------------ft_atoi------------\n");
	printf("int max : %d\n", ft_atoi("2147483647"));
	printf("int min : %d\n", ft_atoi("-2147483648"));
	printf("int max + 1 : %d\n", ft_atoi("2147483648"));
	printf("int min - 1 : %d\n", ft_atoi("-2147483649"));
	printf("0 : %d\n", ft_atoi("0"));
	printf("-0 : %d\n", ft_atoi("-0"));
	printf("00235 : %d\n", ft_atoi("00235"));
	printf("1234aa : %d\n", ft_atoi("1234aa"));
	printf("--1234 : %d\n", ft_atoi("--1234"));
	printf("\n------------atoi------------\n");
	printf("int max : %d\n", atoi("2147483647"));
	printf("int min : %d\n", atoi("-2147483648"));
	printf("int max + 1 : %d\n", atoi("2147483648"));
	printf("int min - 1 : %d\n", atoi("-2147483649"));
	printf("0 : %d\n", atoi("0"));
	printf("-0 : %d\n", atoi("-0"));
	printf("00235 : %d\n", atoi("00235"));
	printf("1234aa : %d\n", atoi("1234aa"));
	printf("--1234 : %d\n", atoi("--1234"));
}

출력 결과

오버플로우, 경계값, 10진수뒤 문자열, -0, 부호 여러번 모두 정상 작동 되는 것을 보실 수 있습니다.

ft_atoi의 매개변수가 const 형태이다 보니 포인터로 접근하기 힘듭니다.

그래서 인덱스로 접근해 앞 부분부터 따와서 하나하나 처리를 해주고 맨 처음 음수 체크를 해주어서 마지막에

체크된 결과값을 곱해 리턴을 해주면 됩니다.

 

 

42서울에서 함수를 여러번 직접 구현을 해봐서 그런진 몰라도 개인적으로 함수들을 직접 구현해서 사용하지 않으면

"이때 어떤 함수를 써야하지??" 하는 상황이 많이 오더라구요

 

그래서 함수들은 어렵지 않다면 직접 구현해 보는것 또한 하나의 공부 방법이라 생각합니다.

별다른 공부 방법이 없다면 함수를 직접 구현해서 사용해 보는건 어떨까요?

728x90
반응형