scanf 함수를 쓴 후 printf 함수를 사용하면 제대로 나오지 않는 경우가 있습니다. 어떤 경우인지 알아봅시다.
#include <stdio.h>
int main(void)
{
char input;
printf("첫 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
printf("두 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
printf("세 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
return 0;
}
이 코드에서 어떤 문제가 발생할까요? 입력 버퍼가 문자열이 모두 다 입력되었다는 것을 알기 위한 기호는 NULL(\0)입니다. 첫 번째 입력이 발생하고 출력이 된 후에 남아있는 NULL 문자가 그 아래 두 번째 입력의 값으로 들어가면서 바로 출력 코드가 실행되었습니다. 왜냐하면 %c는 문자 하나만을 출력하기 때문에 NULL 문자가 아래 버퍼로 인식된거죠.
우리가 원하는 것은 아래였습니다. 그런데 위와 같이 이상하게 출력이 되는 경우가 있습니다. 이를 해결하는 방법은 무엇일까요?
1. scanf(" %c", &input);
첫번째 방법입니다. 형식지정자 %c 바로 전에 띄어쓰기를 하면 됩니다.
scanf(" %c", &input);
이제 적용하겠습니다.
#include <stdio.h>
int main(void)
{
char input;
printf("첫 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
printf("두 번째 입력: ");
scanf(" %c", &input);
printf("출력: %c \n", input);
printf("세 번째 입력: ");
scanf(" %c", &input);
printf("출력: %c \n", input);
return 0;
}
두 번째 입력과 세 번째 입력을 출력한 후에 나오는 scanf는 띄어쓰기 후에 %c를 입력하면 정상적으로 결과가 나오는 것을 알 수 있습니다.
제대로 나오는 것을 알 수 있습니다.
2. scanf("%*c%c", &input);
두 번째 방법입니다. %*c는 한 문자를 버리고 받아옵니다.
#include <stdio.h>
int main(void)
{
char input;
printf("첫 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
printf("두 번째 입력: ");
scanf("%*c%c", &input);
printf("출력: %c \n", input);
printf("세 번째 입력: ");
scanf("%*c%c", &input);
printf("출력: %c \n", input);
return 0;
}
결과를 보겠습니다. 잘 나오네요.
아래는 참고한 블로그입니다.
https://modoocode.com/36
3. getchar();
이번에는 scanf와 함께 다른 함수를 사용해 해결한 경우입니다. 먼저 getchar() 사용법을 보겠습니다. 아래는 참고 링크입니다.
https://en.cppreference.com/w/c/io/getchar
아래 그림은 cppreference의 내용입니다.
<stdio.h>에 포함된 함수입니다. 보시면 받는 것도 void인 것을 알 수 있습니다. 때문에 그냥 아래와 같이 사용하는 것으로 보여집니다. 이 getchar() 함수를 이용하면 버퍼에 남아있는 null 문자를 호출해서 그 공간을 비워줍니다. 자세한 설명은 아래 링크를 참고해봐요!
https://modoocode.com/32
아래는 함수 사용 예입니다.
#include <stdio.h>
int main(void)
{
char input;
printf("첫 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
getchar();
printf("두 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
getchar();
printf("세 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
return 0;
}
성공적으로 실행된 것을 확인할 수 있었습니다.
4. rewind(stdin);
rewind 함수를 사용하겠습니다. 먼저 cppreference를 보면 아래와 같이 나옵니다.
rewind 함수에 대한 설명은 아래 링크에 나옵니다. 간단히 설명하자면 rewind 함수는 파일의 다음번에 읽거나 쓸 위치를 처음으로 옮기는 함수라고 합니다.
https://www.acmicpc.net/blog/view/108
아래는 사용 예입니다. (FILE *stream) 안에 표준 입력인 stdin을 넣어주었습니다.
#include <stdio.h>
int main(void)
{
char input;
printf("첫 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
rewind(stdin);
printf("두 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
rewind(stdin);
printf("세 번째 입력: ");
scanf("%c", &input);
printf("출력: %c \n", input);
return 0;
}
이제 실행 결과를 보겠습니다. 원하는 대로 정확하게 나온 것을 확인할 수 있었습니다.
그러나 Windows Subsystem for Linux 환경에서 사용한 GCC 컴파일러는 엉뚱하게도 제대로 나오지 않는 것을 확인할 수 있었고, 이 함수는 컴파일러에 따른 호환성에 문제가 있다고 생각됩니다.
정리하겠습니다.
scanf 함수를 %c 자료형으로 입출력하는 경우 입력 버퍼에서 하나의 문자만 가져오기 때문에 문자의 끝에 자동으로 들어가는 NULL 문자는 버퍼에 그대로 저장되어 있습니다. 따라서 scanf 함수를 연속으로 사용할 경우 사용자가 원하는 결과가 나오지 않습니다.
이를 해결하기 위한 방법 4가지를 알아봤습니다.
1. scanf(" %c", &input);
2. scanf("%*c%c", &input);
3. getchar();
4. rewind(stdin); - 호환성 문제있음
감사합니다!