컴퓨터/C
C언어를 이용하여 다양한 프로그래밍을 하다 보면 아래와 같은 경우를 자주 만나게 됩니다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int numinput;
char charinput;
scanf("%d", &numinput);
printf("%d\n", numinput);
scanf("%c" ,&charinput);
printf("%c", charinput);
//예상 결과는 ??
return 0;
}
소스코드를 읽어와는 다른 결과가 나오면서 종료가 됩니다.
프로그래머는 2번의 입력과 2번의 출력을 만들려고 했지만 애석하게도 프로그램에서는 원하는 데로 동작을 하지 않습니다.
그렇다면 그 원인이 무엇일까요?
버퍼를 이용하여 우리는 장치와 장치 간의 속도 차이를 극복할 수 있게 되었습니다. scanf 또한 입력되는 값을 하나씩 받는 것이 아니라, 버퍼에 저장된 뭉텅이 데이터를 받아옵니다. 그렇다면 위와 같은 소스코드에서 입력 버퍼는 어떤 식으로 데이터를 가지고 있고, scanf는 활용을 하는지 알아보도록 합시다.
scanf("%d", &numinput);
사용자가 100이라는 int값을
입력하고 엔터를 누르게 되면 입력 버퍼에는 아래와 같이 데이터가 남게 됩니다.
scanf에서 "% d"라는 형식 지정자로 숫자를 하나 버퍼에서 불러옵니다.
이때 우리는 scanf 함수를 이용하기 위해 엔터를 눌렀습니다. 그리고 이 엔터 또한 키보드 입력 버퍼 공간에는 줄 넘김을 표현하기 위한 개행 문자인 '\n'이 입력되어 있습니다.
scanf("%c" ,&charinput);
이처럼 키보드 입력 버퍼에 개행 문자가 담겨 있기 때문에 문자 하나를 입력하는 % c 형식 지정자의 경우 개행 문자를 가지고 옵니다. 프로그래머가 원하지 않는 경우가 생기는 것입니다.
이제 위와 같은 소스코드에서 원인을 알 수 있게 되었습니다.
해결 방법을 생각해보자면 가장 근본적인 방법은 아래와 같습니다.
간단하게 몇 가지 방법에 대해 설명해 드리도록 하겠습니다.
fflush 함수는 어떤 스트림의 버퍼를 비우겠다는 의미의 함수입니다.
따라서 표준 입력 스트림 버퍼를 초기화하고 싶으면 아래와 같이 사용하면 됩니다.
fflush(stdin);
하지만 이 방식은 비표준 방식이며 작동하지 않는 환경이 더 많이 있습니다. 따라서 사용하지 않는 것이 바람직합니다.
입력 버퍼의 위치를 되감아 처음의 위치부터 받게 하는 함수입니다. fflush와 비슷한 개념입니다.
rewind(stdin);
이 또한 다른 환경에서 올바르게 동작하지 않을 수 있어 사용하지 않는 것이 바람직합니다.
위와 같은 소스코드에서 문제는 입력 후에 개행 문자가 입력 버퍼에 남아있는 것 입니다.
그렇다면 getchar함수를 이용하여 하나의 문자를 바로 사용해버린다면 문제 해결이 가능합니다.
scanf에서 입력을 마치면서 입력버퍼에 들어간 개행 문자를 getchar함수를 이용해 사용해 버리는 것입니다.
scanf("%d", &numinput);
printf("%d\n", numinput);
getchar();
scanf("%c" ,&charinput);
printf("%c", charinput);
scanf에서 문자를 받을 때 아래와 같이 사용하면 개행 문자와 공백을 무시하고 문자를 받을 수 있습니다.
//scanf("%c",&charinput);
scanf(" %c",&charinput); //위와 차이점은 스페이스 하나뿐
위와 같은 식으로 scanf함수를 이용하면 입력 버퍼 중 공백과 개행 문자를 무시하고 처음으로 만나는 문자의 값을 취하겠다는 뜻입니다.
C 언어 - scan 무한 반복 에러 (0) | 2021.12.01 |
---|---|
C 언어 - 예외처리 (0) | 2021.11.30 |
C 언어 - 버퍼(Buffer)의 개념과 이해 (0) | 2021.11.24 |
C 언어 - time.h (0) | 2021.10.02 |
C 언어 - NULL (0) | 2021.09.30 |
91년생 공학엔지니어의 개발일지
TODAY :
YESTER DAY :
TOTAL :
Commnet