나만의 printf함수 만들기(ft_printf)

김성준·2021년 6월 4일
0

구현한 부분

flag : '-', '0'
width
precision
specifier: c, s, d, i, u, x, X, p, %

개발과정

첫 시작.

printf함수는 C언어를 처음 배울 때부터 사용해왔던 함수인데, 그 함수에 대해 아는 것이 별로 없다는 것을 알게되었다.
printf의 man페이지를 뒤지고 직접 main문을 만들어 여러가지 테스트를 해봤다.
어떤 입력을 주었을 때, 어떤 출력이 나오는지 어느정도 파악을 한 후에 코드를 짜기 시작했다.

처음 짠 구조.

1) 입력으로 들어온 문자열을 하나씩 읽는다.
2) '%'를 만나면 뒤의 문자들을 한칸 씩 읽으며 그 정보를 구조체에 저장한다.
3) 구조체에 저장된 specifier에 따라 각 자료형으로 분기한다.
4) get_size함수로 총 할당할 문자열의 크기를 구한다.
5) apply_width함수와 apply_precision함수로 공백과 0를 채운다.
6) fill_arg함수로 다중인자로 받아온 인자를 뽑아내 문자열에 채운다.

문제점.

get_size, apply_width, apply_precision, fill_arg 각 네개의 함수를 printf_utils.c라는 하나의 파일에 선언하고 각 specifier마다 돌려쓰려고 했다.
하지만 코드를 만들다 보니 specifier마다 size를 구할 때, precision이나 arg가 적용될 때 일관적인 규칙이 적용되는 것이 아니었다.
각각의 규칙을 하나의 함수에 넣다보니 if문 분기가 너무 많아져서 코드의 가독성이 떨어진다고 느꼈다.
또한 하나의 파일에 여러 specifier의 의존성이 모두 묶여있다보니 디버깅을 할 때, 하나를 고치면 다른 하나가 터지는 문제도 발생했다.
이러한 문제로 구조를 바꿔야겠다는 생각이 들었다.

다시 짠 구조.

기본 구조는 처음의 구조와 동일하다.
바뀐 것은 각 specifier마다 static함수로 get_size와 apply_precision, apply_arg가 추가된 점이다.
하나의 함수에 묶여있던 의존성을 specifier마다 나눠줘서 하나의 함수를 수정하면 연달아 터지는 것을 방지했다.
또한 각 specifier마다 따로 문제가 되었던 함수들이 있기 때문에 if문 떡칠을 줄일 수 있었다.

나만의 printf함수를 만들며 공부한 것들.

원본 printf함수의 문법

  • %[flags][width][.precision][length modifier]specifier

그림1. specifier

그림2. flag & width

그림3. precision

그림4.각 specifier마다 flag와 precision이 적용 가능한지

undefined behavior

각 specifier에서 허용하지 않는 flag를 주거나 precision을 허용하지 않는데 precision을 넣으면 컴파일 시 undefined behavior라고 경고를 발생시킨다.
하지만 컴파일 결과를 출력 해보면 출력은 나오는 것을 확인할 수 있다.

1: printf("06s\n", "abcd");
2: printf("06c\n", 'a');

out1: 00abcd
out2: 00000a

구현할 때, 이런 undefined behavior도 원본 printf함수와 똑같이 작동하게 만들었다.

참고자료

https://modoocode.com/35
http://man.openbsd.org/printf.3

profile
수신제가치국평천하

0개의 댓글