26. scanf, scanf_s 함수

A) scanf함수와 scanf_s 함수를 사용할 때는 반환한 값을 기억할 메모리 주소를 전달해야 해! B) 네. 그리고 scanf_s 함수로 문자나 문자열을 입력받을 때도 버퍼의 크기도 전달해야죠.

 

int scanf(const char * format, … );
int scanf_s(const char * format, … );

scanf와 scanf_s 함수는 표준 입력(키보드)에 입력한 내용을 포멧에 맞게 얻어오는 함수예요.
그리고 scanf_s 함수는 scanf 함수의 안전한 버전의 함수죠.

scanf 함수의 반환 값은 포멧 사양자에 맞게 변환한 개수이며 포멧 사양자는 printf에서 사용하는 것과 거의 같아요.
double 형식 실수를 입력받을 때 %f 대신 %lf를 사용하는 정도가 차이점이죠.

scanf 함수와 scanf_s 함수는 포멧에 맞지 않는 부분이 있으면 더 이상 작업을 진행하지 않아요.
그리고 %s 포멧은 공백이나 탭, 엔터를 만나기 전까지 문자열만 변환해요.
공백을 포함해서 문자열을 입력받을 때는 gets나 gets_s를 사용하세요.

그리고 scanf 함수에서는 입력한 내용을 호출한 곳의 변수에 설정하는 일을 합니다.
따라서 호출하는 곳에서는 변수의 주소를 전달하세요.
변수의 메모리 주소를 얻을 때는 주소 연산자(&)를 사용해요.

◈ scanf 함수를 사용하는 예

◈ 실행 결과

 

다음의 예제 코드를 보면 scanf 함수를 두 번 호출하고 있어요.
두 번째 scanf 함수를 호출하는 곳에서는 포멧 사양자로 “%d.%d.%d.%d”를 전달하고 있죠.
최종 사용자가 포멧과 다르게 123.45.23ab45 를 입력하면 포멧이 맞게 입력한 123.45.23 부분만 변환해요.
그리고 변환 성공한 개수 3을 반환하죠.

◈ scanf 함수를 사용하는 예

◈ 실행 결과

 

그런데 scanf 함수를 사용하면 컴파일 경고 메시지가 나와요.
포멧에 맞게 변환하여 입력 인자로 받은 주소에 값을 지정하는 과정에서 전달받은 메모리 크기를 벗어날 위험이 있거든요.
이러한 버퍼 오버플로우 문제를 개선한 함수가 scanf_s 함수예요.
scanf_s함수는 대부분 scanf함수 사용법과 거의 같아요.
차이가 있는 부분은 문자나 문자열을 입력받을 때 버퍼 길이도 전달해야 한다는 것이죠.

◈ scanf_s 함수를 사용한 예

◈ 실행 결과

그리고 scanf 함수를 사용하고 경고 메시지를 확인하기 싫다면 #pragma 매크로를 이용하세요.
#pragma warning(disable:4996)