8. 사용자로부터 얻은 정보를 변수에 저장하기

  • 23 minutes to read

프로그램을 실행할 때마다 서로 다른 값을 입력 받으려면 콘솔에서 입력한 값을 변수에 저장할 수 있어야 합니다. 키보드로부터 입력을 받고 모니터로 출력을 하는 일반적인 내용을 표준 입출력(standard input/output)이라고 합니다.

8장 한 줄 정의

> // scanf() 함수 등으로 콘솔(터미널)로부터 데이터 입력 받기 

scanf() 함수 미리보기 예제 코드

코드: scanf.c

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>

int main(void)
{
   int num;
   scanf("%d", &num); 
   printf("%d\n", num);
   return 0;
}
1234 (엔터)
1234

8.1. 데이터 입력 관련 함수

지금까지 콘솔에 데이터를 출력할 때에는 printf() 함수를 사용해 왔습니다. 콘솔에서 사용자로부터 데이터를 입력 받고자 할 때에는 다음과 같은 함수가 주로 사용됩니다.

표: 입력 관련 함수

함수 설명
scanf() 콘솔로부터 여러 형태의 서식을 사용하여 데이터를 입력 받습니다. 엔터키를 누를 때까지 대기합니다.
getch() 콘솔로부터 한 문자를 정수로 입력 받습니다.
gets() 콘솔로부터 문자열을 입력받습니다.

우리가 가장 많이 사용할 scanf() 함수는 콘솔에 대기하고 있다가 사용자가 데이터 입력한 후 엔터키를 누르면 해당 데이터를 입력 받아서 그 결괏값을 변수에 저장해줍니다.

scanf() 함수의 가장 기본적인 모양입니다.

  • scanf("서식 지정자", &변수, …);
    • int scanf(char const * const _Format, …);
    • 값 가져오기가 성공하면 개수를 int로 반환하고 실패하면 EOF(-1)을 반환합니다.
      • EOF는 End of File의 의미를 갖습니다.

scanf() 함수의 서식 지정자는 printf()와 비슷합니다.

표: scanf() 함수 서식 지정자

서식 지정자 설명
%d 부호 있는 정수
%u 부호 없는 정수
%c 문자 하나
%s 문자열
%f 실수(float)
%lf 실수(double)
%Lf 실수(long double)
%e 실수(지수 형식)
%x 16진수
%o 8진수

8.2. 콘솔로부터 정수 하나를 입력 받아 출력하기

scanf() 함수를 사용하여 콘솔로부터 정수 하나를 입력 받아 출력하는 프로그램을 작성하겠습니다.

코드: input_integer_.c

// input_integer.c 
//[?] 표준 입력인 콘솔로부터 정수 하나를 입력 받아 출력하는 프로그램 
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    int num = 0; // 정수 타입의 변수 준비 
    int _ = 0; // 버림(Discards): scanf 함수의 결괏값을 담을 임시 변수

    printf("정수 하나를 입력하세요: "); // 프롬프트(prompt, 안내 메시지) 출력 
    _ = scanf("%d", &num); // 표준 입력을 통해서 하나의 정수를 받아 num 변수에 저장

    printf("%d\n", num); // num 변수의 값을 표준 출력을 통해서 출력 

    return 0;
}
정수 하나를 입력하세요: -1234
-1234

코드: ScanFormat.c

#define _CRT_SECURE_NO_WARNINGS // scanf() 보안 경고에 따른 컴파일 에러 방지
#include <stdio.h>

int main()
{
	int num;
	int r; 

	printf("정수 하나를 입력하세요. _\b");

	r = scanf("%d", &num);

	printf("%d개 입력됨: %d\n", r, num);

	return 0; 
}

참고: #define _CRT_SECURE_NO_WARNINGS

#define _CRT_SECURE_NO_WARNINGS 코드 없이 scanf() 함수를 사용하면 다음과 같이 컴파일 에러가 발생합니다. (물론, 이 구문은 Windows 운영체제의 Visual Studio 사용 환경에서만 넣으면 됩니다.)

'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.

