0. 프로젝트 목표
- stdio.h 에 있는 printf와 유사한 함수 만들기
- 뉴라인버퍼를 사용하는 것은 아니고 문자열 해석해서 write함수로 찍어내기
- %[flags][width][precision][cspdixX%] 만 하기
- flag는 0과 -, specifier는 cspdixX% 만 출력하기
1. Makefile
1. libft.a를 이용해서 libftprintf.a를 만들어야 함
2. libft.a 를 컴파일 libftprintf.a로 복사 후 만든 .c파일을 libftprintf.a에 추가하면 됨
-> 그렇게 하지 않으면 libftprintf.a 만 가지고 libft.a에 있는 함수를 사용할 수 없음
-> 왜냐하면, libftprintf.a의 소스파일 중 libft.a의 함수를 사용하기 때문에..
-> 사용하려면 -lft -lftprintf 이렇게 두개의 라이브러리를 추가해야 함
-> 결국 테스트나, 뮬리넷은 libftprintf.a 만 가지고 결과값을 내기 때문에
-> libft.a 에 소스를 추가해야 맞는 듯 (cp ./lib/libft.a libftprintf.a)
3. 참고로 -c로 obj까지 컴파일 할 땐 링킹과정이 없기때문에 -l 옵션은 사용되지 않음에 명심
4. I옵션으로 2개를 줘야함 libft.h파일은 ./lib에, libftprintf.h은 ./header에 있기 때문
5. 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
CC = gcc
CFLAGS = -Wall -Wextra -Werror
LIB_DIR = ./lib
INC = -I./lib -I./header
NAME = libftprintf.a
SRC_DIR = ./src
SRC_NAME = ft_printf.c
SRCS = $(addprefix $(SRC_DIR)/, $(SRC_NAME))
OBJ_DIR = ./obj
OBJ_NAME = $(SRC_NAME:.c=.o)
OBJS = $(addprefix $(OBJ_DIR)/, $(OBJ_NAME))
$(NAME) : $(OBJS)
$(MAKE) -C $(LIB_DIR) bonus
cp $(LIB_DIR)/libft.a $@
ar rc $@ $^
$(OBJS) :
$(CC) $(CFLAGS) $(INC) -c $(SRCS) -o $@
all : $(NAME)
clean :
$(MAKE) -C ./lib clean
rm -rf $(OBJS)
fclean :
$(MAKE) -C ./lib fclean
rm -rf $(NAME) $(OBJS)
re : fclean all
.PHONY : all clean fclean re
|
cs |
www.cplusplus.com/reference/cstdio/printf/
2. cspdiuxX% 제어자 정리
%c : character
%s : string
%p : pointer address
%d : signed decimal integer
%i : signed decimal integer
%u : unsigned decimal integer
%x : unsigned Hex integer (lowercase)
%X : unsigned Hex integer (uppercase)
%% : print % character
3. - 0 . * 정리
number : 폭 크기 (default로 오른쪽 정렬, space로 채움)
- : 왼쪽 정렬
0 : 오른쪽 정렬일 때 빈칸을 space가 아닌 0으로 채움 (정수일 때 유효)
.number : 정수일 땐 출력되는 최소 숫자 (더 크면 0으로 채움), 문자열일 땐 최대 문자수
* : number를 파라미터로 받음
cf) 그냥 최대한 많은 경우를 printf에서 테스트해보고 똑같이 구현하면 됨
4. 가변인자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include <stdarg.h>
void foo(const char *format, ...)
{
va_list ap; // 가변인자를 불러올 데이터리스트
size_t i;
i = 0;
va_start(ap, format);
// 2번째 매개변수는 가변인자 직전의 매개변수를 넣음 (가변인자의 주소를 판단하기 위함인듯)
{ // 사실 중괄호 {}는 필요없으나 가독성을 위함이라고 POPE...
while (*format)
{
if (*format == '%')
{
++format;
if (*format == 'c')
{
char ch = va_arg(ap, int); // word단위로 스택에 들어가서 char도 int로 뽑음
write(1, &ch, 1);
}
// any command
}
else
{
write(1, &str[i], 1);
}
i++;
}
}
va_end(ap); //가변인자 리스트 ap 사용을 중단함을 알림
}
|
cs |
malbongcode.tistory.com/108?category=892906
5. 전체적인 로직 흐름
1. while문으로 char하나씩 출력
2. %를 만났을 때는 다른 로직
-> parsing (%[flag][width][.precision]specifier 를 구조체에 넣기) -> 넘어간 index 값 리턴
-> make_data (모든 값을 char *로 만들기, 출력에 용이함) -> 에러체크
-> print_data (parsing한 구조체의 값에 따라 출력하기) -> 출력한 cnt 값 리턴
cf) 속도적인 측면에서는 write를 줄이는 게 맞음
cf) 생산적인 측면에서는 write로 하나씩 찍어내는 것이 맞음
'42cursus' 카테고리의 다른 글
Kubernetes(쿠버네티스) 개념 정리하기 (0) | 2021.01.07 |
---|---|
libasm - 참고 자료 위주로 정리하기 (42seoul) (1) | 2020.11.28 |
cub3d - mlx사용법 위주로 정리하기 (42seoul) (2) | 2020.11.03 |
ft_server - 가이드 및 참고자료 정리하기 (42seoul) (2) | 2020.10.19 |
get_next_line - 초간단 정리 (42seoul) (0) | 2020.10.09 |