인프런 커뮤니티 질문&답변

fe님의 프로필 이미지
fe

작성한 질문수

홍정모의 따라하며 배우는 C언어

8.8 메뉴 만들기 예제

count함수에서 버퍼비우기 필요한 이유?

작성

·

413

0

안녕하세요. get_integer()에서 정수값을 리턴받고 그 값이 count()에서 num값으로 쓰이는데

count()에서 그 어떤값도 getchar()을 통해 입력받지않죠.

while (getchar() != '\n')

continue;

이 문장들이 count()에서 왜 필요한지 모르겠습니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

char get_choice(void);
char get_first_char(void);
int get_integer(void);
void count(void);

int main()
{
	int user_choice; //사용자의 입력

	while ((user_choice = get_choice()) != 'q')
	{
		switch (user_choice)
		{
		case 'a':
			printf("Avengers assemble!\n");
			break;
		case 'b':
			printf("\a");
			break;
		case 'c':
			count();
			break;
		default:
			printf("Error with %d.\n", user_choice);
			exit(1);
			break;
		}
	}
	return 0;
}
char get_choice(void)
{
	int user_input;

	printf("Enter the letter of your choice:\n");
	printf("a. avengers    b. beep\n");
	printf("c. count       q. quit\n");

	user_input = get_first_char();

	while ((user_input < 'a' || user_input>'c') && user_input != 'q') // 입력 유효성 검증
	{
		printf("Please try again.\n");
		user_input = get_first_char();
	}

	return user_input;
}

char get_first_char(void) // 첫 번째 글자만 받는 함수
{
	int ch;
	ch = getchar();
	while (getchar() != '\n')
		continue;
	return ch;
}

int get_integer(void)
{
	int input;
	char c;

	while (scanf("%d", &input) != 1)
	{
		while ((c = getchar()) != '\n')
			putchar(c);
		printf("is not an integer.\nPlease try again.");
	}
	return input;
}

void count(void)
{
	int i, num;
	printf("Enter an integer:\n");
	num = get_integer();
	for (i = 1; i <= num; i++)
		printf("%d\n", i);
	while (getchar() != '\n')
		continue;
}

답변 3

7

**오류 발견 시 지적 부탁드립니다.**

넵 먼저 첫번째 질문에 답변드리겠습니다.

제가 홍정모 교수님이 프로그램을 설계하신 의도를 다 알 수는 없지만, 이 프로그램의 경우 c를 입력하면 count라는 기능이 동작하도록 되어있습니다. count를 동작시키기 위해 get_integer 라는 함수를 사용해서 integer 하나를 입력받는 것이구요. get_integer 내부에서는 정수가 입력된 게 맞는지 확인하고, 맞다면 return 하는 식으로 동작하는 거죠. (count 기능의 내부기능으로 get_integer 기능)

이때 제가 드린 2번 질문처럼 '만약에 get_integer 안의 scanf 에서 input이 정상적으로 입력됐으나, 버퍼에 남는 값이 생긴다면?' 이라는 가정을 해봅시다.

이 가정에 맞는 input 값은 "123 k" 와 같은 input일 것입니다. "123 k" 를 입력하면 scanf가 공백문자 전까지 입력을 받아 123이 정상적으로 입력되지만, " k"가 버퍼에 남게 됩니다.

따라서 count 함수는 버퍼에 남았을지 모를 값을 비워줘야 합니다 (물론 get_integer 에서 input을 return 하기전에 버퍼를 비워줘도 문제 없겠습니다) count 함수가 끝나면 다시 사용자의 선택 (a, b, c, q) 을 입력받을텐데, 버퍼에 값이 남으면 오동작이 발생하게 되니까요. 

while (getchar() != '\n')

  continue; 

를 주석처리 해놓고 "123 k" 와 같은 값을 입력해보시면 어떤 식으로 작동하는지가 이해되실 거라고 생각합니다

두번째 질문에 대한 답은 생각하신 대로가 맞습니다. 그러나, getchar()의 버퍼와 scanf 버퍼가 따로 있는 것이 아닙니다. 입력(키보드)에 대한 버퍼가 있고, 입력시에 그 버퍼에서 값을 임시로 받아두었다가 한번에 옮기는 것입니다. 따라서 getchar 를 이용해 입출력 버퍼를 비우는 게 가능한 것입니다.

(추가 설명)

참고 : https://jhi93.github.io/category/os/2019-11-25-operatingsystem-02-1/

참고로 올려드린 사이트의 첫번째 그림을 보시면, 키보드와 마우스에 local buffer가 있는 모습을 보실 수 있습니다

이 부분은 저 역시 공부중인 부분이라 더 정확하게 설명드리기가 조금 어렵네요

-답변이 도움이 되셨다면 좋아요를 눌러주세요!-

2

1. scanf 는 공백을 기준으로 나눠서 입력받습니다. 따라서, 버퍼에 남는 값이 생길 수 있습니다

2. '만약에 get_integer 안의 scanf 에서 input이 정상적으로 입력됐으나, 버퍼에 남는 값이 생긴다면?' 이라는 가정을 해봅시다. 어떤 입력을 넣으면 위의 가정대로 진행될까요?

3. 2에서 버퍼에 값이 남은채로 count 에, 

while (getchar() != '\n')

  continue; 

가 없다면?

해당 코드만 주석처리 해놓고 2에서 찾은 입력값을 넣어보세요. 못 찾으시겠으면 다시 질문 주시면 알려드리겠습니다 :)

-답변이 도움이 되셨다면 좋아요를 눌러주세요!-

0

fe님의 프로필 이미지
fe
질문자

Charlie Park님 답변 감사합니다.

"get_integer()에서는 버퍼를 비워주는 while문이 없기 때문에

count()에서 

while (getchar() != '\n')

  continue; 

을 넣어 버퍼를 비워준다."

이렇게 이해하면 될까요?

+) while (getchar() != '\n')

  continue;

을 가지고 getchar()로 입력받은 공간의 버퍼만 비우는게 아니라,

'scanf()로 입력받은 공간의 버퍼 또한' 지워줄 수 있는건가요?

fe님의 프로필 이미지
fe

작성한 질문수

질문하기