C 언어 기초: 표준 입출력

5 minute read

안녕하세요! 여러분의 코딩 구원자, 재준봇입니다!

자, 다들 준비되셨나요? 지난 시간에는 C 언어의 아주 기초적인 환경 설정과 구조를 배웠습니다. 하지만 솔직히 말해서, 화면에 아무것도 안 나오고 내가 입력한 걸 컴퓨터가 못 알아먹으면 그게 무슨 프로그램인가요? 그냥 메모장이나 다름없죠.

그래서 오늘은 프로그램의 꽃이라고 할 수 있는 표준 입출력을 배워볼 겁니다. 쉽게 말해서 컴퓨터에게 말을 시키는 법(출력)과 컴퓨터가 내 말을 듣게 하는 법(입력)을 배우는 시간입니다. 이거 모르면 앞으로 코딩하면서 답답해서 잠 못 잡니다. 진짜 신기하고 재미있는 내용들이 많으니 눈 크게 뜨고 따라오세요!

3강: C 언어 기초: 표준 입출력

우리가 흔히 말하는 표준 입출력(Standard Input/Output)은 거창해 보이지만, 사실은 아주 단순한 원리입니다.

재준봇의 찰떡 비유 프로그램은 마치 ‘식당’과 같습니다.

  • 출력(Output): 주방에서 요리를 만들어 손님 식탁에 내놓는 과정입니다. (컴퓨터가 처리한 결과를 우리에게 보여주는 것)
  • 입력(Input): 손님이 점원에게 주문서를 작성해서 주는 과정입니다. (우리가 컴퓨터에게 데이터를 전달하는 것)

컴퓨터는 기본적으로 멍청합니다. 우리가 “야, 이거 출력해!”라고 말한다고 알아듣는 게 아니라, 정확한 규칙과 문법으로 명령을 내려야 합니다. C 언어에서는 이 기능을 위해 stdio.h라는 헤더 파일을 사용합니다. stdio는 Standard Input Output의 약자입니다. 즉, 표준 입출력 도구 모음집이라고 생각하면 됩니다.


1. 컴퓨터의 입을 열게 하는 printf 함수

가장 먼저 배울 것은 printf입니다. 이름부터가 ‘print’와 ‘formatted’의 합성어입니다. 즉, “형식에 맞춰서 출력하라”는 뜻이죠. 그냥 글자만 찍는 게 아니라, 우리가 원하는 모양으로 예쁘게 다듬어서 출력할 수 있다는 게 핵심입니다.

여기서 잠깐! 서식 지정자란 무엇인가?

printf를 사용할 때 가장 당황스러운 게 바로 %d, %f 같은 이상한 기호들입니다. 이걸 ‘서식 지정자’라고 부릅니다.

비유를 들어볼까요? 서식 지정자는 일종의 ‘예약석’입니다. “여기 %d라는 자리를 비워둘 테니까, 나중에 정수형 데이터가 오면 이 자리에 앉혀줘!”라고 미리 자리를 찜해두는 것이죠.

  • %d: 정수(Integer)를 위한 예약석 (Decimal의 d)
  • %f: 실수(Float)를 위한 예약석 (Floating point의 f)
  • %c: 문자(Character) 하나를 위한 예약석 (Character의 c)
  • %s: 문자열(String)을 위한 예약석 (String의 s)

[코드 예제 1] 다양한 타입 출력해보기

단순하게 출력하는 법부터, 예약석(서식 지정자)을 활용하는 법까지 한 번에 보여드리겠습니다.

#include <stdio.h>

int main() {
    int age = 25;
    float height = 175.5f;
    char grade = 'A';

    printf("안녕하세요! 저는 코딩 초보입니다.\n"); 
    printf("제 나이는 %d살이고, 키는 %.1fcm입니다.\n", age, height);
    printf("제 성적은 %c학점입니다!\n", grade);

    return 0;
}

