인프런 커뮤니티 질문&답변
while (scanf(
작성
·
1.3K
2
안녕하세요.
스트링 입력을 받는 아래 코드에서
while (scanf("%[^\n]%*c", input) != 1)
printf("Please try again.\n>> ");
아무것도 입력하지 않고 엔터키를 누르면
Please try again>>
이 구문이 무한 반복으로 나타납니다.
왜 이런 걸까요?
답변 8
6
**오류 발견 시 지적 부탁드립니다.**
조금 까다로운 부분인데, 최대한 이해되도록 설명해보겠습니다.
scanf("%[^\n]%*c", input) 에서 빈 엔터를 입력하면 %[^\n]에 의해 scanf는 아무것도 읽어들이지 않습니다. \n 전까지 읽어야하는데, 첫 문자가 \n이니 작동하지 않는거죠.
따라서, while 문 검사에서 계속 빈 엔터를 마주치니, %[^\n]에 의해 scanf가 아무것도 읽어들이지 않고, 그렇기에 애초에 %*c 작동으로 이어지지 않는 겁니다.
그렇다면, %*c는 도대체 왜 필요할까?
아래의 단순한 코드를 실행해봅시다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char input1[10];
scanf("%[^\n]", input1);
printf("%s checked", input1);
}
분명 이 코드에서는 scnaf 안에 %*c가 없습니다. 그러나 %*c가 있는 코드와 동일하게 동작합니다.
scanf 안을 바꿔가면서 실행해보세요
그런데 아래의 코드를 실행해보시면, %*c가 있고 없음에 따라 결과가 달라집니다
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char input1[10];
char input2[10];
scanf("%[^\n]", input1);
scanf("%[^\n]", input2);
printf("%s checked", input1);
printf("%s checked", input2);
}
이 코드에서 abc를 입력하면 아래와 같은 결과가 나옵니다
![]()
이때 디버거로 주소를 확인해보면 아래와 같은 상태가 됩니다

즉, input1을 받고나서 버퍼에 남은 \n 때문에 input2를 받는 scanf가 제대로 실행되지 않고
출력시에 input1은 정상적으로 출력되지만 input2를 출력하려고 하니 문자열 끝의 \0 이 없고
쓰레기 값을 계속 출력하다가 input1의 메모리까지 침범해서 input1 끝의 \0을 만나서야 printf가 끝나는 모양새입니다
이 코드에서 원래와 같이 %[^\n]%*c 를 사용하면, input1 input2 모두 정상적으로 입력받을 수 있습니다.
따라서 정리하자면 이렇습니다
%*c는 버퍼에 남아있는 \n을 비워주는 역할이 맞다.
정확히는, 마지막 문자인 \n을 버퍼로부터 읽어들이지만, 없는셈 치고 문자열에는 입력해주지 않는 것입니다.
그러나,
[Enter]만 입력했을 경우 &[^\n]에 의해 scanf가 애초에 읽어들이지 않으므로 %*c가 작동하지 않았다는 것입니다.
-답변이 도움이 되셨다면 좋아요를 눌러주세요!-
6
**오류 발견 시 지적 부탁드립니다.**
넵 말씀하신대로 버퍼 때문이 맞습니다. 홍정모 교수님께서 왜 코드를 저렇게 쓰셨는지는 모르겠으나, 아마 엔터만 들어올 경우를 가정하지 않고 작성하신 것 아닐까요?
scanf가 작동하는 방식을 생각해봅시다. "%[^\n]%*c"에 따라 \n을 만날때 까지([^\n]) 읽어들이고, 마지막의 문자는 무시(*c)합니다.
이때 [Enter]만 입력하면?
먼저 버퍼에 \n이 쓰여질 겁니다. 동시에, scanf가 공백문자를 만났으므로 작동하기 시작합니다. 이때 scanf는 format specifier 에 따라 \n 만나기 전까지 읽고, 마지막 문자를 무시합니다.
이때 \n 만나기 전까지 읽는다는 것은, \n을 읽는다는 것일까요, 버퍼에 남겨두는 것일까요?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char input[10];
char ch;
scanf("%[^'k']%*c", input);
printf("%s\n", input);
ch = getchar();
printf("%c\n", ch);
}
이런 코드를 예시로 실행해봅니다. 입력에 abck를 넣으면, abc가 먼저 출력되고, 한줄을 띄운 후 k가 출력됩니다
즉, 버퍼에는 k가 남습니다.
k 대신 \n 으로 실행해도 마찬가지입니다.
원래 코드로 돌아가, while 조건 검사 이후 printf가 실행되고, 다시 while문의 조건 검사를 하는데, 위와 똑같은 일이 반복됩니다. 버퍼에 있는 건 \n 뿐인데, [^\n]으로 인해 \n을 버퍼에 남기고 읽으니 반환값은 계속 0이고 무한루프를 돌 수 밖에 없습니다
해결책은, while 문안에 버퍼를 지우는 코드를 추가하면 됩니다.
-답변이 도움이 되셨다면 좋아요를 눌러주세요!-
3
2
2
1
1
자세한 답변 정말 감사합니다.
한가지 여전히 의문으로 남는 부분은
%[^\n]%*c 코드에서
%*c이부분이 버퍼에 남아있는'\n'을 비워주는 역할로 알고 있는데, 왜 그렇게 하지 않았는가 입니다.
0
답변 감사드립니다
반환값은 0으로 알고 있습니다. 따라서 while문 조건 ! =1에 해당되므로 다시 루프가 시작된다는 것 까진 이해하겠습니다.
하지만 다시 scanf입력을 할 수 있어야 하는데 그럴수 없이 출력이 무한 루프를 돕니다. 버퍼에 남은 정보때문인지 그부분은 명확이 이해를 하지 못하겠습니다.
해당 부분의 프로그램 설계가 애초에 입력이 없으면 재입력을 받으려고 했던게 아니었나요?







헉