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

현정님의 프로필 이미지
현정

작성한 질문수

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

8.8 메뉴 만들기 예제

8.8 메뉴 만들기 예제 개행 입력시 문자가 무시됩니다

작성

·

279

·

수정됨

1

안녕하세요! 아래의 코드를 실행시킨 뒤 먼저 '\n'입력 후 원하는 메뉴키를 입력하면 원하는대로 처리가 되지 않아요.

가령 이런식으로 엔터를 먼저 입력하고 q를 입력하면 quit를 실행하지 않고 다시 while문을 돌더라고요.

디버거로 한단계씩 살펴보니 문제는 get_first_char()함수에서 발생하는데, 처음에 getchar() 함수로 개행(\n)을 받으면서 다음 버퍼비우기(?) 코드에서 또 다시 입력을 받는 것 같고, 이 함수의 리턴값은 처음에 받았던 개행(c='\n')으로 나가서 생기는 문제 같은데요..

이 코드에서 어떻게 고쳐야 처음 들어올 개행도 입력오류처럼 처리할 수 있을까요??

 

코드는 아래와 같습니다!

 

#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':

putchar('\a');

break;

case 'c':

count();

break;

default:

printf("Error with %d.\n", user_choice);

exit(1);

break;

}

}

return 0;

}

void count(void)

{

int n, i;

printf("Enter an interger:\n");

n = get_integer();

for (i = 1; i <= n; ++i)

printf("%d\n", i);

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

continue;

}

char get_choice(void)

{

int user_input;

do

{

printf("Enter the letter of your choice:\n");

printf("a. avengers\tb. beep\n");

printf("c. count\tq. quit\n");

user_input = get_first_char();

 

} while ((user_input < 'a' || user_input > 'c') && user_input != 'q');

 

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.\n");

printf("Enter an interger:\n");

}

return input;

}

답변 2

1

홍정모님의 프로필 이미지
홍정모
지식공유자

안녕하세요? 질문 제목의 "씹혀요"를 "무시됩니다"로 수정해주시기를 부탁드립니다. 학생의 질문은 제가 임의로 수정할 수 없습니다.

현정님의 프로필 이미지
현정
질문자

앗 네!! 수정했습니다

1

안녕하세요, 답변 도우미 Soobak 입니다.

질문주신 부분에 대하여 해결된 코드를 제가 직접 작성하여 알려드리려고 하다가,
질문자님께서 직접 디버거도 활용해보셨고, 해결에 거의 다 접근하신 것 같아서 아쉬운 마음에 조금의 힌트만 드려보고자 합니다.
거의 다 왔어요!

말씀하신 것처럼, get_first_char() 함수의 반환값이 \n 일 때에 대해서, get_choice 의 함수에서 user_input 에 담기는 값이 어떤 값일지, 해당 값에 대하여 어떤 처리를 하면 더 이상 while 반복문을 수행하지 않을지 조금만 더 고민해보시면 좋을 것 같습니다.

힌트 : get_choice 함수 안의 while() 조건문, main() 함수 안의 while() 조건문 안의 조건 수정!

현정님의 프로필 이미지
현정
질문자

답변 감사합니다! 힌트를 보고 다음과 같이 수정해보았는데요,

get_choice 함수 안의 while 조건에 && user_input != '\n'를 추가해, 엔터 입력에 대한 리턴값으로도 더이상 while문을 돌지 않게 만들고,

main() 함수 내의 while조건문에서 case '\n':break;를 추가해서 다른 입력값(a,b,c,q를 제외한 입력값)처럼 처리할 수 있게 바꿔봤습니다.

#define CRTSECURE_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':

			putchar('\a');

			break;

		case 'c':

			count();

			break;

		case '\n':

			break;

		default:

			printf("Error with %d.\n", user_choice);

			exit(1);

			break;

		}

	}

	return 0;

}

void count(void)

{

	int n, i;

	printf("Enter an interger:\n");

	n = get_integer();

	for (i = 1; i <= n; ++i)

		printf("%d\n", i);

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

		continue;

}

char get_choice(void)

{

	int user_input;

	do

	{

		printf("Enter the letter of your choice:\n");

		printf("a. avengers\tb. beep\n");

		printf("c. count\tq. quit\n");

		user_input = get_first_char();

		

	} while (user_input != 'a' && user_input != 'b' && user_input != 'c' && user_input != 'q' && user_input != '\n');

	

	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.\n");

		printf("Enter an interger:\n");

	}

	return input;

}

그런데 위의 코드처럼 바꿔도 첫 입력으로 엔터를 입력시 엔터를 두 번 입력해야 다음 루프로 넘어간다는 문제가 있더라고요(get_first_char()함수는 손을 대지 않았으므로)

그래서 이번에는 get_first_char()함수를 다음과 같이 고쳐봤는데요(get_first_char()함수를 제외한 다른 코드는 제일 처음 제가 올렸던 코드와 같습니다),

아래의 코드로 실행시키면 엔터를 한번만 입력했을 때 여타 입력들처럼 다시 메뉴를 띄울 수 있더라고요. 이렇게 함수 안에 리턴이 두 번 들어가도 괜찮을까요?

char get_first_char(void)
{
	int ch;

	ch = getchar();
	if (ch == '\n')
		return -1;

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

	return ch;
}

안녕하세요, 답변 도우미 Soobak 입니다.

말씀하신 것 처럼, 하나의 함수 안에서 여러 개의 return 문을 사용할 수 있습니다. 하지만, 함수가 복잡해질수록, return 문이 많아지면 코드의 가독성이 떨어질 수 있고, 함수의 흐름을 이해하기 어려울 수 있다는 단점이 있습니다.

따라서, 상황에 따라서 적절한 주석이나 변수 이름 등을 사용하여 코드의 가독성을 높이는 것이 좋습니다. 말씀해주신 get_first_char 함수에서는 반환값이 char 자료형이므로, -1 대신 반환할 수 있는 유효한 값이며 예외로 처리하고자 한다는 의미로 '\0' (null 문자) 를 반환하는 것이 조금 더 가독성이 높은 방법이 아닐까 생각해봅니다.

결국 스스로 의도하신 대로 코드를 수정하고 작동되도록 만드셨네요! 👍👍

현정님의 프로필 이미지
현정

작성한 질문수

질문하기