[printf 함수분석] %d, %i 서식지정자 정밀도 규칙

gaeun·2020년 9월 23일
0

ft_printf

목록 보기
1/1

들어가기에 앞서...

  • C Library printf의 기능을 직접 구현하기에 앞서 original printf를 분석하며 작성한 글입니다.
  • 해당 포스트는 printf 함수의 형식태그 중에서 정밀도(precision)를 집중 분석한 글이며, 일반적인 정밀도 규칙은 작성하지 않았습니다.
  • 이 글은 정밀도 중에서도 특수한 case에 적용되는 규칙만을 정리하였습니다. 따라서 일반적인 정밀도 규칙과는 별개로 생각하는게 좋습니다.
  • 테스트 환경은 맥 OS이며 리눅스나 윈도우에서는 다른 결과가 나올 수 있습니다.
  • dot 은 printf 형식태그 중에서 정밀도에 쓰이는 점(.)입니다.
  • pre 는 정밀도 숫자 값 입니다.
  • ^ 는 공백 1칸입니다.
  • 인자 는 printf에 넘겨주는 정수를 말합니다. (해당 포스트는 서식지정자 %d, %i에 대해서만 다룹니다.)
  • 편의상 앞에 printf 글자, 첫 번째 인자를 묶어주는 "", 맨 뒤의 ;를 생략하고 작성했습니다.
    ex. printf("%5.d", 123); → (%.5d, 123)

1. (dot == 1) and (pre X or pre == 0 or pre < 0) and (인자 != 0) 일 때

ex. printf("%5.d", 123); printf("%5.0d", 123); printf("%5.-2d", 123); printf(%5.*d, -2, 9);

(1) pre를 숫자로 받는 경우

  • [pre가 음수] pre의 마이너스를 ‘-’ flag로 적용하고, pre 값을 양수로 바꿔서 width로 적용한다. (width 값이 따로 있더라도 무시하고 pre를 width로 사용)
    👉 ex. (%5.-2d, 9) : 9^
  • [pre가 0 또는 X] pre를 무시하고 나머지 형식태그를 적용하여 인자를 출력
    👉 ex.(%5.d, 10) : ^^^10, (%5.0d, 10) : ^^^10

(2) pre를 ‘*’ 인자로 받는 경우

  • [pre가 음수] pre를 무시하고 나머지 형식태그 적용하여 인자를 출력
    👉 ex.(%5.*d, -2, 9) : ^^^^9

  • [pre가 0] pre를 무시하고 나머지 형식태그 적용하여 인자를 출력
    👉 ex.(%5.*d, 0, 10) : ^^^10

  • [pre가 X] 인자 개수가 맞지 않으므로 처리할 필요X


2. 위의 1번 상황에서 인자는 0일 경우 (예외 해당)

ex. printf("%5.d", 0); printf("%5.0d", 0); printf("%5.-2d", 0); printf(%5.*d, -2, 0);

(1) pre를 숫자로 받는 경우, 인자인 0을 출력하지 않는다.

  • [pre가 음수] pre 값을 양수로 바꿔서 width로 적용하여 공백만 출력 (width 값이 따로 있더라도 무시하고 pre를 width로 사용)
    👉 ex.(%5.-2d, 0) : ^^, (%05.-2d, 0) : ^^, (%-5.-2d, 0) : ^^
  • [pre가 0 또는 X] pre를 무시하고 width만 적용하여 공백 출력
    👉 ex.(%5.0d, 0) : ^^^^^, (%5.d, 0) : ^^^^^, (%1.d, 0) : ^, (%1.0d, 0) : ^, (%.d, 0) : 출력X, (%.0d, 0) : 출력X

(2) pre를 '*' 인자로 받는 경우, 인자인 0을 출력한다. (pre == 0인 경우 제외)

  • [pre가 음수] pre를 무시하고 나머지 형식태그 적용하여 인자를 출력
    👉 ex.(%5.*d, -2, 0) : ^^^^0, (%-5.*d, -2, 0) : 0^^^^, (%05.*d, -2, 0) : 00000, (%.*d, -2, 0) : 0

  • [pre가 0] (예외 발생) 인자인 0을 출력하지 않음. 1-(2)번과 동일한 규칙 (pre를 무시하고 width만 적용하여 공백 출력)
    👉 ex.(%5.*d, 0, 0) : ^^^^^, (%-5.*d, 0, 0) : ^^^^^, (%05.*d, 0, 0) : ^^^^^

  • [pre가 X] 인자 개수가 맞지 않아서 이상한 값이 찍힘. 처리할 필요X


3. 번외: (인자 == 0) and (pre > 0) 일 때

평소의 정밀도(precision) 규칙대로 적용된다.

(1) pre를 숫자로 받음

​ 👉 (%.5d, 0) : 00000, (%7.5d, 0) : ^^00000, (%-7.5d, 0) : 00000^^, (%07.5d, 0) : ^^00000

(2) pre를 '*' 인자로 받음

​ 👉 (%.*d, 5, 0) : 00000, (%7.*d, 5, 0) : ^^00000, (%-7.*d, 5, 0) : 00000^^, (%07.*d, 5, 0) : ^^00000


4. 마무리 정리

(dot == 0) and (인자 == 0) and (width > 0)
vs (dot == 1) and (pre X or pre == 0) and (인자 == 0)

👉 printf("%5d", 0); vs printf("%5.d", 0);

  • 전자는 플래그 정상 작동 = 인자 0을 출력
    👉 (%5d, 0) : ^^^^0, (%1d, 0) : 0

  • 후자는 위에서 설명한 2-(1)번에 해당하는 case. (pre를 무시하고 width만 적용하여 공백 출력)
    👉 (%5.d, 0) : ^^^^^

  • 전자와 후자의 차이점
    전자는 dot(.)을 찍었는데 정밀도가 없는거고, 후자는 dot(.)이 아예 등장X.
    전자는 무조건 인자 0을 출력하고, 후자는 인자 0을 출력하지 않는 경우도 있다.

오탈자, 틀린 부분이 있거나 궁금한 점이 있다면 편하게 댓글 남겨주세요! 🙂

profile
비전공자의 개발 도전기

0개의 댓글