스트림

스트림에는 입력 스트림, 출력 스트림 2가지가 존재한다. 이 스트림은 운영체제가 제공하는 소프트웨어로 구현되어있는 것으로 파일 스트림 혹은 모니터에 출력하는 출력 스트림 등이 있다.

먼저 문자 단위 입출력 함수를 보자.

  • int putchar(int c);
  • int fputc(int c, File * stream);
  • 함수 호출 성공 시 쓰인 문자 정보 반환, 실패 시 EOF 반환.

여기서 신경 쓸 점은 fputc함수의 경우 파일을 문자를 전송할 스트림을 지정할 수 있다. 즉 파일을 대상으로도 데이터를 전송 가능하다.

다음으로 문자 입력 함수를 보자.

  • int getchar(void);
  • int fgetc(File * stream);
  • 파일의 끝에 도달하거나 함수호출 실패 시 EOF 반환

키보드로부터 하나의 문자를 입력 받는 함수라 할 수 있다. fgetc 함수도 하나의 문자를 입력받지만 fputc함수와 마찬가지로 입력받을 스트림을 지정할 수 있다. 즉 파일을 대상으로 입력이 가능하다.

 

위의 함수들을 보면 함수호출 실패 시 EOF를 반환한다는 것을 알 수 있다. EOF란 End Of File의 약자로써 파일의 끝이라는 의미이다. 파일의 끝은 존재하지만 키보드의 끝은 어떻게 알 수 있을까? 바로 ctrl +  Z이다.(윈도우 기준) 이를 다음의 예시로 알아보자.

<소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main(void) {
    int ch;
    while (1) {
        ch = getchar();
        if (ch == EOF)
            break;
        putchar(ch);
    }
    return 0;
}
cs

<실행결과>

ctrl + Z를 입력하자 종료가 된것을 확인할 수 있다.

이번에는 문자열 입출력 함수에 대해서 알아보자.

  • int puts(const char *s);
  • int fputs(const char* s, FILE * stream);
  • 성공시 음수가 아닌 값, 실패 시 EOF 반환

puts 함수의 경우 호출되면 자동으로 개행이 되지만 fputs함수의 경우 자동으로 개행이 되지 않는다.

  • char * gets(char *s);
  • char * fgets(char *s, int n, FILE * stream);
  • 파일의 끝에 도달하거나 함수호출 실패 시 NULL 포인터 반환

표준 입출력 & 버퍼

버퍼링을 하는 이유는 데이터 전송의 효율성 때문이다. 1층에서 3층까지 책을 옮긴다고 했을때 책을 한권씩 나르는것 보다 가방에 20권씩 담아서 나르는것이 더 효율적이라는 예시를 생각해보면 이를 쉽게 이햐할 수 있다.

출력버퍼를 비우는 fflush함수

int fflush(FILE * stream);

이 함수는 인자로 전달된 스트림의 버퍼를 비우는 기능을 제공한다.

 

그렇다면 입력버퍼를 비워야할 경우가 있을까? 이를 다음의 예시를 통해 알아보자.

<소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
int main(void) {
    char perID[7];
    char name[10];
 
    fputs("주민번호 앞 6자리 입력: ", stdout);
    fgets(perID, sizeof(perID), stdin);
 
    fputs("이름 입력: ", stdout);
    fgets(name, sizeof(name), stdin);
 
    printf("주민번호: %s \n", perID);
    printf("이름: %s \n", name);
    return 0;
}
cs

<실행결과>

왜 이런 결과가 나타났을까? 우선 주민등록번호를 보면 999999 총 7글자이다.(엔터 포함) 그런데 sizeof(perID)가 7이므로 문자열을 입력받기 위해 널문자를 제외하고 총 6글자를 읽어지는 것이다. 즉 개행 이 입력 버퍼에 남으므로 fgets함수까지 남는다. fgets는 \n을 읽으면 종료하므로 입력버퍼에 남은 \n 만 읽고 종료해버리는 것이다.따라서 위와 같은 경우를 방지하기 위해 입력 버퍼를 비워야 한다. 그러면 어떻게 해야 할까?

바로 함수를 정의하는 것이다. 이를 다음의 예시로 보자.

<소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
void ClearLineFromReadBuffer(void) {
    while (getchar() != '\n');
}
 
int main(void) {
    char perID[7];
    char name[10];
 
    fputs("주민번호 앞 6자리 입력: ", stdout);
    fgets(perID, sizeof(perID), stdin);
 
    ClearLineFromReadBuffer();
 
    fputs("이름 입력: ", stdout);
    fgets(name, sizeof(name), stdin);
 
    printf("주민번호: %s \n", perID);
    printf("이름: %s \n", name);
    return 0;
}
cs

<실행결과>

입력 버퍼를 비우니 정상적으로 동작하는것을 알 수 있다.


그 외의 함수들

문자열 길이 반환하는 함수 : strlen

문자열 복사 함수 : strcpy, strncpy

문자열 덧붙이는 함수 : strcat, strncat

문자열 비교 함수 : strcmp, strncmp

문자열의 내용 int로 변환 : atoi

문자열의 내용을 long으로 변환 : atol

문자열의 내용을 double로 변환 : atof

'C' 카테고리의 다른 글

12. 구조체와 사용자 정의 자료형 2  (0) 2021.06.27
11. 구조체와 사용자 정의 자료형  (0) 2021.06.27
9. 함수 포인터 & void 포인터  (0) 2021.06.26
8. 2차원 배열과 포인터  (0) 2021.06.26
7. 이중 포인터  (0) 2021.06.25

+ Recent posts