문자 입력 받기
지난번 기록은 잘 이해 되었으면한다
이번 기록에서는 제목에서도 볼 수 있듯이
두 가지 내용을 한꺼번에 배우게 된다.
바로, 문자를 키보드로
부터 입력을 받는 것이지.
문자를 입력 받을 수 있다면,
숫자도 당연히 입력 받을 수 있게 된다.
즉, 이번 강좌에서는 문자 형식의 변수와
키보드로 부터 입력을 받는
입력에 대해 알아 보도록 하겠다.
일단, 컴퓨터에서
문자를 처리하는 방식에
대해 생각해 보도록하자.
우리의 컴퓨터는 그다지 똑똑하지 못하다.
아무리 최신 Intel CPU 를 장착해도
컴퓨터는 단지 0 과 1 만을 처리할 뿐.
따라서, 2 와 3 같은 숫자도 처리하지 못하는데
어떻게 a, b 가, 나, 韓 과
같은 수 많은 문자를 처리할 수 있겠는가?
하지만, 방법이 있다.
이러한 문자들을 숫자에 대응시키는 것입니다.
그런데, 숫자에 대응시킨다면
컴퓨터가 이 것이 숫자인지,
아니면 문자인지 어떻게 알까?
물론 알 방법은 없다.
단지 이 숫자를 ‘문자’ 형태로
사용하거나 ‘숫자’ 형태로 사용하는 것.
문자를 저장하는 변수는
앞에서 살짝 본 적이 있다.
바로 char 이다.
int integer
의
약자였다면 char
은
character 의 약자 다.
변수가 등장하면 어김없이 등장하는
아래의 표를 살펴 보도록 하자.

보시는 것과 같이 char 은 맨 위에
위치해 있으며 크기는 1 바이트.
또한, 이를 통해 나타낼 수 있는
숫자의 범위를 알려주고 있는데,
이는 -128 부터 127 까지, 256 까지 다.
/* 문자를 저장하는 변수 */
#include <stdio.h>
int main(){
char a;
a = 'a';
printf("a 의 값과 들어 있는 문자는? 값 : %d , 문자 : %c \n", a,a);
return 0;
}
위 소스를 성공적으로 컴파일 했다면
char a;
이 부분은 char 형 변수를 선언하는 부분.
기억이 안나시는 분들은 3장으로 되돌아 가보자
a = 'a';
C 컴파일러는 이 a 가 변수 a 라고
착각하여 a 라는 변수의 값을 a 라는
변수에 대입하는 문장으로 인식하게 된다.
따라서 a 에는 아무런 값이
들어있지 않은 쓰레기 값(NULL) 이 되어
나중에 a 라는 문자를 출력해 보았을 때,
이상한 값이 나오게 된다.
문자를 대입하는 것도
숫자를 대입하는 것과 동일.
대입 연산자를 이용하면 된다.
printf("a 의 값과 들어 있는 문자는? 값 : %d , 문자 : %c \n", a, a);
마지막으로,
위 printf 문에 대해 보도록 하겠다.
앞에서 말했듯이 컴퓨터는 a 가
문자라는 것 자체를 모른다고 했다.
단지 우리가 a 를 문자로 보느냐
아니면 숫자를 보느냐에
따라 달라진다고 했는데,
이 말 뜻을 위 printf 문을 보면 알 수 있다.
일단, %d 는 a 의 값을
숫자 (정수인 10 진수) 라고
출력하라는 뜻.
그 옆의 %c 는 아마 예상했겠지만
a 의 값을 문자로 출력하라는 뜻.
따라서, %c 에는 a 에
저장되어 있던 문자 ‘a’ 가 출력되게 된다.
그렇다면 %d 에는 무엇이 출력되었을까?
앞에서 말했지만 컴퓨터는 문자와 숫자를 일대일
대응 시켜서 생각한다고 했다. 따라서,
%d 에 출력되는 숫자가
바로 a 에 대응되는 숫자를 가리킨다.
이 때, 각 문자 마다 대응되는 숫자를
아무렇게나 하는 것이 아니라
일정하게 정해져 있는데
현재 우리가 쓰고 있는
컴퓨터에서는
다음과 같이 정의되어 있다.
위 표는 미국 표준 학회(ASA) 에서
정한 아스키
(ASCII, American Standard
Code for Information Interchange)
코드로8 비트 데이타를 이용하여
여러 문자에 번호를 붙인 것.
아까, a 의 숫자 값을 출력하였을 때
97 이 나왔는데 위 표에서 찾아 보면
a 의 값이 97 임을 볼 수 있다.
이 때, 위 표의 내용이 0 부터 127 까지
밖에 없는 이유는 위 표준을 정할 당시
그 당시 7 비트 만으로 충분하다고
생각했기 때문.
하지만 IBM 에서 좀 더 많은
종류의 문자가 필요하게 되자
1 비트를 더 추가 시켜서
확장된 아스키 코드
(Extended ASCII Code) 를
만들었다.
하지만 위 256 개
가지고는 충분하지 못하다.
왜냐하면 우리 글만 해도
자모음 24 개로 구성되어 있는데,
한 글자당 최대 초성/중성/종성 을
모두 표현해야 합다.
또한 더욱 심각한 것은
한자와 같은 표의문자의
경우 수만 개가 넘는
한자 데이터들을 가지고
있어야 하는데 이를 256 개 안에 다
표현한다는 것은 불가능하기 때문.
따라서, 컴퓨터가 전세계에 보급되자
좀 더 많은 종류의 문자를
표현해야 한다는 필요성이 대두되었다.
결국에는 유니 코드(Unicode) 라는
새로운 형식의 문자 체계를 도입하게 된다.
유니코드는 한 문자를 1 에서 4 바이트까지
다양한 길이로 처리합니다. 이는,
기존 아스키 코드의 체계를 유지하면서,
새로운 문자들을 추가하기 위함이다.
여러분은 아직 유니코드를
직접 다룰 일은 없기 때문에
여기서는 무시하셔도 괜찮다.
scanf 의 도입
/* 섭씨온도를 화시로 바꾸기 */
#include <stdio.h>
int main() {
double celsius; // 섭씨 온도
printf("섭씨 온도를 화씨 온도로 바꿔주는 프로그램 입니다. \n");
printf("섭씨 온도를 입력해 주세요 : ");
scanf("%lf", &celsius); // 섭씨 온도를 입력 받는다.
printf("섭씨 %f 도는 화씨로 %f 도 입니다 \n", celsius, 9 * celsius / 5 + 32);
return 0;
}
위 소스를 성공적으로 컴파일 했다면 아래와 같이 나온다.


