F.R.I.D.A.Y.

scanf_s 사용하기 본문

DEV/C C++

scanf_s 사용하기

F.R.I.D.A.Y. 2019. 4. 28. 03:20
반응형

 매번 scanf_s를 사용하면서도 제대로 된 사용법을 몰라서 질문을 하는 분들이 많습니다. 그래서 이번 포스트에서는 scanf_s의 사용 방법에 대해 설명합니다.


scanf_s

 C언어에서 입력을 받는 표준 입력입니다. 과거에도 C언어 표준으로 존재하기는 했으나 선택 구현이라 scanf_s를 구현한 컴파일러는 MSVC밖에 없었다고 하더군요. 그래서 많은 사람들이 scanf_s는 MSVC에서만 제공하는 "C언어 비표준이다!"라고 단정 짓는 경우가 있었습니다. 저도 최근까지는 scanf_s가 비표준인 줄 알고 있었어요...

 

 scanf_s의 함수 원형은 다음과 같습니다.

int scanf_s(const char *format [, argument]...);

 이때 [, argument]... 는 추가로 입력을 받을 때 사용합니다.

반환 값

 무릇 함수는 반환형이 존재합니다. 위에서 원형을 살펴보면 알 수 있듯이 scanf_s는 int타입의 데이터를 반환합니다.

	int a, b, c;
	scanf_s("%d %d %d", &a, &b, &c);

 위 식에서 모두 정상적으로 값을 입력받으면 3이라는 값이 반환됩니다. 즉, 정상 입력 시에는 아래 이미지의 밑줄 친 부분의 argument 개수만큼 값이 반환됩니다.

 만일 0이 반환되면 모두 제대로 할당되지 않았다는 뜻이 될 수 있겠네요.

 오류, 혹은 EOF(End of File)을 만나면 EOF를 반환합니다. EOF는 stdio.h 헤더에 -1로 define 되어있습니다.

사용법

 기존에 scanf를 이용하신 경험이 있다면 크게 어렵지 않습니다. 대부분의 서식 지정자가 동일하거든요. 따라서 저는 이번에 초보시절 가장 헷갈려하는 부분을 소개하고자 합니다.

#include <stdio.h>

int main(void) {

	char a, b, c;
	char str[30];
	scanf_s("%s %c %c %c", str, &a, &b, &c);

	return 0;
}

 이렇게 작성하면 문제를 일으킵니다. scanf_s는 scanf에서 발생 가능한 문제점을 해소하기 위해 새로 만들어진 함수입니다. 포인터로 변경했을 때, 길이가 특정되지 않은 데이터를 담는 변수 대해서는 [해당 변수 주소, 받을 문자열 길이]로 작성해주어야 합니다. 받을 문자열 길이는 변수가 담을 수 있는 공간보단 작아야겠죠.

 즉, 위 코드는 아래와 같이 변경되어야 하죠.

더보기

# 정확한 길이를 알지 못하는 데이터?

 대표적인 예로 문자열이 있습니다. 문자열은 길이가 모두 같은 것이 아니라 사용할 때마다 가변적으로 변합니다. 우리가 말을 할 때 모두 동일한 길이의 글자로 표현하지는 않습니다. 이러한 특성을 생각하면 문자열은 가변적인 것이라 생각할 수 있습니다.

#include <stdio.h>

int main(void) {

	char a, b, c;
	char str[30];
	scanf_s("%s %c %c %c", str, 30, &a, 1, &b, 1, &c, 1);

	return 0;
}

 ※ 참고하세요

 scanf_s에서 문자열을 입력받을 때는 char 기준 [배열 길이 - 1]의 값이 들어가야 합니다. 마지막 NULL문자를 넣기 위함입니다.

더보기

