ft_printf_3일차

아따맘마·2020년 11월 12일
0

ft_printf

목록 보기
4/9

다시 보는 ft_printf 메커니즘

2일차 때 ft_printf를 구현하기 위해서 구조체 변수를 사용해야 한다는 것을 알았다.(형식지정자를 받기 위해)
그럼 오늘은 예제를 하나 들어보면서 ft_printf가 어떻게 구현되야 할지 다시 자세히 생각해보자. 2일차 때도 했지만 복습하는 차원에서 한번 더!

ft_printf("size is %[flag][width][.precision]d, str is %s", int, str);

그러면 메커니즘은 다음과 같다

아 그리고 printf에 관한 옵션들을 자세히 설명한 사이트 두 곳이 있다.
https://modoocode.com/35
https://dojang.io/mod/page/view.php?id=736
만약 헷갈린다면 두 사이트 보면서 하면 좋을 듯 싶다. 두 사이트 모두 코딩하면서 보기에 훌륭한 사이트들이니 자주 들어가서 공부하자

ft_printf.h

#ifndef FT_PRINTF_H
#define FT_PRINTF_H
#define ERROR -1

해당 함수들...

#endif

여태까지 코딩을 짤 때는 가독성 없이 짯었다. 예를 들어 error일 때 -1을 반환한다면 그럴때마다 그냥 return (-1); 와 같이 코딩을 했지만! 이제부터는 가독성도 따지면서 짜보려고 한다.
그래서 #define을 열심히 활용해볼 생각이다.
ft_printf.h에서 구조체 변수도 선언해줘야 한다.

typedef struct	s_list
{
	int size;
    ...
}				t_list

와 같이 형식지정자에 쓰일 변수들을 넣어주자.

ft_printf.c

ft_printf()

이 함수에서는 구조체 변수를 선언하고 가변인자를 만들어야 한다. 가변인자를 만들면 format인자가 유효한지 체크를 해주는 함수로 넘긴다. 만약 format가 존재하지 않거나 문자열이 아니거나 하는 오류를 범하면 -1을 반환한다.(전에도 봤다시피 ft_printf는 오류가 나면 negative 숫자를 반환)

ft_format()

이 함수에서 받는 매개변수는 가변인자 ap, 형식지정자를 받는 구조체 변수, format 변수일 것이다. 구조체 변수는 포인터로 받는다.

그러면 일단 format이 유효한지 체크해보고 유효하면 문자열을 읽어나간다.
(여기서 유효성은 format이 존재하는지만 확인, 문자열인지 아닌지는 생각해보니까 ft_printf자체의 매개변수 format이 문자열형이기 때문에 신경안써줘도 될듯)

%가 아닐 때


%가 아니면 printf 반환값이 문자열의 길이이니까 t_list->size++해줘야 하고 해당 문자를 읽어야 한다. 구조체 변수를 설정할 때 내부에서 초기화 할 수 없으니 ft_format()이 실행할 때 t_list->size = 0으로 미리 초기화

%일 때


만약 문자를 확인했는데 %이다?? 그러면 이제부터 복잡해진다.
문자열 주소값을 하나 더 넘겨서 먼저 형식지정자를 확인해야 한다. 근데 여기서 잠깐!!
형식 지정자를 확인하기 전에 형식지정자 구조체 변수를 초기화 하고 가야한다. %가 나올때마다 계속 초기화를 해줘야하기 때문이다.
그리고 형식지정자를 확인하는 함수로 넘겨서 유효하면 이번엔 서식지정자를 확인한다. 서식지정자도 유효하면 해당하는 값 출력한다.

ft_format_tag()

매개변수로는 가변인자 ap, 구조체 변수, format이다. 여기서는 구조체 변수는 이중 포인터로 받아서 ft_format()함수에서도 변하게 해줘야 한다.

형식지정자에 대해서 생각하다가 한가지 의문점이 들었다. 형식, 서식지정자를 받기 위해서는 %를 쓰는데 %를 출력하고 싶으면 %%로 한다. 그럼

printf("%");

라고 출력을 하려고 하면 오류가 발생할까??해서 봤는데...

warning이 뜬다. 이것을 놓칠뻔 했다. 그럼 ft_format_tag를 돌리면서 처음에 NULL값이면 오류를 반환해야하고 flag, width, precision을 확인하면서 서식지정자가 나타나기 전까지 NULL값이 나타나면 오류를 반환해야할 것이다.
형식지정자의 순서는 전에도 말했듯이 다음과 같다.

그리고 flag width, .prec...에 해당하는 옵션들을 다시 확인하면

flag

풀래그의미
-왼쪽 정렬
+양수 : +부호, 음수 : -부호 출력
공백양수 : 아무 부호 출력 x, 음수 : -부호 출력
#출력하고자 하는 진법에 맞게 부호. 서식지정자 o, x, X와 사용(8진 : 0, 16진 : x, 16진 : X)
0출력하고자 하는 폭에서 남는 공간에 0을 출력

width

의미
숫자숫자만큼 폭을 지정하여 출력. 실수는 .(점) , e+까지 폭에 포함
**기호가 나오면 문자열 내에서 폭을 지정하지 않는다. 대신에 문자열 다음 인자에 폭을 지정할 정수를 받는다. 이 인자 다음에 출력할 데이터를 순차대로 넣는다.

precision

정확도의미
.숫자지정한 숫자만큼 소수점 아래 자리 출력

ft_specifier()

여기서도 받아야 하는 매개변수는 format, 구조체, ap일 것이다.

일단 형식지정자가 확인이 끝나고 오류가 없으면 서식지정자를 확인해야 할 것이다.
이 함수에서 가장 처음으로 해야할 것은 NULL값이 아닌지 확인해주고, 우리가 프린트할 서식지정자중에 있는지 확인해야 할 것이다.
서브젝트를 확인하면 cspdiuxX%에 해당하는 서식지정자를 보면 된다.
보너스는 일단 나중으로... 본내용만 하는것만으로도 벅찬 ㅠㅠ. 실수가 보너스에 있던데 여태까지 들어봤을 때 너무 어렵더라요

서식지정자의미
c문자 출력
s문자열 출력
p포인터 주소 출력
d부호 있는 십진법 정수 출력
i부호 있는 십진법 정수 출력
u부호 없는 십진법 정수 출력
x부호 없는 16진법 정수 출력(소문자)
X부호 없는 16진법 정수 출력(대문자)
%% 출력

해당 서식지정자가 있으면 그에 맞는 서식지정자를 출력하는 함수로 보낸다.
없으면 에러 반환!!

결론


ft_printf를 짜는데 계획없이 생각나는대로 짜보니까 중간중간 계속 막혔다. 더군다나 요새는 ADsP 자격증을 준비하게 되면서 다른 공부에 더 집중을 하다보니 ft_printf 과제를 하는데 집중을 많이 하지 못하게 되서 고민이 많았다.
그래서 계획적으로 짜는것에 대한 중요성을 깨달아 대충대충 하지 않고 함수 하나하나 어떻게 쓸것인지, 어떤 흐름대로 코딩을 해야하는지 일일이 생각해보면서 하려고 한다.
오늘은 ft_printf 본 함수에서 어떤 함수들을 쓸 것인지 자세하게 알아보았다.
이렇게 정리하고 보니 흐름을 알게 되어 쉽게 짤 수 있을듯 하다.

아 뺴먹은 함수가 있는데 구조체 변수를 초기화해주는 함수를 추가해줘야 한다. 다행히 이 함수까지 포함하여 ft_printf.c에는 5개의 함수를 쓸 수 있어 제한을 넘기지 않았다.

profile
늦게 출발했지만 꾸준히 달려서 도착지점에 무사히 도달하자

0개의 댓글