[ft_printf] 대략적 코드 흐름, 조건문에서 주의할 점

퐁퐁이·2021년 12월 29일
0

42SEOUL

목록 보기
10/12

방금 ft_printf 평가를 받다가, 코드에 대한 중요한 comment를 받게 되어서 쓰는 글

대략적인 코드의 흐름은 이렇다.

<ft_printf.c>

  • ft_printf 함수에서 하나의 고정인자와 가변인자를 매개변수로 받는다.
  • va_list 가변 인자 포인터 변수 ap와, 각 가변인자에 대한 출력 길이를 임시 저장할 변수를 선언한다.
  • va_start로 가변인자를 가리키게 한다.
  • 가변인자에 대한 출력 길이 임시 저장할 변수 += ft_parse_format
  • va_end로 가변인자의 파싱이 끝났음을 알려준다.

<ft_parse_format.c>

  • 고정 인자의 문자열의 문자들이 널 종료 문자를 만날 때 까지 순차적으로 탐색한다.
  • '%' 문자를 만났을 경우, 서식 지정자에 대한 처리를 수행한다
    -ft_parse_format 함수 호출, '%' 다음 인덱스 문자의 가변 인자 목록 포인터를 매개변수로 넘겨준다
    -맨 끝에 '%'만 있을 경우 다음 문자는 NULL이므로, break
  • '%'문자를 발견하지 못할 경우, 문자를 순수 출력한다.

<ft_parse_type> 함수는 다음과 같은데 어떤 점이 문제가 될 수 있을까?

int	ft_parse_type(const char c, va_list ap)
{
	int		cnt;

	cnt = 0;
	if (c == 'c') //문자
		cnt += ft_print_ch(ap);
	else if (c == 's') //문자열
		cnt += ft_print_str(ap);
	else if (c == 'p') //포인터의 메모리 주소
		cnt += ft_print_mem(ap, c);
	else if (c == 'd' || c == 'i') //부호가 있는 10진 정수, scanf에서 역할이 다름
		cnt += ft_print_int(ap, c); //d : 10진수 입력받음, i : 10/8/16진수 입력 받음
	else if (c == 'u') //부호가 없는 10진 정수
		cnt += ft_print_unsigned_int(ap, c);
	else if (c == 'x' || c == 'X') //부호가 없는 16진 정수 (소문자 / 대문자)
		cnt += ft_print_hexadecimal(ap, c);
	else if (c == '%') //형식 지정에 필요한 문자, %기호 출력 
		cnt += write(1, "%", 1);
	return (cnt);
}

이러한 조건문을 쓸 때는 주의할 점이 있다.
바로, "모든 조건에 해당하지 않을 경우에 대한 처리."

예를들어, "%m"과 같은 가변인자 목록 포인터를 매개변수로 넘겨 받았다면 어떻게 처리가 될까?

위 로직만으로만 봤을 때는, 모든 조건문에 해당하지 않기 때문에 아무 것도 출력 되지 않는다. 즉, 무시되는 것이다. 그러므로 else문을 마지막에 추가해서, 문자 그대로 write 해주는 부분이 필요하다.

그리고 매개변수를 ap로 넘겨주는 것 보다는, va_arg로 바로 넘겨주는 것이 더 깔끔하고 간단한 코드가 될 수 있었다!

write는 오류 시 -1을 반환하기 때문에 % 기호 출력 시 사용 된 write 함수에 대한 예외처리도 필요하다.

다행히 3개의 test기를 돌려 봤을 때 모두 통과가 되었기 때문에 fail을 받지는 않았다. 그런데 아주 중요한 부분을 놓친 것 같다!!
(jonghpar님 감사합니당 😆)

profile
코딩하는 에디

0개의 댓글