3강 · 제3장 · 65~77쪽 · 약 55분

입·출력 함수와 연산자(1)

함수의 개념을 짚고, 표준 출력함수(printf·putchar·puts)와 표준 입력함수(scanf·getchar·gets)를 예제로 익힙니다. (교재 제3장 65~77쪽)

학습 목표

  • 함수(라이브러리 함수)가 이름·인자·반환값으로 호출되는 재사용 단위임을 설명한다
  • 출력 양식이 문자형 상수 + 변환기호(%문자) + 제어문자(\문자)로 이루어짐을 설명한다
  • 주요 변환기호(%d %ld %lld %u %o %x %f %e %c %s %%)를 자료형에 맞게 사용한다
  • 표준 출력함수 printf·putchar·puts의 쓰임과 출력 양식 편집(%5d, %-5d, %05d, %7.2f)을 안다
  • 표준 입력함수 scanf·getchar·gets의 쓰임과 주소 연산자 &, 공백 처리를 안다
  • 교재 표기(void main, gets, #pragma warning, 출력의 %lf)와 이 사이트·표준 표기 차이를 안다

왜 이 강이 필요한가?

프로그램은 자료를 받아 처리하고 내보냅니다. 1·2강에서 변수와 자료형을 배웠으니, 이제 그 자료를 화면에 출력하고 키보드에서 입력하는 방법을 익힙니다.

이 강은 교재 제3장(입출력함수와 연산자) 의 65~77쪽 범위이며, 순서는 다음과 같습니다.

  1. 함수의 개념 — printf·scanf가 바로 “함수”입니다. 함수가 무엇인지부터 가볍게 정리합니다.
  2. 표준 출력함수 — printf, putchar, puts
  3. 표준 입력함수 — scanf, getchar, gets

3장 후반의 연산자는 4강에서 다룹니다.

본문의 C 예제는 코드 아래에 실행 칸이 붙습니다. 다만 이 인라인 실행 칸에는 입력 상자가 없어서, scanf가 필요한 예제는 같은 변환 명세를 쓰는 sscanf(고정 문자열 파싱)로 결과를 보여 줍니다. 진짜 키보드 입력 실습은 맨 아래 종합 실습(입력 상자 있음)이나 상단 「코드연습」 탭에서 하세요.


1. 함수의 개념

함수(function) 는 어떤 일을 하는 코드에 이름을 붙여 두고, 필요할 때 그 이름으로 불러 쓰는(호출하는) 재사용 단위입니다. 수학의 y = f(x)처럼 생각하면 됩니다.

요소설명printf("%d", n) 에서
이름호출할 때 쓰는 식별자printf
인자(argument)함수에 넘겨 주는 입력 값"%d", n
반환값(return value)함수가 돌려주는 결과 값출력한 문자 수(잘 안 씀)

C가 제공하는 함수는 두 갈래입니다.

  • 라이브러리 함수 — C 시스템이 미리 만들어 둔 함수. printf, scanf, strlen 등. 쓰려면 해당 헤더를 #include 합니다.
  • 사용자 정의 함수 — 내가 직접 만드는 함수. 6·7강에서 정의·호출·기억 클래스를 본격적으로 다룹니다.

C는 입출력을 언어 문법이 아니라 라이브러리 함수로 제공합니다. 그래서 모든 예제가 #include <stdio.h>로 시작합니다. #include는 함수의 선언(원형) 만 가져오고, 실제 구현은 링크 때 표준 라이브러리에서 연결됩니다(1강 복습).

이 예제 실행

실행 결과가 여기에 표시됩니다.

함수는 인자를 받아 일을 하고 값을 돌려줍니다. strlen("knou")는 길이 4를, printf("hello\n")는 출력한 문자 수 6을 반환합니다. 반환값을 꼭 쓸 필요는 없지만, “함수는 값을 돌려준다”는 감각을 잡아 두세요.


2. 표준 출력함수

자료를 컴퓨터 내부에 기억시키는 것을 입력, 내부에 기억된 내용을 외부(화면)로 나타내는 것을 출력이라고 합니다. C는 이 입출력을 언어 문법이 아니라 <stdio.h>의 라이브러리 함수로 제공하며, 대표 출력함수는 셋입니다.

함수기능
printf()여러 종류의 자료를 양식을 지정해 출력
putchar()문자 1개를 출력
puts()문자열을 출력하고 자동으로 줄바꿈

2.1 printf — 양식 지정 출력

printf는 print formatted(양식을 지정한 출력), 뒤에 나오는 scanf는 scan formatted(양식을 지정한 입력)의 줄임말입니다.

  • 형식: printf("출력 양식", 인자1, 인자2, …);
  • 출력 양식(큰따옴표로 감쌈)은 세 가지로 이루어집니다.
    1. 문자형 상수 — 글자·숫자·기호. 그대로 화면에 나옴
    2. 변환기호 %문자 — 뒤의 인자를 그 자리에 끼워 넣음
    3. 제어문자 \문자 — \n(줄바꿈), \t(탭) 등 (2강 이스케이프 문자 복습)

인자는 왼쪽부터 순서대로 % 기호에 대응됩니다. 예를 들어 printf("A = %d, B = %c\n", a, b); 한 줄은 이렇게 나뉩니다.

printf("A = %d, B = %c\n", a, b); 의 조각종류하는 일
A = , , B = 문자형 상수그대로 화면에 출력
%d, %c변환기호a, b를 순서대로 그 자리에 끼워 넣음
\n제어문자줄바꿈

이 예제 실행

실행 결과가 여기에 표시됩니다.

같은 변수 c가 %c(문자 A)와 %d(코드 값 65)에 각각 대응된 점을 보세요.

2.2 printf 변환기호

%문자변환 형식인자의 자료형
%d부호 있는 10진 정수char, short, int
%ld / %lld10진 long / long long 정수long / long long
%u부호 없는 10진 정수unsigned int
%o부호 없는 8진수unsigned int
%x, %X부호 없는 16진수 (소문자 / 대문자)unsigned int
%f10진 부동소수점float, double
%e, %E지수 표기float, double
%c문자 하나char, int
%s문자열char *
%p포인터 주소값void *
%%% 문자 자체(인자 없음)

이 예제 실행

실행 결과가 여기에 표시됩니다.
  • 같은 비트 패턴이라도 %u/%o/%x는 10진/8진/16진으로 다르게 보입니다.
  • 지수 결과는 이 사이트에서 1.234568e+03입니다. 교재(Windows)는 지수를 3자리로 써서 1.234568e+003으로 나옵니다. 지수 자릿수는 환경마다 다릅니다.

생각해 보기: printf("test", 123);처럼 인자가 남으면 남는 인자는 조용히 무시됩니다(정상 동작). 반대로 printf("test %d");처럼 인자가 모자라면 쓰레기 값이 찍히거나 프로그램이 죽는 미정의 동작입니다. 컴파일러는 -Wformat 경고로 알려 줍니다.

2.3 printf 출력 양식 편집 — 폭·정렬·정밀도

%와 변환 문자 사이에 숫자·기호를 넣어 편집합니다.

편집뜻
%5d최소 너비 5, 오른쪽 정렬(앞을 공백으로)
%-5d최소 너비 5, 왼쪽 정렬(뒤를 공백으로)
%05d최소 너비 5, 남는 앞자리를 0으로 채움
%6.1f전체 너비 6(소수점 포함), 소수 이하 1자리
%.11s문자열 앞 11자만 출력

이 예제 실행

실행 결과가 여기에 표시됩니다.

교재 예제3-1(종합) — \t 탭, %04d/%09d 0채움, %.3f/%.3e 정밀도, %.11s 자르기를 한 번에:

이 예제 실행

실행 결과가 여기에 표시됩니다.

2.4 putchar — 문자 1개 출력

  • 형식: putchar(문자); — 문자 하나를 출력합니다.
  • 인자는 정수형 변수·상수, 문자형 변수·상수, 수식이면 됩니다.

이 예제 실행

실행 결과가 여기에 표시됩니다.

putchar는 뒤에 나오는 입력함수 getchar와 짝입니다(문자 하나 출력 ↔ 문자 하나 입력).

2.5 puts — 문자열 출력

  • 형식: puts(변수); — 문자열을 출력한 뒤 자동으로 줄을 바꿉니다(문자열 끝 \0을 \n으로).
  • 그래서 printf("%s", s)와 달리 \n을 따로 붙이지 않아도 됩니다. 반대로 printf("%s", ...)를 연달아 쓰면 줄바꿈이 없어 붙어서 출력됩니다.

이 예제 실행

실행 결과가 여기에 표시됩니다.

3. 표준 입력함수

<stdio.h>가 제공하는 대표 입력함수도 셋이며, 출력함수와 하나씩 짝을 이룹니다.

함수기능짝이 되는 출력함수
scanf()양식을 지정해 1개 이상의 자료를 입력printf()
getchar()문자 1개를 입력putchar()
gets()문자열을 입력 (위험 — 3.3)puts()

3.1 scanf — 양식 지정 입력

  • 형식: scanf("입력 양식", &변수1, &변수2, …);
  • 변환기호는 printf와 거의 같지만 double 입력은 %lf 를 씁니다. (float은 %f.) printf에서는 둘 다 %f였습니다 — 여기서 갈립니다.
  • 모든 변수 앞에 &(주소 연산자). "값을 어디에 저장할지" 주소를 넘기는 것입니다. (포인터는 9강)
  • 문자열(배열명) 앞에는 &를 생략합니다. 배열명 자체가 주소이기 때문입니다.
  • 자료가 둘 이상이면 입력할 때 공백(스페이스·탭·엔터)으로 구분합니다.
  • %c 앞에 공백 한 칸(" %c")을 두면, 앞선 입력에서 남은 엔터(\n)를 건너뜁니다.
  • scanf가 실행되면 화면에 커서가 깜박이며 입력을 기다리고, 자료를 입력한 뒤 엔터를 누르면 전달됩니다.

scanf 입력 양식 변환기호 — printf의 변환기호를 거의 그대로 쓰지만, 실수는 자료형에 따라 갈립니다.

%문자입력받는 자료
%d정수 (int)
%ld / %lldlong / long long 정수
%f실수 (float)
%lfdouble 실수
%c문자 하나
%s공백 없는 문자열
%o / %x8진 / 16진 정수

인라인 실행 칸에는 입력 상자가 없으니, 문자열에서 읽는 sscanf로 같은 변환 명세를 연습합니다. (scanf의 키보드 대신 첫 인자의 문자열에서 읽을 뿐, 나머지는 동일합니다.)

이 예제 실행

실행 결과가 여기에 표시됩니다.

실제 키보드 입력 형식은 이렇게 씁니다(실행은 맨 아래 종합 실습·「코드연습」 탭에서):

int a;
long long b;
scanf("%d %lld", &a, &b);   /* 예: 1234 1234567890 */

교재는 scanf를 쓰기 전에 #pragma warning(disable:4996)를 넣습니다. 그건 Visual Studio 전용입니다. 이 사이트(GCC/clang)에서는 필요 없습니다.

3.2 getchar — 문자 1개 입력

  • 형식: ch = getchar(); — 괄호 안에 인자가 없습니다.
  • 문자 하나를 읽어 정수(int)로 반환합니다. 입력 끝(EOF)을 구분해야 하므로 저장 변수는 int로 두는 것이 안전합니다.
  • 문자 입력 후 엔터를 눌러야 전달됩니다.

키보드로 받은 문자를 그대로 되돌려 찍는 예입니다(입력이 필요하므로 「코드연습」 탭에서):

int c;
while ((c = getchar()) != EOF)
    putchar(c);

3.3 gets / fgets — 문자열 입력

  • 교재 형식: gets(변수); — 엔터까지(공백 포함) 한 줄을 읽어 배열에 저장하고 끝에 \0을 붙입니다.
  • 문제: 입력 길이를 검사하지 않아 배열 크기를 넘겨 씁니다(버퍼 오버런). gets는 C11 표준에서 삭제되었고, 최신 컴파일러는 경고하거나 아예 제공하지 않습니다.
  • 대안: fgets(s, 크기, stdin) — 최대 크기 - 1자만 읽어 안전합니다. (끝의 개행문자 \n도 함께 저장될 수 있어, 필요하면 잘라냅니다.)

scanf("%s")와 gets/fgets의 결정적 차이는 공백 처리입니다. scanf("%s")는 공백에서 멈추고, 한 줄 전체를 읽지 못합니다.

이 예제 실행

실행 결과가 여기에 표시됩니다.

4. 교재 예제와 이 사이트가 다른 점

교재에서 자주 보임이 사이트이유
void main()int main(void)표준 권장 형태 (1·2강과 동일)
gets(s)fgets(s, n, stdin)gets는 C11에서 삭제·위험. 최신 컴파일러 미지원
scanf 앞 #pragma warning(disable:4996)불필요Visual Studio 전용 경고. GCC/clang은 그대로 컴파일
출력에 %lf%f표준에서 printf는 float/double 모두 %f. %lf는 scanf의 double용
지수 %e → e+003e+03지수 자릿수는 플랫폼마다 다름(Windows는 3자리)
본문 예제에서 키보드 scanf본문은 sscanf로 결과 확인인라인 실행 칸에 입력 상자가 없음. 실제 입력은 아래 종합 실습·「코드연습」

5. 지금 실습할 것

아래 종합 실습은 입력 상자가 있는 실행 칸입니다. 「표준 입력」 칸에 예: 25 3.5 K seoul 을 넣고 실행하세요. (비워 두면 기본값으로 동작합니다.)

  1. 그대로 실행해 각 변환기호(%d %o %x %f %.2f %e %c %s) 결과 확인
  2. %5d를 %-5d, %05d로 바꿔 정렬·채움 비교
  3. %8.2f의 너비·정밀도 숫자를 바꿔 보기
  4. 「표준 입력」의 마지막 값을 Computer Science로 바꿔 %s가 공백에서 끊기는지 관찰
  5. scanf의 " %c"에서 앞 공백을 지우면 grade에 무엇이 들어오는지 확인
  6. puts(city)와 printf("%s", city)의 개행 차이 확인

printf 형식 요약: %d 정수, %ld/%lld long, %u/%o/%x 부호 없는 10·8·16진, %f/%.2f/%e 실수, %c 문자, %s 문자열, %%는 % 자체. scanf는 double에 %lf, 변수 앞에 &(문자열/배열명은 생략).

코드 실습 (C)

실행 결과가 여기에 표시됩니다.

확인 퀴즈

1. C의 표준 입출력 함수(printf, scanf 등)의 선언이 들어 있는 헤더는?
2. C에서 printf, scanf 같은 표준 함수를 쓸 수 있는 이유로 가장 알맞은 것은?
3. 출력 양식에서 % 문자 자체를 화면에 찍으려면?
4. int 변수 n에 값을 입력할 때 올바른 scanf 형태는?
5. double 변수를 scanf로 입력받을 때 쓰는 변환기호는?
6. printf("|%-5d|", 42); 의 출력은?
7. scanf("%s", s); 로 "Hello World"를 입력하면 s에 저장되는 값은?
8. gets() 함수를 쓰지 말아야 하는 가장 큰 이유는?
9. puts(s)와 printf("%s", s)의 차이로 알맞은 것은?

스스로 점검