scanf 대신에 scanf_s를 사용하라고 나옵니다. scanf_s 함수는 C 언어 표준 함수가 아닌 Visual Studio 전용입니다. 그래서 박용준 강사의 강의에서는 scanf를 기준으로 사용합니다.

CAUTION

#define 지시문은 반드시 #include 지시문보다 먼저 선언되어야 합니다.

8.3 표준 입력으로 정수 두 개 입력 받아 출력하기

이번에는 공백을 구분으로 두 개의 정수를 입력 받아 출력하겠습니다.

***코드: input_two_integer_.c ***

// input_two_integer.c 
//[?] 표준 입력인 콘솔로부터 두 개의 정수를 입력 받아 출력하는 프로그램 
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    int one, two, _;

    printf("정수 두 개를 공백으로 구분해서 입력하세요: ");
    _ = scanf("%d %d", &one, &two); // 2개의 정수를 입력 받아 각각의 변수에 저장

    printf("%d %d\n", one, two); // 입력된 내용 출력 

    return 0;
}
정수 두 개를 공백으로 구분해서 입력하세요: 3 8
3 8

8.4 부호 없는 정수 입력

이번에는 부호 없는 정수를 입력 받겠습니다.

부호 없는 정수 입력 관련 서식 지정자는 다음 표와 같습니다.

표: 부호 없는 정수 서식 지정자

서식 지정자 설명
%u 부호 없는 정수(unsigned)
%lu 부호 없는 long 정수
%llu 부호 없는 long long 정수

코드: input_unsigned_integer.c

// input_unsigned_integer.c 
//[?] 표준 입력인 콘솔로부터 나이를 정수로 입력 받아 출력하는 프로그램 
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    unsigned int age;
    int _; // 버림(Discards) 

    printf("나이를 입력하세요: "); // 프롬프트(Prompt, 안내 메시지)
    _ = scanf("%u", &age); // %u 서식 지정자로 부호없는 정수 입력 받기 

    printf("나이: %d\n", age); // 입력된 값 출력 

    return 0;
}
나이를 입력하세요: 20
나이: 20

실수 데이터 입력

실수 데이터 타입을 scanf로 입력 받겠습니다. printf에서는 %ffloat, double에 대해서 썼는데요. scanf에서는 float%f, double%lf, long double%Lf를 사용합니다.

IMPORTANT

실수 데이터 타입을 scanf로 입력받을 때에는 printf와 달리 double 타입은 반드시 %lf를 사용해야 합니다.

  • float: %f
  • double: %lf
  • long double: %Lf

코드: input_real_number.c

#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    float num1;
    double num2;
    long double num3;

    // 서식 지정자(float(%f), double(%lf), long double(%Lf)) 
    scanf("%f %lf %Lf", &num1, &num2, &num3);

    printf("%.15f\n%.15lf\n%.15Lf\n", num1, num2, num3);

    return 0;
}
3.14 3.14 3.14
3.140000104904175
3.140000000000000
3.140000000000000

float는 정밀도가 낮아서 유효자릿수 7개 이후에는 오차가 발생합니다. 기본값인 double이나 long double은 정밀도가 높아서 유효자릿수 16개 이후에는 오차가 발생합니다.

8.5 scanf를 엔터키를 기준으로 여러 행으로 값을 입력 받기

scanf() 함수를 사용하여 엔터키를 기준으로 여러 행으로 데이터를 입력받을 때, 엔터키가 다음 행에 영향을 주는 경우가 있습니다. 단순히 Windows 환경에서만 사용한다면 fflush(stdin); 코드를 scanf() 함수 사용 다음 라인에 넣어주던 방식도 있었는데요. 이것은 리눅스에서는 실행되지 않습니다. 그래서 여러 가지 해결책이 있는데요. 그 중에서 하나는 scanf() 함수의 서식 지정자 앞에 공백 한 칸을 두어 공백과 엔터를 무시한 문자열만 입력을 받을 수 있도록 할 수 있습니다.

코드: scanf_multi_line.c