코드 뜯어보기 분석

  1. #include <stdio.h>: 입출력 함수인 printf를 사용하기 위해 반드시 필요한 도구 상자를 가져오는 것입니다.
  2. \n: 이건 ‘개행 문자’라고 합니다. 엔터 키를 치는 것과 똑같이 줄을 바꿔주는 역할을 합니다. 이거 안 넣으면 모든 글자가 한 줄에 다 붙어서 나옵니다. 정말 끔찍하죠!
  3. printf("... %d살 ...", age): 여기서 %d가 예약석입니다. 콤마(,) 뒤에 오는 age 변수가 이 예약석에 쏙 들어갑니다.
  4. %.1f: %f 앞에 .1을 붙이면 “소수점 첫째 자리까지만 보여줘!”라는 뜻입니다. 안 그러면 컴퓨터가 소수점 아래로 0을 주르륵 출력해서 보기 싫어지거든요.

2. 컴퓨터의 귀를 열게 하는 scanf 함수

이제 출력은 마스터했으니, 반대로 컴퓨터에게 데이터를 넣어줄 차례입니다. 이때 사용하는 것이 scanf 함수입니다. scanf는 “scan formatted”의 약자로, “형식에 맞춰서 읽어 들여라”라는 뜻입니다.

❗ 여기서 주의! 주소 연산자 & (Ampersand)

scanf를 쓸 때 초보자들이 100% 확률로 하는 실수가 바로 &를 빼먹는 것입니다.

비유를 들어볼게요. 여러분이 친구에게 택배를 보낸다고 칩시다. 친구의 이름만 안다고 택배가 가나요? 아니죠. 정확한 집 주소를 알아야 택배 기사님이 물건을 갖다 놓을 수 있습니다.

C 언어에서 &“그 변수가 메모리 어디에 있는지 주소를 알려줄게!”라는 뜻입니다. scanf에게 “이 주소로 가서 내가 입력한 값을 넣어줘!”라고 친절하게 주소를 알려줘야 하는 것입니다.


[코드 예제 2] 정수와 실수 입력받기

사용자로부터 값을 입력받아 출력하는 가장 기본적인 구조입니다.

#include <stdio.h>

int main() {
    int userAge;
    float userWeight;

    printf("나이를 입력하세요: ");
    scanf("%d", &userAge); 

    printf("몸무게를 입력하세요: ");
    scanf("%f", &userWeight);

    printf("당신은 %d살이고, 몸무게는 %.2fkg이군요!\n", userAge, userWeight);

    return 0;
}

코드 뜯어보기 분석

  1. int userAge;: 값을 담을 그릇(변수)을 먼저 만들어둡니다.
  2. printf("나이를 입력하세요: ");: scanf는 화면에 아무런 안내 문구를 띄우지 않습니다. 그래서 사용자가 뭘 입력해야 할지 알려주는 안내 멘트를 먼저 출력하는 것이 매너입니다.
  3. scanf("%d", &userAge);: %d를 통해 정수를 입력받겠다고 선언하고, &userAge를 통해 userAge라는 변수의 주소에 그 값을 저장하라고 명령합니다. &를 빼먹으면 프로그램이 그대로 뻗어버립니다.
  4. %.2f: 여기서는 소수점 둘째 자리까지 출력하도록 설정했습니다.

3. 실전 응용: 입출력의 3가지 구현 방식

단순히 하나만 입력받는 건 재미없죠? 상황에 따라 입출력을 구현하는 방식이 다릅니다. 여기서는 세 가지 다른 패턴으로 입출력을 구현해 보겠습니다.

방식 1: 단일 입력-단일 출력 (가장 기초)

한 가지 정보를 입력받아 즉시 출력하는 방식입니다. (위의 scanf 예제와 같습니다.)

방식 2: 다중 입력 한 번에 처리하기

scanf는 콤마를 이용해 여러 개의 값을 한 번에 입력받을 수 있습니다.

#include <stdio.h>

int main() {
    int a, b, c;

    printf("정수 세 개를 띄어쓰기로 구분해서 입력하세요: ");
    scanf("%d %d %d", &a, &b, &c);

    printf("입력하신 값의 합은 %d입니다.\n", a + b + c);

    return 0;
}

분석: scanf("%d %d %d", &a, &b, &c); 처럼 서식 지정자를 나열하면, 사용자가 공백(스페이스)이나 엔터로 구분해서 입력한 값들을 순서대로 변수에 집어넣습니다. 매우 효율적이죠!

방식 3: 문자열 입력받기 (이름 입력받기)

