아스키코드는 사람이 사용하는 기호를 컴퓨터 안에서 표현하는 방법에 대해 약속한 것이다.
예를 들어 소스 파일에 A라는 문자를 사용하면 컴퓨터는 8개의 비트를 01000001과 같은 상태로 저장한다.
또한 컴퓨터에 01000001과 같은 비트 열이 있으면 모니터는 화면에 A라는 문자를 보여준다.
아스키코드는 이처럼 문자를 코드화
하는 것!
<아스키코드 표>
종류 | 문자 상수 | 아스키 코드 값 | 출력할 때 |
---|---|---|---|
숫자 문자(10개) | '0' ~ '9' | 48 ~ 57 | 문자 출력 |
대문자 (26개) | 'A' ~ 'Z' | 65 ~ 90 | 문자 출력 |
소문자(26개) | 'a' ~ 'z' | 97 ~ 122 | 문자 출력 |
특수 문자 (33개) | ' '(공백), '$', '&' ... | 32, 36, 38 ... | 문자 출력 |
제어 문자(33개) | '\0', '\t', '\n', '\r' ... | 0, 9, 10, 13 ... | 제어 기능 수행 |
표를 통해 알 수 있는 아스키 코드 값 특징은
대문자를 소문자로 바꾸는 예제를 풀어보자.
# include <stdio.h> int main() { char small, cap = 'G'; if ((cap >= 'A') && (cap <='Z')) { small = cap + ('a' - 'A'); } printf("대문자: %c %c", cap, '\n'); printf("소문자: %c", small); return 0; }
5행은 문자를 저장하기 위해 char형 변수를 선언하고 초기화 한다.
문자 상수는 4바이트의 크기를 갖지만 아스키 코드 값이 0~127 범위에 있으므로
2진수로 바꾸면
문자 'G' 00000000 00000000 00000000 01000111
왼쪽 3바이트는 모두 0이 되고 오른쪽 1바이트만 의미를 갖는다.
따라서 문자는 1바이트 크기의 char형 변수에 저장해 사용한다.
컴파일러는 문자에서 아스키 코드 값을 갖는 오른쪽 1바이트만 변수에 저장하고 남는 바이트는 버린다.
7행은 변수 'cap'에 저장된 문자가 대문자의 아스키 코드 값 범위에 속하는지 검사한다.
문자 'G'의 아스키 코드 값은 71이고, 대문자 A(65)와 Z(90) 사이의 값이므로 if문은 참
그런데, 9행을 보면 소문자에서 대문자를 뺀 차를 활용한다. why?
small = cap + ('a' - 'A');
소문자는 대문자보다 아스키 코드 값이 크고 같은 문자끼리는 아스키 코드 값의 차가 일정하고,
알파벳은 연속된 아스키 코드 값을 가지므로
'a' - 'A'의 값을 대문자 'G'에 더하면 소문자 'g'를 구할 수 있다.
👏👏👏
11행을 보면 제어 문자를 백슬래시
('\')와 제어 기능 암시 문자
('n')를 함께 사용했다.
제어 문자는 형태가 없어 %c
로 출력하면 해당 제어 기능이 수행된다.
scanf 함수로 문자를 입력할 때는 %c 변환 문자를 사용한다.
%c는 형태가 있는 문자를 입력하지만,
공백
이나 탭 문자(tab)
, 개행 문자(enter)
와 같은 제어문자도 입력한다.
이들 세 문자는 숫자를 입력할 때 값을 구분하기 위해 사용되지만
문자를 입력할 때는 그 자체가 하나의 입력 데이터가 된다.
쉽게 이해해보자!
# include <stdio.h> int main(void) { char ch1, ch2; printf("문자를 입력하세요."); scanf("%c%c", &ch1, &ch2); printf("[%c%c]\n", ch1, ch2); return 0; }
enter
를 치는 경우enter
를 치는 경우enter
를 치는 경우enter에 해당되는 개행문자가 변수 ch2에 저장,
따라서 ch1에 입력된 'a'가 출력되고 바로 ch2에 저장된 개행문자가 출력되므로 줄이 바뀜
Space Bar
, Tab
, Enter
를 눌렀을 때 입력되는 문자를 묶어 부르는 말이다.
%d, %lf, %s와 같은 변환 문자로 숫자나 문자열을 입력할 때는 데이터를 구분하는 용도로 쓰이며,
그 자체가 데이터로 입력되지는 않는다.
# include <stdio.h> int main(void) { int a, b; printf("문자를 입력하세요."); scanf("%d %d", &a, &b); printf("%d %d\n", a, b); return 0; }
예를 들어 2개의 int형 변수에 10(공백)20을 입력하면
중간에 있는 공백 문자는 10과 20을 구분하는 용도로만 쓰인다.
공백은 숫자가 될 수 없기 때문!
scanf(" %c %c", &ch1, &ch2);
scanf 함수는 %c앞에 화이트 스페이스를 사용하면 문자도 분리하여 입력할 수 있다.
scanf 함수와 printf 함수는 문자뿐만 아니라 숫자도 입력하는 기능이 포함되어 있으므로
문자만 입출력하는 경우는 문자 전용 함수를 쓰는 것이 효율적이다.
getchar
함수와 putchar
함수는 문자 전용 입출력 함수이다.
int getchar(void); // 매개변수가 없고 입력한 문자를 반환 int putchar(void); // 출력할 문자를 인수로 줌
getchar 함수
매개변수가 없으므로 괄호만 사용하여 호출, 반환값은 int형
변수
반환값은 필요에 따라 변수나 배열에 옮겨 문자나 문자열로 사용
scanf 함수와 마찬가지로 공백, 탭, 개행 문자도 입력하는데 이들 문자를 제외하는 옵션은 없다.
putchar 함수
문자 상수나 문자의 아스키 코드 값을 인수로 주면 해당 문자를 화면에 출력
그리고 출력한 문자를 다시 반환하며 출력 과정에서 에러가 발생하면 -1을 반환
getchar 함수의 반환형이 int형인 이유는 문자 이외의 값도 반환하기 때문이다.
문자의 입력을 끝내기 위해 Ctrl
+ Z
를 누르면 -1을 반환하는데,
아스키 코드 값의 범위 0~127과 겹치지 않는다.
파일의 데이터를 모두 읽은 경우 반환하는 -1과 구분이 불가능할 수 있다.
-1은 모든 비트가 1인 상태로 저장되므로 1바이트 크기 공간에서는 255와 -1을 표현하는 비트열이 같기 때문이다.