// scanf_multi_line.c
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    char name[20];
    int age;
    char nick[20];
    int _;

    printf("입력\n----\n");
    printf("이름: "); _ = scanf(" %s", name); // 서식 지정자 앞에 공백 하나 추가 
    printf("나이: "); _ = scanf(" %d", &age);
    printf("별명: "); _ = scanf(" %s", nick);

    printf("\n출력\n----\n");
    printf("이름: %s\n", name);
    printf("나이: %d\n", age);
    printf("별명: %s\n", nick);

    return 0;
}
입력
----
이름: 박용준
나이: 21
별명: 레드플러스

출력
----
이름: 박용준
나이: 21
별명: 레드플러스

8.6 콘솔로부터 이름을 입력받아 출력하는 프로그램

scanf()함수를 사용하여 문자열 값을 입력 받아 저장 후 사용해보겠습니다.

https://youtu.be/iHUARpv8fmE

코드: input_name_.c

// input_name_.c
// 예제: 콘솔로부터 이름을 입력받아 출력하는 프로그램   
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    char name[20]; // 문자의 배열 => 문자열을 담을 수 있는 그릇 
    int _; // 버림

    //[1] 입력
    printf("이름을 입력하세요: ");
    _ = scanf("%s", name); // 문자열은 %s 서식 지정자로 받기 

    //[2] 출력
    printf("안녕하세요. %s님.", name); // 배열은 이름만 지정하고 & 기호 생략

    return 0;
}
이름을 입력하세요: 홍길동
안녕하세요. 홍길동님.

[1]번 입력 코드의 scanf() 함수는 %s 서식 지정자를 사용하여 콘솔로부터 엔터키를 누를 때까지의 문자열을 입력 받는 기능을 제공합니다. char 형 배열인 name에는 scanf() 함수에 의해서 입력한 문자열이 저장됩니다. [2]번 출력 코드는 printf() 함수의 %s 서식 지정자로 단순히 화면에 name 문자열을 출력하는 역할을 합니다.

8.7 scanf() 함수로 영문자 하나를 입력 받기

scanf() 함수의 %c 서식 지정자를 사용하면 키보드로부터 문자 하나를 입력 받을 수 있습니다. 입력 값을 printf() 함수에서 %c를 사용하여 출력하면 문자가 출력되고, %d를 사용하여 출력하면 문자에 해당하는 아키스코드 숫자가 출력됩니다.

코드: input_character.c

// input_character.c
// 예제: 콘솔로부터 영문자 하나를 입력받아 출력하는 프로그램   
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지 
#include <stdio.h>

int main(void)
{
    char c;

    //[1] 콘솔로부터 문자 하나를 입력 후 엔터키를 누릅니다. 
    int _ = scanf("%c", &c);

    //[2] 대문자 'A'가 입력되면 'A'에 해당하는 정수 값인 65가 출력됩니다.
    printf("%c(%d)", c, c); // %c로 문자 출력, %d로 아스키코드 출력 

    return 0;
}
A
A(65)

만약 'A'를 입력하면 아스키코드에 의해서 65가 저장됩니다. 다시 65에 해당하는 문자를 표현하려면 %c를 사용해서 출력합니다.

https://youtu.be/rI7niU_l8OE

8.8 하나의 문자 입력 받고 하나의 문자 출력하기

표준 입력으로부터 문자 하나를 입력받을 때에는 getchar() 함수를 사용하고 표준 출력으로 문자 하나를 출력할 때에는 putchar() 함수를 사용합니다.

코드: getchar_putchar.c

#include <stdio.h> // getchar(), putchar() 

int main(void)
{
    char c; 

    //[1] 표준 입력으로부터 문자 하나 입력: getchar()
    c = getchar(); 

    //[2] 표준 출력으로 문자 하나 출력: putchar()
    putchar(c);

    putchar('\n');

    return 0;
}
Z
Z

8.9 getchar() 함수로 문자 하나 입력 받기

사용자로부터 문자 하나를 입력받을 때에 getchar() 함수를 사용할 수 있습니다. 일반적으로 C 언어에서 문자 하나는 int 형식으로 처리됩니다. 다음 코드를 작성 후 실행해보세요.

코드: getchar_function.c, GetCharFunctionDemo.c

#include <stdio.h>

int main(void)
{
    int c;

    printf("문자 하나 입력: _\b");
    c = getchar();

    printf("입력한 문자: %c\n", c);

    return 0;
}
문자 하나 입력: Y
입력한 문자: Y

