<개요 및 목표>
구현 하고자 하는 함수
-> int ft_printf(const char *, ...)
외부 허용 함수
-> malloc, free, write, va_start, va_arg, va_copy, va_end
구현 목표
-> <stdio.h> 헤더파일에 삽입되어 있는 printf함수처럼 동작하는 ft_printf함수 만들기
<구현해야 할 항목들>
서식지정자
-> d(int형), i(int형), u(unsigned int)
-> x(16진법 소문자), X(16진법 대문자), p(주소)
-> c(문자), s(문자열), %
flag
-> - : 왼쪽 정렬
-> + : + 출력
-> 0 : 0으로 채우기
-> * : * 자리에 가변인자 적용
makefile
-> ft_printf를 구성하고 있는 모든 *.c 소스파일을 libftprintf.a라는 아카이브(라이브러리)를 만드는 makefile구현
<구현하기 위해 생각해야 할 점>
ex) printf("12345%d", 4);
위의 함수는 %를 만나기 이전까지는 그냥 출력한다. 12345
그 이후 %를 만나게 되면 서식지정자를 만나기 전까지 그 사이에 있는 항목들을 처리해주고 그 항목에 따라 서식지정자에 첫번째 가변인자를 적용시켜 출력한다. 4
따라서 종합하면 123454가 출력하도록 유도해야함
ex) printf("12345%d", 4);
출력 값 : 123454
return 값 : 6
<case 1-2>
0 plag with . (s, c, %, d, i, u, x, X, p)
-> printf("[%0.s]","123"); // []
-> printf("[%0.c]", '1'); // [1]
-> printf("[%0.%]", 123); // [%]
-> printf("[%0.d]", 123); // [123]
-> printf("[%0.i]", 123); // [123]
-> printf("[%0.u]", 123); // [123]
-> printf("[%0.x]", 123); // [7b]
-> printf("[%0.X]", 123); // [7B]
-> printf("[%0.p]", a); // a = (int *a) [0x7ffee42daa20]
<case 1-3>
0 plag with min-width and . (s, c, %, d, i, u, x, X, p)
-> printf("[%05.s]","123"); // [00000]
-> printf("[%05.c]", '1'); // [00001]
-> printf("[%05.%]", 123); // [0000%]
-> printf("[%05.d]", 123); // [_ _123]
-> printf("[%05.i]", 123); // [_ _123]
-> printf("[%05.u]", 123); // [_ _123]
-> printf("[%05.x]", 123); // [_ _ _7b]
-> printf("[%05.X]", 123); // [_ _ _7B]
-> printf("[%05.p]", a); // a = (int *a) [0x7ffee42daa20]
<case 1-4>
0 plag with . and precision (s, c, %, d, i, u, x, X, p)
-> printf("[%0.5s]","123"); // [123]
-> printf("[%0.5c]", '1'); // [1]
-> printf("[%0.5%]", 123); // [%]
-> printf("[%0.5d]", 123); // [00123]
-> printf("[%0.5i]", 123); // [00123]
-> printf("[%0.5u]", 123); // [00123]
-> printf("[%0.5x]", 123); // [0007b]
-> printf("[%0.5X]", 123); // [0007B]
-> printf("[%0.5p]", a); // a = (int *a) [0x7ffee42daa20]
<case 1-5>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
-> printf("[%05.5s]","123"); // [00123]
-> printf("[%05.5c]", '1'); // [00001]
-> printf("[%05.5%]", 123); // [0000%]
-> printf("[%05.5d]", 123); // [00123]
-> printf("[%05.5i]", 123); // [00123]
-> printf("[%05.5u]", 123); // [00123]
-> printf("[%05.5x]", 123); // [0007b]
-> printf("[%05.5X]", 123); // [0007B]
-> printf("[%05.5p]", a); // a = (int *a) [0x7ffee42daa20]
<case 2-1>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
min-width > precision > 가변인자 길이
-> printf("[%06.5s]","123"); // [000123]
-> printf("[%06.5c]", '1'); // [000001]
-> printf("[%06.5%]", 123); // [00000%]
-> printf("[%06.5d]", 123); // [_00123]
-> printf("[%06.5i]", 123); // [_00123]
-> printf("[%06.5u]", 123); // [_00123]
-> printf("[%06.5x]", 123); // [_0007b]
-> printf("[%06.5X]", 123); // [_0007B]
-> printf("[%06.5p]", a); // a = (int *a) [0x7ffee42daa20]
<case 2-2>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
min-width > 가변인자 길이 > precision
-> printf("[%05.2s]","123"); // [00012]
-> printf("[%05.2c]", '1'); // [00001]
-> printf("[%05.2%]", 123); // [0000%]
-> printf("[%05.2d]", 123); // [_ _123]
-> printf("[%05.2i]", 123); // [_ _123]
-> printf("[%05.2u]", 123); // [_ _123]
-> printf("[%05.2x]", 123); // [_ _ _7b]
-> printf("[%05.2X]", 123); // [_ _ _7B]
-> printf("[%05.2p]", a); // a = (int *a) [0x7ffee42daa20]
<case 2-3>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
가변인자 길이 > min-width > precision
-> printf("[%03.2s]","12345"); // [012]
-> printf("[%03.2c]", '1'); // [001]
-> printf("[%03.2%]", 12345); // [00%]
-> printf("[%03.2d]", 12345); // [12345]
-> printf("[%03.2i]", 12345); // [12345]
-> printf("[%03.2u]", 12345); // [12345]
-> printf("[%03.2x]", 12345); // [3039]
-> printf("[%03.2X]", 12345); // [3039]
-> printf("[%03.2p]", a); // a = (int *a) [0x7ffee42daa20]
<case 3-1>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
precision > min-width > 가변인자 길이
-> printf("[%05.6s]","123"); // [00123]
-> printf("[%05.6c]", '1'); // [00001]
-> printf("[%05.6%]", 123); // [0000%]
-> printf("[%05.6d]", 123); // [000123]
-> printf("[%05.6i]", 123); // [000123]
-> printf("[%05.6u]", 123); // [000123]
-> printf("[%05.6x]", 123); // [00007b]
-> printf("[%05.6X]", 123); // [00007B]
-> printf("[%05.6p]", a); // a = (int *a) [0x7ffee42daa20]
<case 3-2>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
precision > 가변인자 길이 > min-width
-> printf("[%02.6s]","123"); // [123]
-> printf("[%02.6c]", '1'); // [01]
-> printf("[%02.6%]", 123); // [0%]
-> printf("[%02.6d]", 123); // [000123]
-> printf("[%02.6i]", 123); // [000123]
-> printf("[%02.6u]", 123); // [000123]
-> printf("[%02.6x]", 123); // [00007b]
-> printf("[%02.6X]", 123); // [00007B]
-> printf("[%02.6p]", a); // a = (int *a) [0x7ffee42daa20]
<case 3-3>
0 plag with min-width and . and precision (s, c, %, d, i, u, x, X, p)
가변인자 길이 > precision > min-width
-> printf("[%02.3s]","12345"); // [123]
-> printf("[%02.3c]", '1'); // [01]
-> printf("[%02.3%]", 12345); // [0%]
-> printf("[%02.3d]", 12345); // [12345]
-> printf("[%02.3i]", 12345); // [12345]
-> printf("[%02.3u]", 12345); // [12345]
-> printf("[%02.3x]", 12345); // [3039]
-> printf("[%02.3X]", 12345); // [3039]
-> printf("[%02.3p]", a); // a = (int *a) [0x7ffee42daa20]
<< 위 결과에서 알 수 있는 것 >>
우선은 0 flag가 오고 차례대로 min-width와 precision이 적용되었을경우 어떻게 출력되는지 나타내었다.
[0.0] = [0._] = [_.0] = [.]
d, i, u, x, X 는 동일한 방식으로 출력.
s, c, % 는 동일한 방식으로 출력.
0 flag 는 모두에게 적용된다. but) 0 flag 가 없어도 precision이 d, i, u, x, X 크기와 min-width보다 크면 자동으로 0 채움.
d, i, u, x, X 길이가 min-width, precision보다 클 때, 그냥 값 그대로 출력.
min-width가 d, i, u, x, X 길이보다 작을 때, d, i, u, x, X, 값 그대로 출력. but) precision이 d, i, u, x, X 보다 크면 이 값 앞에 0을 붙여서 출력.
p 는 0x가 앞에 기본적으로 붙고 뒤에 16진법으로 받은 주소값이 들어간다. 만약에 주소값의 크기가 precision보다 클때는 그대로 출력하다가 작아지면 주소값 앞에 0을 붙인다. 만약 min-width가 주소값 + 2보다(0x를 더한 것)크면 앞에 ' '를 붙임 => 정수랑 똑같이 동작. 만약애 주소값이 0일 때, precision이 없으면 0x0출력하고 precision이 있으면 precision크기만큼 0출력
ex)
-> a의 주소값이 0일 때, printf("[%.p]", a); // [0x]
-> a의 주소값이 0일 때, printf("[%.1p]", a); // [0x0]
-> a의 주소값이 0일 때, printf("[%.2p]", a); // [0x00]
-> a의 주소값이 0일 때, pritnf("[%5.2p]", a); // [_0x00]
========================================================================================================
<case 4-1>
<case 4-2>
=> -랑 0플레그 같이 들어오면 0 flag는 무시된다.
<case 5-1>
min-width and . and - plag and precision (s, c, %, d, i, u, x, X, p)
precision > min-width > 가변인자 길이
-> printf("[%5.-6s]","123"); // [_ _ _ _ _ _] <====> printf("[%-6s]","123"); // [123_ _ _]
-> printf("[%5.-6c]", '1'); // [1_ _ _ _ _] <====> printf("[%-6c]", '1'); // [1_ _ _ _ _]
-> printf("[%5.-6%]", 123); // [%_ _ _ _ _] <====> printf("[%-6%]", 123); // [%_ _ _ _ _]
-> printf("[%5.-6d]", 123); // [123_ _ _] <====> printf("[%-6d]", 123); // [123_ _ _]
-> printf("[%5.-6i]", 123); // [123_ _ _] <====> printf("[%-6i]", 123); // [123_ _ _]
-> printf("[%5.-6u]", 123); // [123_ _ _] <====> printf("[%-6u]", 123); // [123_ _ _]
-> printf("[%5.-6x]", 123); // [7b_ _ _ _] <====> printf("[%-6x]", 123); // [7b_ _ _ _]
-> printf("[%5.-6X]", 123); // [7B_ _ _ _] <====> printf("[%-6X]", 123); // [7B_ _ _ _]
-> printf("[%5.-6p]", a); // a = (char a) [0x____] <====> printf("[%5.-6p]", a); // a = (char a) [0x0___]
<case 5-2>
min-width and . and - plag and space and precision (s, c, %, d, i, u, x, X, p)
precision > min-width > 가변인자 길이
-> printf("[%5.- 6s]","123"); // [_ _ _ _ _ _]
-> printf("[%5.- 6c]", '1'); // [1_ _ _ _ _]
-> printf("[%5.- 6%]", 123); // [%_ _ _ _ _]
-> printf("[%5.- 6d]", 123); // [123 _]
-> printf("[%5.- 6i]", 123); // [123 _]
-> printf("[%5.- 6u]", 123); // [123_ _ _]
-> printf("[%5.- 6x]", 123); // [7b_ _ _ _]
-> printf("[%5.- 6X]", 123); // [7B_ _ _ _]
-> printf("[%5.- 6p]", a); // a = (char *a) [0x_ _ _ _]
<case 5-3>
min-width and . and - plag and + plag and precision (s, c, %, d, i, u, x, X, p)
precision > min-width > 가변인자 길이
-> printf("[%5.-+6s]","123"); // [_ _ _ _ _ _]
-> printf("[%5.-+6c]", '1'); // [1_ _ _ _ _]
-> printf("[%5.-+6%]", 123); // [%_ _ _ _ _]
-> printf("[%5.-+6d]", 123); // [+123_ _]
-> printf("[%5.-+6i]", 123); // [+123_ _]
-> printf("[%5.-+6u]", 123); // [123_ _ _]
-> printf("[%5.-+6x]", 123); // [7b_ _ _ _]
-> printf("[%5.-+6X]", 123); // [7B_ _ _ _]
-> printf("[%5.-+6p]", a); // a = (char *a) [0x_ _ _ _]
<< 위 결과에서 알 수 있는 것 >>
. 뒤에 (' ') or (-) or (+) 가 오면 자동으로 precision은 0이 되고 그 뒤에 나오는 숫자가 min-width가 됨
' '가 오면 d, i의 경우 앞에 공백을 추가해주고 나머지는 고려안해준다.
모든 flag들은 한 번이상오면 그냥 넘긴다.