프로그래밍웹 교과서
이 페이지의 목차
2단원 · 5차시

출력의 형식을 정하다

표준 출력형식 지정자리 맞춤소수점 자릿수

코드 예제: Python · C · 예상 50분

학습 목표

  • 출력 기능의 역할을 설명한다.
  • 형식을 지정하여 원하는 모양으로 값을 출력한다.

관련 성취기준

  • 프그02-02

    입력과 출력의 기능을 이해하고, 형식을 지정하여 데이터를 입력하고 출력할 수 있다.

생각 열기 — 숫자가 줄줄이 나오면

성적을 계산해 이렇게 찍었다.

국어 88
영어 92.5
수학 75
평균 85.16666666666667

값은 다 맞다. 그런데 읽기가 불편하다. 숫자가 시작하는 자리가 들쭉날쭉하고, 평균은 소수점이 열네 자리나 나온다.

출력 — 프로그램이 사람에게 말하는 유일한 창구

프로그램이 아무리 옳게 계산해도 화면에 나오지 않으면 사용자는 알 수 없다. 1단원 6차시에서 알고리즘의 조건으로 “출력이 하나 이상 나온다”를 든 것이 이 때문이다.

출력을 다룰 때 정하는 것은 셋이다.

  • 무엇을

    어떤 값을 보여 줄까

    계산한 값 전부가 아니라 사용자가 필요한 것만. 중간 계산값은 감춘다.

  • 어떻게

    자리와 자릿수

    자리를 맞추면 표처럼 읽힌다. 소수는 몇 자리까지 보일지 정한다.

  • 어디에

    한 줄인가 이어 붙이나

    줄을 바꿀지 말지 정한다. 표를 만들 때는 줄바꿈을 미루기도 한다.

형식 지정 — 자리와 자릿수를 정한다

형식 지정(formatting) — 값을 어떤 모양으로 문자열에 넣을지 정하는 일. 폭과 소수 자릿수, 정렬을 정한다은 값을 문자열에 끼워 넣을 때 모양을 정하는 일이다.

Python자리를 맞춘 성적표
과목 = ["국어", "영어", "수학"]
점수 = [88, 92.5, 75]

for i in range(3):
    print(f"{과목[i]}  {점수[i]:>6.1f}")
print(f"평균  {sum(점수) / 3:>6.1f}")
확인된 실행 결과
국어    88.0
영어    92.5
수학    75.0
평균    85.2
C자리를 맞춘 성적표확인된 출력
#include <stdio.h>

int main(void)
{
    const char *subject[] = {"국어", "영어", "수학"};
    double score[] = {88.0, 92.5, 75.0};
    double sum = 0;

    for (int i = 0; i < 3; i++) {
        printf("%s  %6.1f\n", subject[i], score[i]);
        sum += score[i];
    }
    printf("평균  %6.1f\n", sum / 3);
    return 0;
}
실행 결과
국어    88.0
영어    92.5
수학    75.0
평균    85.2

두 언어의 출력이 글자 하나까지 같다. 형식을 정해 두면 언어가 달라도 같은 모양이 나온다는 것을 보여 주는 예다.

:>6.1f 를 뜯어 보면

{점수 :  >    6    .1    f}
       │  │    │     │    │
       │  │    │     │    └─ 실수로 (float)
       │  │    │     └────── 소수점 아래 한 자리
       │  │    └──────────── 전체 여섯 칸을 차지하게
       │  └───────────────── 오른쪽으로 붙여 (right)
       └──────────────────── 여기서부터 형식 지정

C의 %6.1f 도 같은 뜻이다. 숫자는 오른쪽 정렬이 기본이라 > 에 해당하는 표시가 없다.

자주 쓰는 형식 지정
하려는 일PythonC
정수 그대로{n}%d
실수 소수 한 자리{x:.1f}%.1f
여섯 칸에 오른쪽 정렬{x:>6}%6d / %6.1f
여섯 칸에 왼쪽 정렬{x:<6}%-6d
천 단위 쉼표{n:,}따로 없다. 직접 만들어야 한다
문자열 그대로{s}%s

한글은 자리 맞춤이 언어마다 다르다

3차시에서 예고한 함정이 여기서 나온다. 위 예제는 과목 이름에 폭을 지정하지 않았다. 일부러 그렇게 했다.

  • Python의 f"{과목:<8}" 은 글자 수로 여덟 칸을 센다. 국어 는 2칸으로 세고 6칸을 채운다.
  • C의 %-8s 는 바이트 수로 여덟 칸을 센다. 국어 는 6바이트로 세고 2칸만 채운다.

같은 8 을 적어도 결과가 다르다. 그래서 이 교과서의 예제는 한글에는 폭을 주지 않고 숫자에만 준다.

줄바꿈을 다루는 법

print 는 끝에 줄바꿈을 자동으로 넣는다. 표를 만들 때는 그것을 막아야 한다.

줄바꿈 다루기
하려는 일PythonC
찍고 줄바꿈print(x)printf("%d\\n", x)
줄바꿈 없이 이어 찍기print(x, end="")printf("%d", x) — 원래 안 넣는다
빈 줄 하나print()printf("\\n")
값 사이에 넣을 것 정하기print(a, b, sep=", ")형식 문자열에 직접 적는다

C는 줄바꿈을 자동으로 넣지 않는다. \n 을 빠뜨리면 출력이 죄다 한 줄에 붙어 나온다. 반대로 Python은 넣는 것이 기본이라 막을 때 end="" 를 적는다. 11차시에서 별 찍기를 할 때 이 차이를 실제로 쓴다.

