일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- tipssoft
- 함수
- 알고리즘
- 프로그래밍
- CS
- Tips프로그래밍강좌
- 리뷰
- 티스토리
- 백준
- Windows
- c++
- 이지스퍼블리싱
- Desktop
- Visual Studio
- 지식나눔강좌
- c
- Tips강좌
- 문법
- Javascript
- Direct2D
- c#
- VS ERROR
- 김성엽
- 배열
- doit코틀린프로그래밍
- Kotlin
- 연산자
- Win32
- 포인터
- Programming
- Yesterday
- Today
- Total
F.R.I.D.A.Y.
scanf_s 사용하기 본문
매번 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_s가 탄생한 배경
# index
'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 |