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

정진호님의 프로필 이미지

작성한 질문수

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

8.5 숫자와 문자를 섞어서 입력받기

scanf()가 잘못된 입력을 읽을 때 행동

24.03.03 20:10 작성

·

176

·

수정됨

2

안녕하세요,

이 코드에서 'a 2 3 '을 입력 후 'b 4 5'를 입력하면, 두번째 while문이 돌아갈때 입력버퍼에 남아있는 ' \nb 4 5' 중 ' '는 c로 들어가고, 다음 %d를 읽으려 할때 '\n' 와 %d가 매칭되지 않아 scanf가 종료되고, rows와 cols는 기존 2 와 3이 유지되어 하기와 같이 결과가 나오는 것을 이해를 했습니다.

핵심은 버퍼에 남아있는 ' \nb 4 5' 중 '\n'은 scanf가 읽다가 포기하고 버려졌다 라는 건데요,(이게 스트림이 옮겨졌다고 표현하는게 맞나요?) 이를 테스트하기 위해 하기와 같이 코드를 짜봤는데, 또 아닌 것 같아서요..

만약 제가 깨달은게 사실이라면,

제가 예상한 결과 ->

이 코드를 실행시키고 입력창에 'hello'를 입력하고 엔터를 치는 순간 입력 버퍼에 'hello\n' 이 들어가게되고,첫번째 while문의 scanf() 가 실행될때 %d와 hello가 매칭되지 않으므로 scanf를 종료. scanf가 비정상적으로 종료되었으므로, 입력버퍼에 있는
'hello\n'에서 hello는 버려지고, \n으로 스트림이 옮겨짐.
두번째 while문 조건에서 c에는 \n이 저장되고, 조건문이 거짓이므로 바로 break;가 실행되어 종료됨.

실제 결과 ->

두번째 while문의 putchar까지 실행됨.

 

왜 차이가 발생한건지 궁금합니다.

답변 2

2

Soobak님의 프로필 이미지

2024. 03. 04. 00:55

안녕하세요, 질문&답변 도우미 Soobak 입니다.

 

scanf() 함수에서 형식지정자 불일치 문제가 일어날 때, 버퍼에서 인덱스가 무조건 이동하는 것은 아닙니다.
%d 형식 지정자는, 공백문자(space, 개행, 탭 등)를 만날 때만 버퍼에서 인덱스를 이동시키며 건너뛰고, 값을 읽도록 설계되어있습니다.

즉, 제공해주신 두 번째 코드에서 %d 형식 지정자는 개행 문자를 건너 뛰며 버퍼의 인덱스를 이동시킨 후,
hello\n 문자열 중, h 문자를 읽으려 하지만, 이에 대해서 실패하는 것입니다.

이 때, 공백 문자가 아닌 문자들은 버퍼에 그대로 남아있게 됩니다.
따라서, 두 번째 반복문의 getchar() 함수가 h 문자부터 o 문자까지 hello 문자열을 출력하게 됩니다.

추가적으로, 질문 주신 강의의 관련 내용에 대한 질문&답변 글의 조금 혼동을 드릴 수 있었던 표현에 대해서, 보다 명확하게 내용을 추가 하였습니다.
참고해보시면 도움이 되실 것 같습니다.

좋은 질문 감사드립니다.

정진호님의 프로필 이미지
정진호
질문자

2024. 03. 05. 22:52

수박님 답변 감사드립니다. 정리하면,

1, 첫 번째 while문의 %d 가 h를 읽으려다가 실패.

2, 버퍼의 인덱스는 그대로 h에 위치.

3, 두번째 while문의 getchar()가 현재 버퍼 인덱스에 위치한 h부터 차례대로 읽기 시작.

맞나요?


수박님, 혹시 수박님은 어떻게 해답을 찾으시나요?
예를 들면 답변주신 내용 중에
"공백문자(space, 개행, 탭 등)를 만날 때만 버퍼에서 인덱스를 이동시키며 건너뛰고, 값을 읽도록 설계되어있습니다" 라는 내용들은 어디서 찾으시나요? 수박님도 분명 초보 시절이 있었을텐데, 그 때 모르는게 생겼을때 어떻게 해결하셨는지 과정이 궁금합니다.

질문드리기전에 최소한 디버거로 찍어보거나 다른 분들이 달아주신 질문글의 답변을 참고하고 질문드리지만, 질문드릴때마다 매번 알려달라고 떼쓰는 어린아이가 된 것 같아서 질문할때마다 참 민망합니다 하하..ㅋㅋ ㅠㅠ