활동

실습

표 모양으로 정렬된 성적표 출력하기

약 25분

1단계 — 폭을 바꿔 본다 (10분)

실행기의 [고치기]로 숫자 부분의 형식만 바꿔 보고 결과를 적는다.

형식 결과 (공백을 · 로 표시해 적기)
{점수:>6.1f}
{점수:>10.1f}
{점수:<6.1f}
{점수:>6.0f}
{점수:>6.3f}
{점수:6d} (정수로)
  • 폭을 값보다 작게 주면 어떻게 되는가? ({점수:>2.1f} 로 해 보자)
  • .0f 로 하면 소수 첫째 자리는 버려지는가, 반올림되는가? 92.5 로 확인한다.

2단계 — 머리글을 붙인다 (5분)

표에 머리글과 구분선을 넣어 아래처럼 만들어 보자.

과목    점수
------------
국어    88.0
  • 구분선은 어떻게 만드는 것이 편한가? (Python에서 "-" * 12 를 해 보자)

3단계 — 한글 자리 맞춤을 겪어 본다 (10분)

과목 이름을 길이가 다른 것으로 바꾼다 — ["국어", "사회문화", "수학"].

  • 폭을 주지 않은 지금 코드에서 숫자 자리가 어긋나는가?
  • Python에서 f"{과목[i]:<8}" 처럼 폭을 주면 맞아지는가?
  • 같은 폭을 C의 %-8s 로 주면 어떻게 되는가? 두 결과를 나란히 적어 견줘 본다.
Python :<8 C %-8s
국어 뒤 공백 칸 수
사회문화 뒤 공백 칸 수
숫자가 한 줄로 맞았나

왜 다른지 한 문장으로 적는다.

개념 확인 문제

보기를 누르면 바로 채점된다. 틀려도 해설을 읽으면 된다.

Python의 f「{x:>6.1f}」 에서 6 이 뜻하는 것은?프그02-02

표에서 숫자를 오른쪽 정렬하는 까닭으로 가장 알맞은 것은?프그02-02

같은 폭 8 을 주었는데 Python과 C의 결과가 다른 까닭은?프그02-02

C에서 printf(「%d」, x) 를 여러 번 부르면 출력이 한 줄에 붙어 나온다. 그 까닭은?프그02-02

설계 문서에 출력 형식을 띄어쓰기까지 적어 두는 실질적인 이유는?프그02-02

더 알아보기

심화반올림은 생각보다 까다롭다

{92.45:.1f} 이 92.5 가 될지 92.4 가 될지는 짐작하기 어렵다. 2차시에서 다룬 대로 컴퓨터가 실수를 정확히 담지 못하기 때문이다. 92.45 가 실제로는 92.4499… 로 담겨 있으면 내림이 된다. 성적처럼 민감한 값을 다룰 때는 어떻게 반올림할지 요구 사항에 못 박고(3단원 2차시), 경계값으로 테스트해야 한다(3단원 7차시). 정확한 반올림이 필요하면 실수 대신 정수로 계산하는 방법도 있다 — 소수 첫째 자리까지 필요하면 값을 10배 해서 정수로 다루는 식이다.

실무형식 문자열이 세 세대에 걸쳐 바뀌었다

Python에서 문자열에 값을 끼워 넣는 방법은 여러 가지가 있다. 오래된 "%d" % n 방식, 그다음 "{}".format(n) 방식, 그리고 지금 주로 쓰는 f"{n}" 방식이다. 세 방식이 다 남아 있어 남의 코드를 읽을 때 섞여 나온다. 새로 쓸 때는 f 방식을 쓰는 것이 읽기 좋다 — 값이 들어갈 자리에 이름이 그대로 보이기 때문이다. C의 printf 는 오래됐지만 형식 표기가 거의 그대로 남아, Python의 % 방식이나 다른 언어에도 비슷하게 쓰인다. 하나를 익히면 여러 언어에서 통한다.

심화화면에 바로 안 나올 때가 있다

C에서 printf 로 찍었는데 화면에 바로 안 보이는 일이 있다. 출력을 한 글자씩 내보내면 느려서, 어느 정도 모아 두었다가 한꺼번에 내보내기 때문이다. 이것을 버퍼라 한다. 줄바꿈을 만나거나 버퍼가 차면 실제로 나간다. 그래서 프로그램이 중간에 비정상 종료하면 찍었다고 생각한 출력이 안 나올 수 있다. 디버깅할 때 이것 때문에 헷갈리는 일이 있으니, 마지막 출력이 안 보인다고 그 앞이 실행되지 않았다고 단정하지 않는 편이 좋다.

이어지는 학습

이 차시를 이해하려면 다음을 먼저 알아야 한다.

교과서에서 찾기

교과서해당 위치쪽수
성림출판(Python)프로그래밍의 기초 › 02 입력과 출력104쪽
씨마스커뮤니케이션(Python)프로그래밍 기초 › 1 입력과 출력72쪽
삼양미디어(Python)프로그래밍의 기초 › 01 데이터 입출력 (프그02-01과 통합)42쪽
삼양미디어(C)프로그래밍의 기초 › 01 데이터 입출력 (프그02-01과 통합)42쪽
씨마스(C)C 프로그래밍의 기초 › 2 입출력 함수72쪽
웅보출판사(C)프로그래밍의 기초 › Chapter 02 입출력 함수85쪽