본문 바로가기
프로그래밍/C

scanf , scanf_s " %d "로 정수 입력 받으려다 문자(열)이 잘못 들어왔을 때 무한루프에 빠지는 문제 / 문장 씹히는 문제 해결

by eteo 2022. 4. 27.

 

사용자가 꼭 우리가 기대한대로 입력하라는 법이 없으니 이러한 예외처리도 필요하다.

 

scanf, scanf_s %d로 정수 입력 받으려다 문자나 문자열이 들어왔을 때 무한루프에 빠지는 문제

혹은

다음 문장이 씹히고 그 다음으로 넘어가는 문제의 해결책은 동일하다. 입력버퍼를 비워주면 된다.

 

 

scanf 함수는 %d 정수형을 입력받기 위해 대기하고 있었는데 문자/문자열이 들어오니 값을 대입하지 못하고 그게 입력스트림에 계속 남아서 문제를 일으키는 것이다.

 

 

입력 버퍼를 비우는 방법으로 구글링을 해보면 다음과 같은 방법이 나온다.

 

1. fflush(stdin) -> 사용X

fflush 함수는 원래 출력버퍼를 비우는 용도이기에 사용하지 말라고 함.

(출처 : C언어 열혈 프로그래밍 책)

 

 

2. rewind(stdin)

이것도 원래 표준입력버퍼를 비우는 용도의 함수는 아니었다. 파일포인터 초기화함수로, 인수로 파일포인터를 넣었을 때 파일위치지시자를 맨앞으로 보내주는 함수이다. 근데 파일포인터 대신 표준입력스트림(standard input)을 뜻하는 stdin을 인수로 넣으면 키보드로부터 입력된 표준입력버퍼를 지우는 효과가 있다. 사실 지운다기보다 입력된 데이터를 무시하고 되감기하는 느낌이지만 그게 그거다.

많은 사람들이 입력버퍼를 비우는 용도로 쓰고 있고 큰 문제없이 쓰는것 같다.

참고 : https://docs.microsoft.com/ko-kr/cpp/c-runtime-library/reference/rewind?view=msvc-170 

 

 

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

얘는 입력버퍼에 남아있는 데이터를 꺼내서 비우는 형태다. 꺼내긴 했는데 리턴값을 받아줄 변수가 없으니 걍 사라진다. 사용자가 입력시 마지막으로 엔터를 쳤을테니 버퍼에 남은 맨마지막 문자는 개행문자\n이고 개행문자가 나올때까지 계속 꺼내다가 개행문자가 꺼내진 후엔 while 문이 false가 되어 탈출한다.

 

가끔 검색하다보면 이런 긴 버전 코드도 보인다.

(ch = getchar()) != '\n' && ch != EOF)

입력버퍼에서 꺼낸 리턴값을 ch변수로 받아서 EOF가 아닌지도 체크하는 코드인데..EOF(End of File)는 파일의 끝을 뜻하는 상수로 -1값을 가진다. getchar함수 호출을 실패했을때나 윈도우에서 Ctrl+Z, 리눅스에서 Ctrl+D를 누르면 EOF값이 반환되는데 내생각엔 굳이..저 짧은 버전으로 충분할거 같다.

 

 

테스트 해봤을 때 2, 3번 둘 중 어느걸 사용해도 똑같은 효과를 보였다. 둘 중 맘에 드는 걸 사용하면 될 것 같다.