Soobak님의 프로필 이미지

2024. 03. 06. 22:45

네, 맞습니다.
정확하게 이해하고 계십니다.

 

추가 질문에 대해서 답변을 드리자면, 저는 '질문을 편하게 하시는 것'이 정말 중요하다고 생각합니다.
저 또한 모르는 것이나 궁금한 것, 이해가 어려운 것 들을 커뮤니티, 동료 학우분들 등 다양한 방법을 통해 질문을 많이 했었고, 지금도 많이 합니다.

저도 질문자님처럼 질문할 때 민망함을 느낀적, 어렵다고 생각한 문제에 대해서 의외로 간단한 답변을 듣고 부끄러움을 느낀적 등이 많지만, 그냥 마음 편히 이겨내고 꾸준히 이곳 저곳에 질문하고, 자료들을 검색(요즘에는 Bing, ChatGPT 등의 AI도 많이 활용합니다.)하면서 학습했던 것 같습니다.

지금도 모르는 것이 생기면 그렇게 학습하고 있습니다.
(교수님께서 운영하시는 커뮤니티에도 질문을 하고, 주위 동료, 지인 분들에게도 적극적으로 질문을 많이 하며 학습합니다. 정확한 답을 못 얻을 때도 있지만, 답을 얻기 위한 자료, 예를 들어 책이나 배경 지식, 조언 등 을 얻어 조금씩 나아갑니다. 예 : 제가 버퍼와 시스템 콜 등에 대해서 더 공부하고 싶었을 때, 운영체제와 관련된 책을 공부하면 된다는 조언을 받아 책을 찾아서 공부했던 기억이 납니다.)


따라서, 모르는 것이 생기면 (따배씨++ 강의에 한해서는) 이 곳에 편하게 질문 글을 남겨주세요.
교수님께서도 수강생 분들이 편하게 질문하시기 위해 도우미라는 역할을 만들어주셨고, 편하게 질문을 주시면 열심히 답변 드리는 것이 제 역할이니 적극 활용해주시면 좋을 것 같습니다.

교수님이 운영하시는 커뮤니티(디스코드, 네이버카페, 유투브 등)를 참여하시는 것도 추천드립니다.

디스코드 : https://discord.gg/QkVU8QWUzS(홍정모 연구소)

네이버 카페 : https://cafe.naver.com/jmhonglab(홍정모 연구소)

0

인프런 AI 인턴님의 프로필 이미지

2024. 03. 03. 20:17

안녕하세요, 인프런 AI 인턴입니다. 정진호 님의 질문에 대해 도움을 드릴 수 있는 몇 가지 기존 답변을 찾았습니다. scanf() 함수와 getchar() 함수의 버퍼 동작에 대해 이해하고 싶으신 것 같습니다. scanf() 함수가 잘못된 입력을 읽을 경우 행동 파악에 아래 답변들이 도움이 되기를 바랍니다.

이러한 질문에 대한 답변으로, “질문 4분 18초”에 관한 답변과 “5:25 초”에 관한 답변이 유사한 상황을 설명하고 있습니다. 이 답변들에서는 scanf()가 예상치 못한 입력을 만났을 때, 그리고 getchar()를 이용하여 입력 버퍼를 어떻게 다루는지에 대해 설명하고 있습니다.

  • 질문 4분 18초

    • 이 답변은 scanf()를 이용할 때 정수가 아닌 입력이 버퍼에 남아있는 경우 어떻게 처리되는지를 설명합니다. putchar() 함수를 이용해 남아 있는 입력을 보여주고, 이러한 입력이 버퍼에서 어떻게 다루어지는지를 보여줍니다.
  • 5:25 초

    • 이 답변은 getchar() 함수와 입력 버퍼의 관계, 특히 합당하지 않은 입력 후 getchar() 함수가 버퍼를 어떻게 처리하는지에 대한 질문에 답합니다.

또한, scanf() 함수와 버퍼 동작에 대해 일반적인 설명을 필요로 한다면, “[02:47] getchar()” 질문에 달린 답변이 도움이 될 수 있습니다.

  • [02:47] getchar()
    • 이 글에서는 getchar() 함수가 어떻게 입력 버퍼를 다루는지, 특히 버퍼에 남아있는 내용을 전부 지우는 목적의 while 문과 continue를 사용하는 방법에 대해 설명하고 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.