위와 같이 섭씨가 화씨 온도로
변경된 값이 출력된다.
와우! 드디어 괜찮은
프로그램을 처음으로 만들어 보게 된 것.
소스 코드를 찬찬히 살펴 보도록
double celsius; // 섭씨 온도
일단, celsius 라는 double 형 변수를 선언하였다.
변수의 이름을 종전의 a , b 에서 celsius 라고
한 이유는 좀 더 이해하기 편하기 때문.
좋은 소스 코드의 조건은 다른 사람이
이해하기 쉬운 소스 코드 이고,
다른 사람이 이해하기 쉬운 소스코드는
기본적으로 변수 이름을 보고도
변수를 한 눈에 파악하기 쉽게 만드는 것.
scanf("%lf", &celsius); // 섭씨 온도를 입력 받는다.
이제, 새로운 것이 등장하였다.
printf 에 이어 등장한 scanf 군.
printf 가 화면에 결과를 출력해 주는
함수였다면, scanf 는 화면(키보드) 로
부터 결과를 받아들이는 입력 함수다.
이렇게 흔히 printf 와
scanf 를 가리켜
입출력함수라 한다. 이 때,
scanf 함수는 우리가
어떠한 입력을 하기
전까지 계속 기다립니다.
또한, 입력을 할 때 엔터를
눌러야지만 입력으로 처리된다.
scanf 와 printf 는
이름도 비수무리 할 뿐더러,
사용하는 방법도 비슷합니다.
printf 에서
각 변수를 출력할
포맷(%d, %f, %c 등) 을 변수마다
다르게 하는 것처럼 scanf 도 각
변수의 타입마다 입력받는
포맷을 달리 해야 한다.
위 경우 처럼
double 형의 변수를
입력 받으려면
%lf (소문자 LF 이다, if 가 아니다)
로 해야 한다.
그런데, printf 보다 조금 까다로운 점은
printf 는 double 이나 float
모두 %f 로 출력하지만
이에 경우 float 은 %f 로 무조건
입력 받아야 한다는 점.
마찬가지로 double 형 변수도
무조건 %lf 로만 입력 받아야 한다.
그 외에도, printf 는 정수형 변수는
모두 %d 로 출력 가능했던
반면에 scanf 는 각 자료형
마다 포맷이 다 정해져 있다.
아래 예제에서 잠시 scanf 의
포맷 들에 대해 정리해 보도록 하겠다
printf("섭씨 %f 도는 화씨로 %f 도 입니다 \n", celsius, 9 * celsius / 5 + 32);
마지막으로 위 프로그램의
중요한 부분을 살펴보자.
바로 이 부분에서 섭씨와 화씨의
환산 작업이 이루어 진다.
참고로, 화씨와 섭씨의
변환 공식은 아래와 같다.
따라서, 이 공식을 그대로
C 언어 수식을 바꾼 것이
9 * celsius / 5 + 32 인 것.
곱셈과 나눗셈의 우선순위가
높으므로 9 * celsius / 5 가
먼저 계산 된 후 32 가 더해지므로
위의 식과 일치한다.
따라서 printf 의 두번째
%f 부분에는 위 계산된
화씨의 값이 들어가게 된다.
/* scanf 총 정리 */
#include <stdio.h>
int main() {
char ch; // 문자
short sh; // 정수
int i;
long lo;
float fl; // 실수
double du;
printf("char 형 변수 입력 : ");
scanf("%c", &ch);
printf("short 형 변수 입력 : ");
scanf("%hd", &sh);
printf("int 형 변수 입력 : ");
scanf("%d", &i);
printf("long 형 변수 입력 : ");
scanf("%ld", &lo);
printf("float 형 변수 입력 : ");
scanf("%f", &fl);
printf("double 형 변수 입력 : ");
scanf("%lf", &du);
printf("char : %c , short : %d , int : %d ", ch, sh, i);
printf("long : %ld , float : %f, double : %f \n", lo, fl, du);
return 0;
}
성공적으로 컴파일 후
(경고가 6 개 정도 나올 수 있는데)
(무시하자(´・ω・`) )
d:\□□□□□_fFF□\□□□g□□□m□□□\F\>test
char 형 변수 입력 : b
short 형 변수 입력 : 1
int 형 변수 입력 : 2
long 형 변수 입력 : 3
float 형 변수 입력 : 4
double 형 변수 입력 : 5
char : b , short : 1 , int : 2 long : 3 , float : 4.000000, double : 5.000000
d:\□□□□□_fFF□\□□□g□□□m□□□\F\>
printf("char 형 변수 입력 : ");
scanf("%c", &ch);
일단, 제일 먼저 문자를 입력 받는 부분을 보도록하자.
예전에도 이야기 했지만 한글은 2 바이트
이상을 차지하기 때문에 최대 1 바이트를
차지하는 char 형 변수인 ch 에
한글을 치면 오류가 생긴다.
이와 같이 허용된 메모리 이상에
데이터를 집어넣어 발생하는
오류를 버퍼 오버플로우(Buffer Overflow)
라고 하며 보안 상 매우 취약하다.
버퍼 오버플로우를 이용해서 공격자들이 프로그램의 정상적인 코드가 아니라, 자신들이 원하는 코드가 실행될 수 있도록 조종할 수 있습니다. |
a
뿐만 아니라 근처의 데이터가 손상됨에 따라 큰 문제가 발생하게 될 수 도 있다. 따라서, 여러분들은 |
a
버퍼 오버플로우가 일어나지 않게 허용된 데이터 이상을 집어넣는지 안집어 넣는지 검사해야 한다. |
a
또한 앞으로 우리가 char 형 변수를
선언할 때 에는 이 사람이 문자를
보관하는 변수를 선언하는 구나 라고
생각하도록 하자. 왜냐하면 보통
정수 데이터를 보관하는 변수로는 int 를 쓰지
char 을 잘 쓰지 않을 뿐더러 char 이름도
character 에서 따왔을 만큼
문자와 무언가 관련이 있기 때문.
printf("short 형 변수 입력 : ");
scanf("%hd", &sh);
printf("int 형 변수 입력 : ");
scanf("%d", &i);
printf("long 형 변수 입력 : ");
scanf("%ld", &lo);
이 부분은 여러분들이 무난하게
이해하실 수 있으리라 본다.
단지 포맷에 %hd, %d, %ld 로 다른 것 뿐.
참고로 short 형이나 long 형은 아직
다루지는 않았지만 int 와
똑같은 계열의 정수형
변수라고 생각하시면 된다.
printf("float 형 변수 입력 : ");
scanf("%f", &fl);
printf("double 형 변수 입력 : ");
scanf("%lf", &du);
마찬가지로 float 형에서는 %f 로,
double 형에서는 %lf 로 사용한다는
것을 기억하도록 하자.
정 리 |
• char 은 1 바이트 정수를 저장하는 타입으로, 주로 문자를 저장하는데 사용됩니다. • 각 문자들은 아스키 테이블이란 표를 통해 특정 정수와 대응되어 있습니다. 예를 들어서 65 는 알파벳 A 와 대응됩니다. • scanf 를 통해 사용자로 부터 데이터를 받을 수 있습니다. • %c 는 문자, %d 는 정수, %f 는 float, %lf 는 double 을 받습니다. |