getchar() 함수로 입력 받은 문자 하나를 int 형식 변수에 저장하고 printf() 함수에서 %c 자리 표시자를 사용하여 출력하면 입력한 문자 하나가 정상적으로 출력됩니다.

8.10 _getch() 함수로 콘솔로부터 문자 하나 바로 입력받기

코드: getch_function.c

// getch_function.c
// getch(), _getch(): 키보드로부터 하나의 문자 입력
#include <stdio.h>

int main(void)
{
	char grade;

	printf("C 언어 프로그래밍 학점: _\b");

	grade = _getch();

	printf("\n%c 학점입니다.\n", grade);

	return 0;
}
C 언어 프로그래밍 학점: _
A 학점입니다.

8.11 getchar() 함수로 키보드로부터 하나의 문자 입력받기

코드: getchar_demo.c

// getchar_demo.c
// getchar() 함수: 키보드로부터 하나의 문자 입력
#include <stdio.h> // getchar()

int main()
{
    char blood_type;

    printf("당신의 혈액형은? _\b");
    blood_type = getchar();

    printf("%c형입니다.\n", blood_type);

    return 0;
}
당신의 혈액형은? O
O형입니다.

8.12 한 줄 입력 받고 한 줄 출력하기

코드: gets_puts.c

//[?] 한 줄의 문자열을 입력받고 출력하는 함수: gets(), puts() 
#include <stdio.h>

int main(void)
{
    char buffer[80] = { NULL }; // 문자열 저장할 공간 마련

    //[1] 표준 입력으로부터 한 줄 입력받기: gets()
    gets(buffer);

    //[2] 표준 출력으로 문자열 출력: puts()
    puts(buffer);

    return 0;
}
C Language
C Language

8.13 형식 변환(Type Conversion)

같은 형식의 데이터들끼리는 따로 형식 변환이 필요없이 그대로 값이 대입됩니다.

> int num1 = 1234; // 정수 1234를 number1 변수에 저장
> int num2 = num1; // number1의 값을 다시 number2 변수에 저장 
> num2
1234

형식 변환은 크게 두가지로 분류할 수 있는데요. 암묵적(묵시적;Implicit)인 형 변환과 명시적(Explicit)인 형 변환이 있습니다. 암묵적인 형 변환은 숫자 형식 중 int 형식은 그보다 더 큰 long long 형식 변수에 그대로 담을 수 있습니다.

> int num1 = 1234; // 정수 1234를 number1 변수에 저장
> long long num2 = num1; // number1의 값을 그 보다 큰 long 형식 변수인 number2에 저장
> num2
1234

만약, long 형식의 변수를 int 형식의 변수에 저장하려면 명시적으로 (int)를 붙여서 long을 int로 변경할 수 있습니다. 단, 이러한 경우에는 데이터의 손실이 발생하여 엉뚱한 데이터가 저장될 수 있습니다.

> // int <- (int)long;
> long long num1 = 1234; // 정수 1234를 long 형식 변수인 number1에 저장
> int num2 = (int)num1; // long 형식의 변수를 int 형식의 변수로 변환해서 저장
> num2
1234

8.14 char 형식을 int 형식으로 형식 변환

C 언어에서는 char 형식의 데이터를 int 형식으로 바로 변환이 됩니다. 다음 샘플 코드를 실행해보면 대문자 A에 해당하는 아스키코드 값인 65가 i 변수에 저장됩니다.

코드: char_to_int.c

// char_to_int.c
#include <stdio.h>

int main(void)
{
	char c = 'A';
	int i = c; // char 타입을 int 타입으로 변환

	printf("%d\n", i); // 65

	return 0;
}
65

8.15 gets()과 atoi() 함수로 정수 입력받기

scanf() 함수로도 숫자값을 입력받을 수 있지만, 연속해서 숫자를 입력하고 엔터키를 누르는 경우에는 gets() 함수와 atoi() 함수를 사용해서 문자열로 입력받고 이를 다시 정수형으로 변환해서 출력하는 경우도 있습니다. 이러한 경우에는 다음 코드와 같이 처리할 수 있습니다.

코드: get_number.c

// get_number.c
#include <stdio.h>

