# Result
문자열을 입력하세요 : hello tesla
입력한 문자열 : hello
문자열을 입력하세요 : 입력한 문자열 : tesla
이런 오류들에 대한 설명글이므로 열심히 읽어보시길 바랍니다.
//오류가 나는 scanf
#include <stdio.h>
int main()
{
int num;
char c;
printf("숫자를 입력하시오 : ");
scanf("%d", &num);
printf("문자를 입력하시오 : ");
scanf("%c", &c);
return 0;
}
Result
숫자를 입력하세요 : 1
숫자를 입력하세요 :
#심각한 문제가 발생했다. 우리는 scanf 를 두번 코드에 넣었기에 처음 숫자를 받은 후 두번째로 문자를 받고 결과값들을 보여줘야 하지만 코드를 실행하니 숫자만 받고 실행이 종료되어 버렸다. 이게 무슨 일인가..
우리는 키보드로 치는 모든 정보를 일시적으로 stdin 에 저장되었다가 나중에 입력이 종료되면 한꺼번에 처리하고 이렇게 저장되는 장소를 버퍼(buffer) 라고 부르고 이 중에 키보드에 대한 입력 버퍼를 stdin 이라고 하는 것이다. (입력 스트림) 우리는 입력이 완료됨을 엔터를 침으로서 입력을 마친다는 의미를 컴퓨터에 보내주게 된다. 다시말해 컴퓨터는 개행 문자 \n 을 입력을 종료하였으니 버퍼에 들어있는 내용을 가지고 처리하라는 뜻으로 받아들이게 된다. 그런데 컴퓨터는 \n 까지 버퍼에 저장하게 된다. 즉 우리가 1을 쓰고 엔터를 치면 버퍼에 아래와 같은 상태가 된다.
stdin
--> 1\n
그러면 입력을 끝냈다면 scanf 함수를 이용해서 stdin 으로 부터 숫자를 얻어온다. 그 후 scanf 함수는 공백 문자를 만나기 전까지 stdin 에서 데이터를 가져간 후 버퍼에서 삭제해 버린다. 다시말해 scanf 함수가 scanf("%d", &num) 이라면 num 에 1을 저장한 후 버퍼의 모습은 아래와 같다.
stdin
--> \n
이제 문제가 되었던 scanf("%c", &c); 가 실행될 차례이다. 그런데 여기서 문제다. %c 는 stdin 에서 딱 한개의 문자만을 가져온다. 만약 stdin 에 아무것도 없다면 사용자의 입력을 기다리고 있겠지만 stdin 에 무언가가 있다면 그것을 냉큼 가져오게 된다. 그런데 위에 stdin 에 뭐가 남아있는지 보면 \n 이 남아있다. 따라서 scanf 는 이 \n 를 c 에 저장하게 된다. 즉 c 에는 사용자의 입력으러 받지도 않고 \n 을 넣게 된 것이다. 이는 %s 를 사용하게 되면 공백 말고 실질적인 문자열만 받으므로 문제를 해결할 수 있다.
하지만 %s 를 사용하더라도 또 다른 문제가 발생한다.

여기는 str1, str2 라는 문자열이 있고 이를 위와 같이 두번의 scanf 로 입력 받은 후 처음 입력받고 출력, 두번째 입력받고 출력 이렇게 실행된다. 일반적으로 문자열을 넣어주면 아무런 문제가 생기지 않지만 처음 입력을 할 때 오류가 나는 실행결과를 보여보겠다.
Result
문자열을 입력하세요 : hello tesla
입력한 문자열 : hello
문자열을 입력하세요 : 입력한 문자열 : tesla
이렇게 원하지 않는 오류가 나게 된다. 이제 stdin 의 상태를 살펴보면
stdin
--> hello tesla\n
scanf 함수는 stdin 으로부터 공백을 제외한 문자가 나올 때 까지 모든 공백 문자들은 무시한다. 위의 경우 hello 까지는 가져오지만 띄어쓰기가 공백의 역할을 하기 때문에 hello 까지만 입력되고 다음 scanf 는 입력할세도 없이 tesla 를 가져가고 문자열 뒤에 남은 공백 문자를 보고 중지하여 stdin 은 최종적으로 \n 만 남게 된다.
아무튼 scanf 는 상당히 이해하기 복잡하다. 다음 글에서 이 문제를 해결하는 방법을 설명하도록 하겠다.
| 문자열 리터럴에 대한 이해 (c언어) (0) | 2022.01.30 |
|---|---|
| scanf 의 원리 및 오류 상황에 대한 이해 (2) (0) | 2022.01.30 |
| c 언어 " " 와 ' ' 의 차이점 및 문자열 (0) | 2022.01.27 |
| 함수 포인터 설명 (0) | 2022.01.27 |
| 포인터 swap (**pa, **pb) (0) | 2022.01.26 |
댓글 영역