--- Category : ft_printf Id : 1 Title : "ft_printf 개요" Description : "ft_printf 개요" Date : 2020, 10, 20 (Tue) Auther : seolim pre : 0 next : 0 tags : ft_printf --- # 1 ft_printf 개요 > Link [link not yet]() > Caution 본 문서를 포함한 블로그의 모든 내용은 <b>42 innovation academy</b>의 과제의 작성자의 해석 및 풀이 등으로 이루어져 있습니다.</br>본인이 42 교육생이거나 42 교육을 희망하는 분이라면 글을 먼저 보기보다는 고민해보고 읽어보기를 추천드립니다. > 목적 `<stdio.h>`의 printf()를 구현해 본다. ```c int ft_printf(const char *fmt, ...); ``` 1. 가변 인수(variable argument)를 이해하고 활용할 수 있게끔 한다. 2. 기능별로 분리하여 code 구성할 수 있게끔 한다. 3. parsing의 개념을 이해하고 구성할 수 있게끔 한다. > 선수 지식 ### 가변 인수(variable argument) printf를 생각해보면 함수의 파라미터의 타입도 개수도 정해져있지 않고 실행이 가능하다. 이를 가능하게 해 주는 인수가 가변인수(variable argument)이며 <stdarg.h>의 정의를 통해 조작할 수 있다. 아래 코드를 보자. ```c #include <stdarg.h> int argsTest(int args, ...) { va_list ap; va_start(ap, args); for (int i = 0; i < args; i++) printf("%d ", va_arg(ap, int)); printf("\n"); va_end(ap); } int main() { argsTest(4, 1, 2, 3, 4); argsTest(2, 5, 6); } /* result : * 1 2 3 4 * 5 6 */ ``` 위 코드에서 `...`이 가변인자를 받는 함수이다. 각각의 기능을 간단히 설명하면 아래와 같다.</br></br> - **va_list** : 가변인자 목록 포인터 - **va_start(va_list, void)** : 가변인자 목록 포인터를 두번째 파라미터 다음 주소로 할당한다. - **va_arg(va_list, type)** : 가변인자 목록 포인터를 선언된 타입의 크기만큼 캐스트하고 진행시킨다. 즉 cast된 변수 다음 변수로 포인터가 이동한다. - **va_end(va_list)** : 가변인자 목록 포인터의 메모리 처리를 하는데, 대부분의 운영체제에서는 자동으로 회수되므로 사용하지 않아도 상관없는 경우가 많다. ### parsing 언어학에선 *구문분석*으로 해석되어있고 프로그래밍상에선 어떠한 구분은 원하는 형태로 분석하여 원하는 형태의 데이터로 조립하는 방법이나 과정을 말한다.</br></br>모든 프로그램에서 데이터 통신은 규격 문서와 규격문서에 대한 parsing으로 진행된다. 대표적인 예로 url을 들 수 있다. 현 과제단계에선 간단히 이해하고 자세한 내용은 [wiki](https://en.wikipedia.org/wiki/Parsing)를 참고하도록 하자. ### printf printf는 첫번째 파라미터와 가변인자를 받는 함수로 첫번째 파라미터의 구문은 specifier와 flag, 일반 출력구문으로 이루어진 규격을 가진 char 포인터 문자열이다. **Specifier** printf에서 보던 "%s", "%d" 등이 specifier이고 가능한 spcifier는 아래와 같다. ```c printf("%d", 10); // 부호 있는 정수 printf("%i", 10); // 부호 있는 정수 printf("%u", 10); // 부호 없는 정수 printf("%o", 10); // 부호 있는 8진 정수 printf("%x", 10); // 부호 있는 16진 정수 (소문자 표기) printf("%X", 10); // 부호 없는 16진 정수 (대문자 표기) printf("%c", 'a'); // char 문자 printf("%s", "string"); // char 포인터 문자열 printf("%p", &var); // pointer 주소 printf("%f", 1.2); // 부동 소수 (십진 출력) printf("%e", 1.2); // 부동 소수 (지수 출력, 소문자 표기) printf("%E", 1.2); // 부동 소수 (지수 출력, 대문자 표기) printf("%g", 1.2); // 부동 소수 (e, f중 간단한 것 출력, 소문자 표기) printf("%G", 1.2); // 부동 소수 (e, f중 간단한 것 출력, 대문자 표기) printf("%%"); // '%' 문자 출력 printf("%n", n) // int 형 변수 n에 현재까지 출력된 문자 수를 저장, 출력 없음 ``` **Flag** 각각의 specifier에는 출력과 관련된 flag를 지정할 수 있다. 플래그는 크게 width, decimal, etc로 구분될 수 있고 각각의 내용은 양이 많으므로 [여기](https://modoocode.com/35)를 참고하도록 하자. > ft_printf ### 함수의 기능 첫번째 파라미터 구문을 분석하여 특정한 형태의 구문을 stdout에 출력하는 함수. 요구하는 구문의 specifer와 flag는 아래와 같다.(bonus 제외) - **specifier** : cspdiuxX% - **flag** : -0.*