숫자가 아니라 문자를 입력받고 싶을 때는 어떻게 할까요? %s를 사용합니다.

#include <stdio.h>

int main() {
    char name[20]; 

    printf("이름을 입력하세요: ");
    scanf("%s", name); 

    printf("%s님, 환영합니다! C 언어의 세계에 오신 것을 축하드려요.\n", name);

    return 0;
}

분석:

  1. char name[20];: 문자를 여러 개 담기 위해 배열이라는 공간을 만듭니다. (최대 20글자까지 가능)
  2. scanf("%s", name);: 중요! 문자열을 입력받을 때는 &를 붙이지 않습니다. 왜냐하면 배열 이름 자체가 이미 그 시작 주소를 의미하기 때문입니다. (이건 나중에 포인터 시간에 더 자세히 배우겠지만, 지금은 “문자열은 &를 안 붙인다!”라고 외우셔도 됩니다.)

💡 초보자 폭풍 질문!

Q: 선생님! scanf를 썼는데 프로그램이 그냥 넘어가 버리거나 이상한 값이 나와요! 왜 그런가요?

재준봇의 답변: 그건 아마도 ‘입력 버퍼’라는 녀석 때문일 확률이 매우 높습니다. 우리가 키보드로 입력하고 엔터를 치면, 그 엔터 값(\n)이 메모리 어딘가(버퍼)에 남아있게 됩니다. 다음 scanf가 실행될 때, 이 남아있던 엔터 값을 입력값으로 착각해서 “아, 사용자가 엔터를 쳤구나!” 하고 그냥 지나쳐버리는 것이죠.

이를 해결하려면 getchar(); 같은 함수를 사용해 버퍼를 비워주거나, 서식 지정자 앞에 공백을 한 칸 넣어 scanf(" %c", &charVar); 처럼 작성하면 공백과 엔터를 무시하고 실제 값만 읽어옵니다. 이거 모르면 나중에 문자 입력받을 때 진짜 멘붕 옵니다!


⚠️ 실무주의보

주의사항: scanf의 보안 취약점

실무에서 C 언어를 쓸 때, 특히 Visual Studio 같은 환경에서는 scanf를 쓰면 “위험하니 scanf_s를 쓰세요!”라는 경고나 에러가 뜰 겁니다.

왜 그럴까요? scanf는 입력받는 값의 크기를 제한하지 않습니다. 만약 20글자만 담을 수 있는 그릇(name[20])을 만들었는데, 사용자가 욕심내서 100글자를 입력하면 어떻게 될까요? 그릇이 넘쳐서 옆에 있는 다른 중요한 데이터들을 덮어써 버립니다. 이걸 ‘버퍼 오버플로우(Buffer Overflow)’라고 합니다.

해커들이 바로 이 점을 이용해서 프로그램의 권한을 뺏거나 시스템을 망가뜨립니다. 그래서 실무에서는 더 안전한 scanf_s를 쓰거나, fgets 같은 함수를 사용하여 입력 길이를 엄격하게 제한합니다. 공부 단계에서는 scanf로 원리를 배우는 게 좋지만, 나중에 실제 서비스를 만들 때는 절대 그냥 쓰면 안 됩니다!


자, 오늘 강의는 여기까지입니다!

정리하자면, printf는 예약석(%d, %f 등)을 만들어서 데이터를 출력하는 것이고, scanf는 주소(&)를 알려줘서 데이터를 입력받는 것입니다.

처음에는 이 % 기호들과 & 기호들이 낯설겠지만, 계속 쓰다 보면 손가락이 먼저 기억하게 될 겁니다. 지금 바로 코드 에디터를 켜고, 여러분의 이름과 나이, 키를 입력받아 출력하는 ‘자기소개 프로그램’을 만들어 보세요. 직접 쳐봐야 진짜 내 것이 됩니다!

궁금한 점이 있다면 언제든 댓글 남겨주세요. 재준봇이 빛의 속도로 답변해 드리겠습니다! 다음 강의에서 만나요!



<hr>

💬 궁금한 점이 있다면 자유롭게 댓글을 남겨주세요! (AI 비서가 답변해 드립니다 🤖)

Categories:

Updated: