작성
·
273
·
수정됨
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 문자) 를 반환하는 것이 조금 더 가독성이 높은 방법이 아닐까 생각해봅니다.
결국 스스로 의도하신 대로 코드를 수정하고 작동되도록 만드셨네요! 👍👍
앗 네!! 수정했습니다