본문 바로가기

Programming Language/C

문자

1. 아스키 코드

기본적으로 C 프로그램의 문자는 아스키 코드(Ascii Code)를 따릅니다. 아스키 코드는 1바이트로 구성되는 것으로 0부터 127까지 각각의 번호에 따라 서로 다른 문자를 가지고 있습니다.

0부터 9까지의 숫자는 48부터 57까지의 아스키코드에 해당이 됩니다. 즉, 아스키코드의 48번은 문자 0이 되는 것입니다. 마찬가지로 영문 A는 아스키코드의 65번에 해당하고 영문 소문자 a는 아스키코드의 97번에 해당합니다.

캐릭터형 자체에 아스키코드를 넣어서 아스키코드에 해당하는 문자를 출력하는 예제를 작성해보겠습니다.

#include <stdio.h>

int main(void) {
    char a = 65;
    printf("%c\n", a);
    system("pause");
}

결과:

A
계속하려면 아무 키나 누르십시오 . . .

위에서도 언급했듯이 아스키코드 65는 영문 A에 해당하기 때문에 A가 출력됩니다. 이 결과에서 알 수 있듯이 우리가 자연어를 입력해도 컴퓨터는 내부적으로 모두 숫자로 처리하고 있는 것입니다.


2. 문자 입출력 함수

단 하나의 문자를 입력 받기 위해서는 getchar()라는 함수를 사용합니다. getchar() 함수를 이용해서 문자 하나를 입력 받는 예제를 작성해보겠습니다.

#include <stdio.h>

int main(void) {
    char a = getchar();
    printf("%c\n", a);
    system("pause");
}

결과:

A
A
계속하려면 아무 키나 누르십시오 . . .

getchar()함수를 활용하면 프로그램을 실행한 이후에 입력한 특정한 문자가 그대로 출력되는 것을 확인할 수 있습니다.


3. 버퍼

문자열을 처리할 때는 버퍼(buffer) 의 개념이 많이 활용됩니다. 참고로, 우리가 의도하지 않아도 c프로그램들은 기본적으로 자동으로 버퍼를 이용해 입출력을 처리한다는 특징이 있다. 즉, 위에서 getchar()라는 함수를 이용해서 A를 출력할 때 단순히 A를 입력하면 바로 A를 출력값으로 단순히 보여주는 것이 아니라, 내부적으로는 버퍼를 이용해서 입출력 과정을 처리한 것입니다.

사용자가 굉장히 많은 양의 문자를 입력했다고 가정해보겠습니다. 컴퓨터는 한 번에 처리 가능한 데이터의 양이 매우 한정적입니다. 물론 연산속도는 매우 빠르겠지만 처리할 수 있는 양은 매우 한정적이기 때문에 버퍼(buffer) 라는 곳에 우리가 처리할 데이터를 담아서 차근차근 1개씩 돌아가면서 처리해줍니다. 따라서, 우리가 아무리 많은 내용을 입력한다고 한들 내부적으로는 한 번에 처리되지는 않고 버퍼에 담겼다가 처리가 되는 것입니다.

즉, 버퍼는 임시적으로 특정한 데이터를 저정하기 위한 목적으로 사용되는 메모리의 영역이고, 우리가 만든 프로그램들은 의도하지 않아도 자동으로 버퍼를 이용해 입출력을 처리합니다.

3.1. 입력 버퍼로 인해 발생하는 오류

연속적으로 다양한 자료형의 데이터를 입력받을 때 버퍼를 제대로 이해하지 못했다면 다음과 같은 오류가 발생할 수 있습니다. 하나의 정수형 데이터를 입력받고 출력을 합니다. 이어서 바로 하나의 문자형 데이터를 입력받고 출력을 합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
    int a;
    char c;
    scanf("%d", &a);
    printf("%d\n", a);
    scanf("%c", &c);
    printf("%c\n", c);
    system("pause");
    return 0;
}

결과:

12345
12345

계속하려면 아무 키나 누르십시오 . . .

처음에 하나의 정수형 데이터를 입력하기 위해서 12345 를 입력했고 프로그램은 입력 받은 12345 를 출력하고 바로 프로그램을 종료했습니다. 이것은 컴퓨터가 줄바꿈이나 공백도 아스키코드로 관리하고 있기 때문에 발생한 문제입니다. 12345 를 입력한 뒤 엔터(enter)를 입력한 것을 컴퓨터는 문자로 인식하고 받은 것이다. 이러한 입력 버퍼 오류를 해결하기 위해서는 남아 있는 입력 버퍼를 지워야 합니다.

3.2. 남아 있는 입력 버퍼를 지우기

위해서 발생한 오류를 해결하기 위해서 입력 버퍼를 지울 것이고 이 때, getchar()함수를 사용할 것입니다. 입력 버퍼를 지우는 코드를 작성할 때 EOF 라는 것도 사용할 것인데, 이 것은 End Of File의 약자로 파일의 끝을 나타냅니다. 먼저 완성된 코드를 보겠습니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
    int a;
    char c;
    scanf("%d", &a);
    printf("%d\n", a);
    int temp;
    while((temp = getchar()) != EOF && temp != '\n'){ }
    scanf("%c", &c);
    printf("%c\n", c);
    system("pause");
    return 0;
}

결과(숫자만 입력했을 때)

12345
12345

결과(문자를 입력했을 때, 최종)

12345
12345
a
a
계속하려면 아무 키나 누르십시오 . . .

위 프로그램은 입력 버퍼 오류가 발생했던 코드와 달리 숫자를 입력 후 출력 뒤 개행문자를 만나면 입력을 멈춥니다. 따라서 정상적으로 하나의 문자까지 출력할 수 있습니다.
오류가 발생했던 코드와 다른 점은 이 부분입니다.

int temp;
while((temp = getchar()) != EOF && temp != '\n'){ }

하나의 문자를 받으면 temp에 담깁니다. 이제 그 temp를 EOF와 비교합니다. 즉, 파일의 끝인지 비교하는 것입니다. 또한, temp가 개행문자인지 비교합니다. 만약 둘 중 하나에 해당하면 아무 것도 처리하지 않습니다. 그래서 {} 안이 비어 있는 것입니다.
while을 사용함으로서 남아 있는 개행문자를 모두 없는 것으로 처리하여 입력 버퍼를 효과적으로 비울 수 있습니다. 즉, 파일의 끝이거나 개행문자를 만나면 입력을 멈추기 때문에 입력 버퍼를 비운다는 것입니다.
또한 컴퓨터는 내부적으로 모든 문자들은 숫자로 관리되기 때문에 int temp; 와 같이 int형을 사용해서도 문자를 받을 수 있습니다.