int main(void)
{
    int number1 = 0;
    int number2 = 0;
    char buffer[80];

    printf("첫 번째 숫자 입력: "); gets(buffer); number1 = atoi(buffer);
    printf("입력한 숫자는 %d입니다.\n", number1);

    printf("두 번째 숫자 입력: "); gets(buffer); number2 = atoi(buffer);
    printf("입력한 숫자는 %d입니다.\n", number2);

    return 0;
}
첫 번째 숫자 입력: 1234
입력한 숫자는 1234입니다.
두 번째 숫자 입력: 2345
입력한 숫자는 2345입니다.

8.16 예제: 사각형의 넓이 구하기

C 언어로 사각형의 넓이를 구하는 예제입니다. 사용자로부터 밑변과 높이를 입력받아 사각형의 넓이를 구합니다.

코드: rectangle_area.c

// rectangle_area.c
// C 언어 코드 샘플 - 사각형의 넓이 구하기 - 사각형의 넓이는 밑변 곱하기 높이
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    // 변수 선언 및 초기화 
    double width = 0.0; // 밑변
    double height = 0.0; // 높이
    double area = 0.0; // 넓이
    int _ = 0; // 버림(Discards)

    // 사용자로부터 데이터 입력
    printf("밑변: "); _ = scanf("%lf", &width);
    printf("높이: "); _ = scanf("%lf", &height);

    // 처리
    area = width * height;

    // 출력 
    printf("사각형의 넓이: %.2lf\n", area);

    return 0;
}
밑변: 10
높이: 20
사각형의 넓이: 200.00

원의 넓이와 둘레 구하기

이번에는 C 언어로 원의 넓이와 둘레를 구하는 예제 코드에 대해 간단히 설명해보겠습니다.

코드: 예제_원의넓이와둘레길이.c, example_calculate_area_circumference_of_circle.c

/*
	예제_원의넓이와둘레길이.c
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// 상수 선언: PI = 3.141592654...
#define PI 3.141592654f

int main(void)
{
	// 변수 선언
	float r;

	// 사용자로부터 반지름 입력
	printf("반지름: ");
	scanf("%f", &r);

	// 처리 및 출력
	printf("원의 넓이: %f\n", (r * r * PI));
	printf("원의 둘레 길이: %f\n", (2 * r * PI));

	return 0;
}

위 코드에서는 먼저, 상수 PI를 3.141592654...로 정의하고, 사용자로부터 반지름을 입력받습니다. 그리고 원의 넓이와 둘레 길이를 계산하여 출력합니다.

원의 넓이는 반지름의 제곱에 상수 PI를 곱한 값입니다. 원의 둘레 길이는 반지름에 2를 곱한 후 상수 PI를 곱한 값입니다.

위 코드를 실행하면, 다음과 같은 결과가 출력됩니다.

반지름: 5
원의 넓이: 78.539818
원의 둘레 길이: 31.415927

위 결과에서는 반지름이 5인 원의 넓이가 약 78.54이고, 둘레 길이가 약 31.42임을 확인할 수 있습니다.

이렇듯 C 언어를 이용하여 간단한 수식을 계산하여 출력하는 것은 매우 간단하고 기본적인 프로그래밍 방법 중 하나입니다. 이러한 예제를 기반으로 다양한 기능을 추가하고, 활용하여 더 복잡한 프로그램을 만들어 낼 수 있습니다.

8.17 형식 변환 오차 주의

float 타입은 오차를 허용합니다. 그래서 우리가 생각하는 결과가 나오지 않을 수 있음을 주의해야 합니다.

코드: decimal_part.c

#include <stdio.h>

int main(void)
{
    float money = 88.99;

    printf("전체: %.2f\n", money); // 88.99
    printf("소수부: %d\n", (int)((money - (int)money) * 100)); // 98
    printf("소수부: %d\n", (int)((money - (int)money) * 1000000)); // 989997

    return 0;
}
전체: 88.99
소수부: 98
소수부: 989997

미리보기: scanf()로 문자열 입력 받기

  • scanf("%s", 문자열저장공간);

  • 공백을 포함한 한 줄 입력 서식: %[^\n]s

VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com