본문 바로가기

문자 입출력 함수

1. 문자 출력 함수

 

다음의 두 가지가 있다.

 

int putchar(int c);

int fputc(int c, FILE* stream);

 

함수 호출이 성공하면  c 를,  즉 출력한 문자의 아스키 코드값을 int형으로 반환하고,

함수 호출이 실패하면 EOF를 반환한다. EOF는 조금 뒤에 살펴본다.

 

정수  c 를 문자의 형태로 출력한다. 예를 들어  c  값이 65면 A가 출력된다.

 fputc  함수는  stream 을 통해 출력할 스트림을 지정할 수 있다.

 stream 을 stdout으로 지정하면 모니터로 출력되고, 파일로 지정하면 파일로 출력할 수 있다.

 stream 의 자료형에서  FILE 은 파일 구조체인데, 아직은 자료형의 일종이라고만 알아두자.

 

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
int main()
{
    putchar(65);
    fputc(66, stdout);
 
    return 0;
}
 
cs

 

 

 

 

 

2. 문자 입력 함수

 

다음의 두 가지가 있다.

 

int getchar();

int fgetc(FILE* stream);

 

함수 호출이 성공하면 입력된 문자의 아스키 코드값을 int형으로 반환하고,

함수 호출이 실패하면 EOF를 반환한다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main()
{
    int input;
 
    input = getchar();
    putchar(input);
 
    input = fgetc(stdin);
    putchar(input);
 
    return 0;
}
 
cs

 

 

 

결과만 보면 하나의 문자만 입력되고 출력된 것 같지만, 실제로는 두 개의 문자가 입출력되었다.

다만 첫 번째 문자 A와 달리 두 번째 문자는 개행 문자(Enter)였기 때문에 보이지 않았을 뿐이다. 엔터 키를 누르면 10의 아스키 코드값을 갖는  '\n' 이 입력된다. 따라서  getchar()  호출 시에는 A가 입력되지만  fgetc(stdin)  호출 시에는  input 으로 개행 문자가 반환되기 때문에 두 번째  putchar(input) 에서는 개행이 출력되는 것이다.

 

 

 

 

3. EOF

 

End Of File. 파일의 끝을 명시하기 위해 정의된 상수로, -1의 값을 갖는다.

예를 들어 fgetc 함수로 파일의 내용을 읽어올 때 반환값이 EOF인 것은 파일의 끝에 도달했다, 즉 더이상 읽어올 내용이 없다는 것을 의미한다.

 

키보드를 대상으로 읽어올 때 getchar 함수와 fgetc 함수는 함수 호출이 실패했거나, 특정 커맨드가 입력되었을 때 EOF를 반환한다. 특정 커맨드는 Windows에서는 ctrl+z, Linux에서는 ctrl+d다. 키보드 입력에는 끝이라는 게 없으니 언제 EOF를 반환할 지 약속해놓은 것이다.

 

참고로 EOF는 아스키 코드표에 명시되어 있지도 않으니, 문자로 출력해선 안 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
int main()
{
    int input = 0;
    
    while (input != EOF) //입력값이 EOF면 탈출!
    {
        input = getchar();
        
        if(input == EOF) { printf("EOF"); }
        else { putchar(input); }
    }
 
    return 0;
}
 
cs

 

 

 

참고로 위에서는 하나의 문자만 입력했지만, 꼭 그럴 필요는 없다.

문자열이 입력되면 문자열의 문자 수 만큼 getchar 함수가 호출된다.

예를 들어 Hello를 입력하면 getchar 함수가 6번(개행 포함) 호출된다.

 

 

 

 

4. 왜 int형인가?

 

문자 입력 함수가 입력받는 것도, 문자 출력 함수가 출력하는 것도 한 글자의 문자다. 그러니 char형을 매개변수로 받고 char형을 반환해도 될 것 같은데, 왜 3바이트나 더 큰 int형을 받고 반환하는 걸까?

 

문자 입출력 함수는 문자의 아스키 코드값도 반환하지만 EOF, -1도 반환한다. 그런데 EOF는 int 타입이기 때문에 이 값을 char형 변수에 저장하면 잘못 해석될 위험이 있다. 

 

아스키 코드표에는 0~127의 값을 갖는 문자만 명시되어 있고, 문자로 출력한다는 것은 아스키 코드에 대응하는 문자를 출력하는 것을 의미한다. 따라서 문자 형태로 EOF를 출력한다는 것은 어불성설이다. 특히 unsigned char형일 경우 언더플로우(underflow)가 일어나 -1이 아닌 255가 저장된다. 따라서 안정적으로 -1의 값을 유지할 수 있는 int의 형태로 입력받고 입력하는 것이 바람직하다.

 

 

 

 

5. 문자 단위 입출력 함수의 의의

 

다음 두 코드는 동일한 결과를 나타낸다.

 

ch = getchar();

putchar(ch);

 

scanf("%c", &ch);

printf("%c", ch);

 

scanf 함수로도 문자를 입력받을 수 있다. 그런데 왜 문자 입출력 함수가 따로 있는 걸까?

scanf 함수와 printf 함수는 서식 지정을 통해 어떤 형태의 데이터든 출력할 수 있다. 때문에 문자 입출력에 특화된 함수에 비해 필요한 연산이 많아 속도가 느리고 차지하는 메모리 공간의 크기도 크다. 때문에 단순히 문자를 입출력할 거라면 scanf 함수와 printf 함수보다 문자 입출력 함수를 사용하는 것이 바람직하다.

 

 

 

 

6. 문자를 입출력한다?

 

앞에서 문자를 입력받는다고 했지만, 사실 입력받은 데이터를 문자로 간주한다고 이해하는 게 바람직하다. 마찬가지로 문자를 출력한고 했지만, 데이터를 문자로 간주해 출력한다고 이해하는 게 바람직하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main()
{
    int input;
 
    input = getchar();
    printf("getchar()로 3 입력: %d\n\n", input);
    
    scanf("%d"&input);
    printf("scanf(\"%%d\", &input)로 3 입력: %d\n", input);
 
    return 0;
}
 
cs

 

 

똑같이 3을 입력했지만  getchar() 로 입력받았을 때는 문자 3으로 간주해  input 에는 문자 3의 아스키 코드값인 51이 저장되었다. 하지만  scanf("%d", &input) 로 입력받았을 때는 정수 3으로 간주해  input 에는 정수 3이 그대로 저장되었다.

 

마찬가지로 51을  putchar(51) 로 출력하면 문자 3의 아스키 코드값으로 간주해 3이 출력되지만  printf("%d", input) 로 출력하면 정수 51로 간주해 51이 그대로 출력된다.

 

이는 문자 뿐 아니라 문자열, 실수 등에도 해당된다. 

 

'Programming > C' 카테고리의 다른 글

문자열 길이 측정, 복사, 연결 함수  (0) 2019.05.13
문자열 입출력 함수  (0) 2019.05.07
스트림  (0) 2019.05.01
void형 포인터  (0) 2019.04.15
함수 포인터  (0) 2019.04.10