문자열 출력 함수에서 어떻게 매개변수로 넣은 정수형을 곧바로 문자열로 포매팅해서 출력할까?
아스키테이블에는 0
~9
까지의 숫자표현만 존재한다. 만약 2147483647
라는 정수를 출력하기 위해서는 각자리당 문자 하나씩해서 출력해야한다.
fprintf("%d", 2147483647);
위의 코드를 실행하면 함수안에서 매개변수로 받은 정수를 마법같이 문자열로 바꿔서 표준출력에 보여준다.
> 2147483647%
문자열 출력함수와 가변 길이 매개변수에 대해서는 다른 포스팅에서 알아보도록 하고,
이번에는 정수형 데이터를 문자열로 출력하는 방법중 재귀함수의 호출스택을 사용하는 방법을 알아보겠다.
static void print_int_reculsive(int i)
{
if (i == 0) { /* 3. */
return;
}
print_int_reculsive(i / 10); /* 4. */
putchar('0' + i % 10); /* 5. */
}
static void print_int(int i)
{
if (i == 0) {
putchar('0'); /* 1. */
}
print_int_reculsive(i); /* 2. */
}
int main(void)
{
print_int(__INT_MAX__);
}
우선 매개변수로 들어온 정수가 0
의 경우를 따로 처리해주지 않으면 2번을 거쳐 3번으로 빠지게 될텐데 이렇게되면 문자열을 출력할수가 없기 때문에 우선 매개변수가 0
인경우는 그냥 0
을 출력해주도록 하자
이제 재귀함수를 호출해서 i
를 아스키테이블상의 1
~9
의 문자로 바꿔서 char
하나를 출력하도록 한다
재귀함수에 의해서 i
는 계속 10
으로 나눈 몫으로 들어올것이다. 만약 i
가 0
이되면, 즉, 10
으로 나눈 몫이 0
으 되면 모든 정수에서 모든 자리의 평가가 끝났음을 의미하기 때문에 재귀호출을 끊어준다
실제로 현재 자리에 있는 문자를 출력하기 전에 정수에 있는 앞의 모든 숫자들을 먼저 출력해야한다.
예를들어 2147483647
라는 정수가 있다면 7
을 출력하기전 4
를출력해야하고 4
를출력하기전 6
을 출력해야하고 ... 1
을출력하기전 2
를 출력해야한다. 2
는 정수중에서 가장 앞자리에 속하기 때문에 2
를 출력하는 호출스택에서 print_int_reculsive(0)
의 함수의 매개변수로 0
을 넘겨주게 되어서 재귀호출이 종료된다.
이제 재귀함수의 호출스택이 2
를 출력하는 단계까지 왔다면 2
부터 1
, 4
, 7
, 4
, 8
, 3
순으로 7
까지 출력을하고 호출스택이 전부 pop되면 함수가 리턴된다.
여기서 putchar('0' + i % 10);
아스키 문자 0
에 아스키테이블에서의 오프셋만큼 값을 더해주면 0
~9
까지 범위안에서 자유롭게 출력이 가능하다.
각 호출스택마다 라인브레이크를 넣어주면 아래와같이 출력된다
스택을 사용한다면 재귀함수를 상용하지 않아도 구현할 수 있을 것 같다.