# Q. 문자는 1바이트만 쓰는데 굳이 뒤에 1을 붙여줘야 하나요?

 처음 배울 때는 문자는 1바이트라 생각하실 수 있습니다. 그러나 이는 ASCII 인코딩에서 유효하는 것입니다. 한글이나 한자 등은 하나의 문자를 표현하는데 2바이트, 혹은 그보다 많은 크기를 이용합니다. 때문에 "문자는 무조건 1바이트다!"라고 표현할 수 없습니다.

 물론, 2바이트 등을 담는 문자(wide character, multibyte character)에 대한 함수 또한 제공하지만, scanf_s 함수를 이용할 때는 문자를 받을 때도 뒤에 해당 문자의 크기를 명시해주어야 합니다.

 

 만일 wchar_t[# VS에는 wchar_t라는 자료형이 있으며, 크기는 short와 같은 2Byte입니다. 와이드 바이트 문자를 받을 목적으로 만들어진 자료형입니다.]를 사용해 문자열을 받으려면 아래와 같이 이용해야겠죠.

wchar_t str[10];
scanf_s("%S", str, 9);

 str 뒤에 붙는 숫자 9는 str이라는 변수가 저장할 수 있는 최대 문자의 수를 의미합니다. 자세한 내용은 글 하단 scanf_s 링크를 참고하세요.


서식 지정자

 scanf_s를 사용하는 데 있어 기본적인 서식 지정자는 다음과 같습니다.

서식 지정자
%c 문자 char %C 문자 wchar_t
%s 문자열 char * %S 문자열 wchar_t *
%hhd char 범위 정수 %hhu unsigned char 범위 정수
%hd short 범위 정수 %hu unsigned short 범위 정수
%d int 범위 정수 %u unsigned int 범위 정수
%ld long 범위 정수 %lu unsigned long 범위 정수
%lld long long 범위 정수 %llu unsigned long long 범위 정수

 지금 설명하는 서식 지정자의 속성은 scanf_s, scanf에 대한 것으로 wscanf_s, wscanf에 대한 서식 지정자는 아닙니다. 자세한 서식 지정자는 다음 문서를 참고하세요.

 

scanf 형식 필드 문자

scanf 형식 필드 문자scanf Type Field Characters 이 문서의 내용 --> 다음 정보는 scanf 와 같은 보안 버전을 비롯하여 함수의 모든 scanf_s패밀리에 적용됩니다.The following information applies to any of the scanf family of functions, including the secure versions, such as scanf_s. type 문자는 요구되는 유일한 서식 지정

docs.microsoft.com


참고 문서

 

 

scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l

scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_lscanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l 이 문서의 내용 --> 표준 입력 스트림에서 형식이 지정된 데이터를 읽습니다.Reads formatted data from the standard input stream. 이러한 버전의 scanf, _scanf_l, wscanf, _wscanf_l에는 CRT의 보안 기능에 설명된 대로 향상된 보안 기능이

docs.microsoft.com

 

scanf 형식 필드 문자

scanf 형식 필드 문자scanf Type Field Characters 이 문서의 내용 --> 다음 정보는 scanf 와 같은 보안 버전을 비롯하여 함수의 모든 scanf_s패밀리에 적용됩니다.The following information applies to any of the scanf family of functions, including the secure versions, such as scanf_s. type 문자는 요구되는 유일한 서식 지정

docs.microsoft.com


더 알아보기

 scanf_s가 탄생한 배경

 

scanf()의 문제점

VS ERROR C4996 : SDL 오류 오늘은 scanf() 함수와 같이 입출력 함수, 문자열 함수를 다룰 때 종종 발생하는 C4996에 대해 다뤄봅니다. 원인 원래는 문제없이 컴파일되는 것이 맞지만, scanf() 등의 함수에서 발생..

pang2h.tistory.com

# index

728x90
반응형

'DEV > C C++' 카테고리의 다른 글

Snake with Windows API  (0) 2019.06.08
define VS typedef  (0) 2019.05.21
배열 선언을 x-y가 아니라 y-x순으로 작성하는 이유  (4) 2019.04.24
상수의 접미어  (0) 2019.04.13
예외처리 - assert 사용해보기  (0) 2019.04.12
Comments