기본 입출력 - 입력
다루는 내용
- 기본 입력
- FILE의 멤버 _base, _ptr, _cnt
기본 입력을 위한 함수들도 기본 출력처럼 stdin버퍼에서 하나의 문자를 얻어오는 getchar, stream을 string으로 얻어오는 gets, 포맷에 맞게 얻어오는 scanf등이 있다.
이들은 공통적으로 stdin버퍼에 아직 처리되지 않은 stream이 존재하는지 확인을 하고 없을 경우에는 하나의 stream이 입력되기를 기다리고 있을 경우에는 입력되기를 기다리지 않는다.
Look & Feel & Think
다음을 보면서 stdin버퍼에 아직 처리되지 않은 stream이 존재하지 않을 때 어떠한 동작을 하는지 생각해보자.
흔히 프로그래밍을 학습을 할 때 작성한 이가 테스트를 하는 경우가 많다. 이로 인해 사용자가 잘못 사용할 수도 있다는 사실을 간과하게 된다.
위의 예를 보면 사용자가 정수를 입력할 곳에 "my number is 12"라고 입력을 하였다. "%d"포맷은 stdin버퍼에 있는 아스키코드가 숫자 문자에 해당하는 아스키코드의 연속적인 나열을 정수로 변환해 준다.(예: "123" => 123) 그런데, 첫 번째 아스키코드가 'm'에 해당하기 때문에 no operation이 되어 해당 statement는 종결되게 된다. 이 뿐만 아니라 아직 stdin버퍼에는 처리되지 않은 stream이 여전히 존재하기 때문에 이 후에 stdin으로부터 입력받아 처리하는 부분에까지 영향을 미치는 것을 알 수 있다.
fflush함수를 이용하여(fflush(stdin);) 다음에 수행하는 곳에 영향을 주지 않도록 처리를 해야 할 것이다.
int getchar(void);
stdin버퍼에서 하나의 문자를 얻어온다.
Look & Feel & Think
stdin은 FILE *형으로 프로그램이 시작하면서 커널 모드에서 stdin과 stdout은 열고 진입점(main)이 시작된다. FILE 구조체의 멤버중에 _base는 버퍼 시작 주소, _ptr은 처리할 stream시작 주소, _cnt는 아직 처리되지 않은 stream내의 아스키 코드 개수를 값으로 갖는다.
아래의 예를 보면 stdin->_base는 변하지 않고 stdin->_ptr만 하나씩 변함을 알 수 있다. 또한, fflush(stdin);을 통해 기존 stream은 정상 처리로 변환시킴을 알 수 있다.
출력된 내용을 보면 stdin버퍼의 실제 내용이 지워지는 것이 아니라 _cnt를 0으로 변환함으로써 처리할 것이 없는 것으로 바꾸는 것이다.
참고로 FILE구조체의 멤버는 사용하는 컴파일러에 따라 다르게 정의되어 있으므로 stdio.h를 확인해 보라.
char *gets(char *buf);
gets는 사용을 함에 있어 주의해야 한다. gets함수 내부에서는 입력인자인 buf에 어느 정도의 공간이 할당되어 있는지에 대한 아무런 점검도 하지 않는다. 이는 프로그램 사용자가 buf크기를 초과하여 입력하였더라도 그대로 옮긴다는 것이다. 이를 개발 공정 내에서 테스트를 통해 확인을 하기도 쉽지 않다. stdin의 버퍼 크기에 맞추어 buf 크기를 맞추면 되긴 하지만 이는 프로그램 목적에 비해 쓸 데 없이 커다란 버퍼가 되어버릴 확률이 높다. 이에 대한 고민을 각자가 해 보길 바라면 자세한 내용은 함수만들기에서 다루기로 한다.
int scanf(const char *format,...);
포맷 사양자는 이전 항목에서 언급한 바가 있다.
'언어 자료구조 알고리즘 > C 언어 문법' 카테고리의 다른 글
24. 배열의 사용 (0) | 2009.08.19 |
---|---|
23.배열 (0) | 2009.08.19 |
22. 제어문 - 반복문 (0) | 2009.08.19 |
21.제어문 - 선택문 (0) | 2009.08.19 |
20. 제어문 - 조건문 (0) | 2009.08.19 |
18. 기본 입출력 - 출력 (0) | 2009.08.19 |
17.기본 입출력 개요 (0) | 2009.08.19 |
16. 지시/주소/인덱스/간접연산자 (0) | 2009.08.19 |
15. 비트/ 쉬프트 연산자 (0) | 2009.08.19 |
14. 비교/논리 연산자 (0) | 2009.08.19 |