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

픽린님의 프로필 이미지
픽린

작성한 질문수

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

8.8 메뉴 만들기 예제

(2:48) a, b, q 입력은 모두 다 잘 받는데, c 입력만 정상적으로 받아들이지 못합니다.

해결된 질문

작성

·

189

0

int main()

{

while (1) {

char c;

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

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

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

if ((c = getchar()) == 'a')

printf("Avengers assemble!\n");

else if ((c = getchar()) == 'b')

printf("\a");

else if ((c = getchar()) == 'c') {

int num;

printf("Enter an integer : ");

scanf("%d", &num);

for (int i = 1; i <= num; i++)

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

}

else {

printf("\n");

break;

}

}

1. a, b, q 모두 정상적으로 받아들여서, 의도했던 결과를 도출하는데, c만 정상적으로 받아들이지 않습니다.

2. 제가 처음에 char c; 선언 후, c = getchar( );이라고 입력해준 후, 각 조건문에서 getchar( )없이 c == 'b' 이런 식으로 c하고만 비교해주기도 했는데,
→a 입력만 받아들이고 끝내버리는 문제가 있었습니다.

1과 2 두가지 경우에서 발생한 문제의 원인이 무엇인지 잘 모르겠습니다.

답변 1

0

우선 getchar() 입력 메서드는 문자를 입력 받아 버퍼에 저장하여 하나씩 꺼내오는 형태로 사용됩니다.
반환값은 int형으로 반환이 되고요.

1번의 경우 getchar()를 조건문마다 호출 하셔서 생기는 에러입니다.
테스트 하실때 아마도 a -> b -> c 또는 a -> b ->q 이런 식으로 테스트 하셨을 것으로 예상이 됩니다.
(제가 그랬습니답)

코드를 따라 실행 해본다면, 첫번째 if문에서 getchar()입력 함수를 만나 입력하게 됩니다.
a 이렇게 입력하게 되겠죠? 입력하게 되면 버퍼에는 'a' 와 enter(입력한뒤 누르는 enter 맞습니다)가 저장 됩니다. 아스키코드로 한다면 '\n' 문자가 저장 될 것 같네요.

그래도 a를 입력했으니 해당 조건문을 통과해 원하는 문구를 출력하게 됩니다.
이후 반복문을 돌아 다시 조건문에 왔을 때 다시 첫번째 if문을 만나게 됩니다.
하지만 버퍼에 남아있던 '\n' 문자를 읽어옴으로 인해 두번째 if문으로 넘어가고
b를 입력한다면 조건문을 통과해 소리를 내게 됩니다. (만약 여기서 c를 입력했다면 종료될 것 입니다.)

대강 어떤식으로 getchar() 입력메서드가 실행되는지 감이 오시나요?
마지막 c를 입력하려 하니 버퍼에는 '\n' 문자가 남아 첫번째 조건문을 건너뛰어 두번째 조건문에 c를 입력하게 됩니다. 두번째는 b를 입력받는 조건문이라 넘어가고 다음 조건문에서 '\n'를 읽어와 넘어가게 됩니다.

2번 같은 경우 해당 코드가 작성자님이 원하시는 방향의 코드가 될 것 같습니다.
다만 앞서 말했듯이 문자 입력 후 버퍼에 '\n' 문자가 남아있어 반복문을 한번 실행 후 재 입력 되지 않고 넘어가는 문제가 생기는 것 입니다.
해당 문제를 해결하기 위해서는 버퍼를 지우는 작업이 필요합니다. 구글에 검색 하시면 많은 자료가 나오니 참고해서 진행 하시면 될 것 같습니다.

제가 설명을 잘 하지 못해 이해가 되지 않으셨다면 말씀해주세요 ㅜㅜ

픽린님의 프로필 이미지
픽린
질문자

image
와....! 그렇군요. 친절히 자세하게 설명해주신 덕분에 금방 이해할 수 있었습니다. a와 b는 잘 입력이 되는 것 같다가 c는 제대로 입력이 안되고, q도 사실상 제대로 입력이 안된 상태였는데 그런 이유가 있었네요..! 정말 감사합니다.

버퍼 내 데이터를 없애주는 과정에서 궁금증이 또 생겨 실례를 무릅쓰고 또 한번 질문드립니다..!
image
버퍼 내 데이터를 없애주는 작업으로
while (c != '\n') continue;
라고 입력했었는데, 실행시켜보면 a를 입력받고, 그 이후에 어떤 값도 입력받지를 않았습니다.
이걸 보면 '버퍼'라는 것이 이름이 정의된 데이터 공간(변수)에 각각 할당이 되는 것이 아니라,
변수가 선언된 자료형에 따라 버퍼 크기가 할당된다거나
혹은 getchar()같은 함수에 버퍼 크기가 할당되는 것이 아닐까 싶습니다.
→그래서 c != '\n' 이 아니라, getchar() != '\n' 을 했을 때 비교 대상이 어떤 것이느냐에 따라 결과가 달리 나오고, 버퍼 내 데이터를 처리해줄 수 있는지 여부가 결정되는 것 같습니다.

c로 비교했을 땐 제대로 작동하지 못했지만, getchar()를 입력했을 때는 정상적으로 버퍼 내 데이터를 삭제해줄 수 있었는지... 잘 모르겠습니다ㅠㅠ

※위에 정상 실행이 됐던 코드는 while (getchar() != '\n') continue;라고 입력했습니다.

작성자님이 말씀하신 것처럼 변수에 버퍼가 각각 할당 되는 것은 아닙니다.
일반적으로 사용하는 입력 함수 scanf(), getchar(), getch() 등등 과 출력함수 printf(), putchar(), putch() 등등이 C언어에서 정의한 표준 입출력 함수들입니다. 해당 입출력 함수들을 사용하게 되면 자동으로 입출력 버퍼를 생성해 데이터를 버퍼에 저장하게 됩니다.

입출력 함수 사용시에 자동으로 버퍼에 적재가 됩니다.

c != '\n' 의 조건 같은 경우에는 c에 대입된 값을 검사하기 때문에 해당 식은 버퍼를 비우는 행위가 아닙니답
getchar() 함수의 경우 앞서 말씀드렸듯이 버퍼에 저장된 문자를 읽어오는 함수이기 때문에 해당 함수로 반복문을 실행 하면 버퍼에 있는 문자를 계속 읽어 오면서 빈 버퍼를 만들어주게 됩니다.


if/else 문 마다 반복문을 넣는게 조금 더 직관적일 수도 있을 것 같은데요. while()문 마지막 또는 if/else문 종료 후 한번만 넣어주시는게 코드를 좀 더 간결하게 바꿀수 있을 것 같습니다.

버퍼에 관한 내용은 검색하면 더욱 다양한 자료가 나오니 참고하시면 좋을 것 같습니답 좋은하루 되세요

픽린님의 프로필 이미지
픽린

작성한 질문수

질문하기