Namespaces
Variants

std:: scanf, std:: fscanf, std:: sscanf

From ko.cppreference.net
< cpp ‎ | io ‎ | c
헤더 파일에 정의됨 <cstdio>
int scanf ( const char * format, ... ) ;
(1)
int fscanf ( std:: FILE * stream, const char * format, ... ) ;
(2)
int sscanf ( const char * buffer, const char * format, ... ) ;
(3)

다양한 소스에서 데이터를 읽어와서 format 에 따라 해석하고 결과를 지정된 위치에 저장합니다.

1) 데이터를 stdin 에서 읽어옵니다.
2) 파일 스트림 stream 에서 데이터를 읽습니다.
3) 널 종료 문자 배열 buffer 에서 데이터를 읽습니다.

목차

매개변수

stream - 읽을 입력 파일 스트림
buffer - 읽을 널 종료 문자 문자열을 가리키는 포인터
format - 입력을 읽는 방법을 지정하는 널 종료 문자 문자열을 가리키는 포인터
... - 수신 인자

format 문자열은 다음으로 구성됩니다:

  • 공백이 아닌 멀티바이트 문자 (% 제외): 형식 문자열의 각 문자는 입력 스트림에서 정확히 하나의 동일한 문자를 소비하거나, 스트림의 다음 문자가 동일하지 않으면 함수가 실패합니다.
  • 공백 문자: 형식 문자열의 공백 문자 하나는 입력에서 사용 가능한 모든 연속된 공백 문자를 소비합니다 (마치 std::isspace를 루프에서 호출하는 것처럼 결정됩니다). 형식 문자열에서 "\n", " ", "\t\t" 또는 다른 공백 문자 간에는 차이가 없습니다.
  • 변환 지정. 각 변환 지정은 다음 형식을 갖습니다:
  • 도입 % 문자.
  • (선택 사항) 할당 억제 문자 *. 이 옵션이 있으면 함수는 변환 결과를 수신 인자에 할당하지 않습니다.
  • (선택 사항) 최대 필드 너비를 지정하는 정수(0보다 큼), 즉 함수가 현재 변환 지정에 지정된 변환을 수행할 때 소비할 수 있는 최대 문자 수입니다. %s와 %[는 너비가 제공되지 않으면 버퍼 오버플로를 초래할 수 있습니다.
  • (선택 사항) 길이 수정자는 수신 인자의 크기, 즉 실제 대상 유형을 지정합니다. 이는 변환 정확도와 오버플로 규칙에 영향을 미칩니다. 기본 대상 유형은 각 변환 유형마다 다릅니다(아래 표 참조).
  • 변환 형식 지정자.

사용 가능한 형식 지정자는 다음과 같습니다:

변환
지정자
설명 예상
인자 유형
길이 수정자→ hh h 없음 l ll j z t L
C++11부터만 사용 가능→ 예 예 예 예 예
%
리터럴 %과 일치합니다.
해당 없음 해당 없음 해당 없음 해당 없음 해당 없음 해당 없음 해당 없음 해당 없음 해당 없음
c

문자 또는 문자 시퀀스와 일치합니다.

  • 너비 지정자가 사용되면 정확히 width 문자와 일치합니다 (인자는 충분한 공간이 있는 배열에 대한 포인터여야 합니다).
  • %s 및 %[와 달리 배열에 널 문자를 추가하지 않습니다.
해당 없음 해당 없음
char*
wchar_t*
해당 없음 해당 없음 해당 없음 해당 없음 해당 없음
s

공백이 아닌 문자 시퀀스(문자열)와 일치합니다.

  • 너비 지정자가 사용되면 최대 width 또는 첫 번째 공백 문자까지 중 먼저 오는 것까지 일치합니다.
  • 일치하는 문자 외에 항상 널 문자를 저장합니다 (따라서 인자 배열은 최소 width+1 문자를 위한 공간이 있어야 합니다).
[set ]

set 문자 집합의 비어 있지 않은 문자 시퀀스와 일치합니다.

  • 집합의 첫 번째 문자가 ^이면 집합에 없는 모든 문자가 일치합니다.
  • 집합이 ] 또는 ^]로 시작하면 ] 문자도 집합에 포함됩니다.
  • 검사 집합의 초기 위치가 아닌 - 문자가 [0-9]에서처럼 범위를 나타낼 수 있는지는 구현 정의입니다.
  • 너비 지정자가 사용되면 최대 width까지만 일치합니다.
  • 일치하는 문자 외에 항상 널 문자를 저장합니다 (따라서 인자 배열은 최소 width+1 문자를 위한 공간이 있어야 합니다).
d

십진 정수와 일치합니다.

  • 숫자의 형식은 std::strtol에서 10 값에 대해 base 인수로 기대하는 형식과 동일합니다.
signed char* 또는 unsigned char*
signed short* 또는 unsigned short*
signed int* 또는 unsigned int*
signed long* 또는 unsigned long*
signed long long* 또는 unsigned long long*
std::intmax_t* 또는 std::uintmax_t*
std::size_t*
std::ptrdiff_t*
해당 없음
b (C++26)

부호 없는 이진 정수와 일치합니다.

  • 숫자의 형식은 std::strtoul에서 2 값에 대해 base 인수로 기대하는 형식과 동일합니다.
i

정수와 일치합니다.

  • 숫자의 형식은 std::strtol에서 0 값에 대해 base 인수로 기대하는 형식과 동일합니다 (기수는 구문 분석된 첫 번째 문자에 의해 결정됩니다).
u

부호 없는 십진 정수와 일치합니다.

  • 숫자의 형식은 std::strtoul에서 10 값에 대해 base 인수로 기대하는 형식과 동일합니다.
o

부호 없는 팔진 정수와 일치합니다.

  • 숫자의 형식은 std::strtoul에서 8 값에 대해 base 인수로 기대하는 형식과 동일합니다.
x
X

부호 없는 십육진 정수와 일치합니다.

  • 숫자의 형식은 std::strtoul에서 16 값에 대해 base 인수로 기대하는 형식과 동일합니다.
n

지금까지 읽은 문자 수를 반환합니다.

  • 입력을 소비하지 않습니다. 할당 횟수를 증가시키지 않습니다.
  • 지정자에 할당 억제 연산자가 정의된 경우, 동작은 정의되지 않습니다.
a (C++11)
A (C++11)
e
E
f
F (C++11)
g
G

부동 소수점 숫자와 일치합니다.

  • 숫자의 형식은 std::strtof에서 기대하는 형식과 동일합니다.
해당 없음 해당 없음
float*
double*
해당 없음 해당 없음 해당 없음 해당 없음
long double*
p

포인터를 정의하는 구현 정의 문자 시퀀스와 일치합니다.

  • printf 계열 함수는 %p 형식 지정자를 사용하여 동일한 시퀀스를 생성해야 합니다.
해당 없음 해당 없음
void**
해당 없음 해당 없음 해당 없음 해당 없음 해당 없음 해당 없음
참고 사항

n 이외의 모든 변환 지정자에 대해, 지정된 필드 너비를 초과하지 않으면서 변환 지정자가 정확히 기대하는 시퀀스이거나 기대하는 시퀀스의 접두사인 가장 긴 입력 문자 시퀀스가 스트림에서 소비됩니다. 이 소비된 시퀀스 이후의 첫 번째 문자(있는 경우)는 읽히지 않은 상태로 남습니다. 소비된 시퀀스의 길이가 0이거나 소비된 시퀀스를 위에 지정된 대로 변환할 수 없는 경우, 파일 끝, 인코딩 오류 또는 읽기 오류로 인해 스트림에서 입력이 차단되지 않는 한 일치 오류가 발생하며, 이 경우 입력 오류입니다.

% 지정자를 제외하고, 입력 항목(또는 %n의 경우 입력 문자 수)은 먼저 변환 지정자에 적합한 유형으로 변환됩니다. *로 할당이 억제되지 않은 경우, 변환 결과는 아직 쓰여지지 않은 다음 인자가 가리키는 객체에 기록됩니다. 이 객체가 적절한 유형을 가지고 있지 않거나 변환 결과를 객체에 표현할 수 없는 경우, 동작은 정의되지 않습니다.

[, c, n 이외의 모든 변환 지정자는 입력 구문 분석을 시도하기 전에 모든 선행 공백 문자를 소비하고 버립니다 (마치 std::isspace를 호출하는 것처럼 결정됨). 이러한 소비된 문자는 지정된 최대 필드 너비에 포함되지 않습니다.

변환 지정자 lc, ls, l[는 첫 번째 문자가 변환되기 전에 std::mbrtowc를 0으로 초기화된 std::mbstate_t 객체로 호출하는 것처럼 멀티바이트-와이드 문자 변환을 수행합니다.

변환 지정자 s와 [는 일치하는 문자 외에 항상 널 종결자를 저장합니다. 대상 배열의 크기는 지정된 필드 너비보다 최소 1 이상 커야 합니다. 대상 배열 크기를 지정하지 않고 %s 또는 %[를 사용하는 것은 std::gets만큼 안전하지 않습니다.

고정 너비 정수 유형(std::int8_t 등)에 대한 올바른 변환 지정은 헤더 <cinttypes>에 정의되어 있습니다 (SCNdMAX, SCNuMAX 등은 %jd, %ju 등과 동의어입니다).

각 변환 지정자의 동작 후 시퀀스 포인트가 있습니다. 이를 통해 동일한 "싱크" 변수에 여러 필드를 저장할 수 있습니다.

지수가 있고 숫자가 없는 불완전한 부동 소수점 값(예: 변환 지정자 "100er"로 %f 구문 분석)을 구문 분석할 때, "100e" 시퀀스(가능한 유효한 부동 소수점 숫자의 가장 긴 접두사)가 소비되어 일치 오류가 발생하고 (소비된 시퀀스를 부동 소수점 숫자로 변환할 수 없음), "r"이 남습니다. 일부 기존 구현은 이 규칙을 따르지 않고 "100"만 소비하도록 롤백하여 "er"를 남깁니다 (예: glibc 버그 1765).

변환 지정이 유효하지 않은 경우 동작은 정의되지 않습니다.

반환값

성공적으로 할당된 수신 인수의 개수(첫 번째 수신 인수가 할당되기 전에 일치 실패가 발생한 경우 0일 수 있음), 또는 EOF 첫 번째 수신 인수가 할당되기 전에 입력 실패가 발생한 경우.

복잡도

보장되지 않습니다. 특히 일부 구현에서는 std::sscanf 가 O(N) 인 경우가 있으며, 여기서 N = std:: strlen ( buffer ) [1] 입니다. 고성능 문자열 파싱을 위해서는 std::from_chars 를 참조하십시오.

참고 사항

대부분의 변환 지정자는 먼저 연속된 모든 공백을 소비하기 때문에, 다음과 같은 코드는

std::scanf("%d", &a);
std::scanf("%d", &b);

서로 다른 줄에 입력된 두 정수를 읽을 것입니다(두 번째 % d 가 첫 번째 입력 후 남은 개행 문자를 소비함) 또는 같은 줄에 공백이나 탭으로 구분된 두 정수를 읽을 것입니다(두 번째 % d 가 공백이나 탭을 소비함).

The conversion specifiers that do not consume leading whitespace, such as % c , can be made to do so by using a whitespace character in the format string:
std::scanf("%d", &a);
std::scanf(" %c", &c); // %d 이후의 개행 문자를 무시하고 문자 하나를 읽습니다

일부 std::sscanf 구현은 std::strlen 호출을 포함하므로, 전체 문자열 길이에 대해 런타임이 선형적으로 증가할 수 있습니다. 이는 std::sscanf 를 반복적으로 호출하여 문자열 앞부분에서 값을 파싱할 경우 코드가 2차 시간에 실행될 수 있음을 의미합니다 ( 예시 ).

예제

#include <clocale>
#include <cstdio>
#include <iostream>
int main()
{
    int i, j;
    float x, y;
    char str1[10], str2[4];
    wchar_t warr[2];
    std::setlocale(LC_ALL, "en_US.utf8");
    char input[] = "25 54.32E-1 Thompson 56789 0123 56ß水";
    // 다음과 같이 파싱:
    // %d: 정수
    // %f: 부동소수점 값
    // %9s: 최대 9개의 공백이 아닌 문자로 이루어진 문자열
    // %2d: 두 자리 정수 (숫자 5와 6)
    // %f: 부동소수점 값 (숫자 7, 8, 9)
    // %*d: 어디에도 저장되지 않는 정수
    // ' ': 모든 연속된 공백
    // %3[0-9]: 최대 3자리 숫자 문자열 (숫자 5와 6)
    // %2lc: 멀티바이트에서 와이드 문자로 변환하여 두 개의 와이드 문자
    const int ret = std::sscanf(input, "%d%f%9s%2d%f%*d %3[0-9]%2lc",
                                &i, &x, str1, &j, &y, str2, warr);
    std::cout << "Converted " << ret << " fields:\n"
                 "i = " << i << "\n"
                 "x = " << x << "\n"
                 "str1 = " << str1 << "\n"
                 "j = " << j << "\n"
                 "y = " << y << "\n"
                 "str2 = " << str2 << std::hex << "\n"
                 "warr[0] = U+" << (int)warr[0] << "\n"
                 "warr[1] = U+" << (int)warr[1] << '\n';
}

출력:

Converted 7 fields:
i = 25
x = 5.432
str1 = Thompson
j = 56
y = 789
str2 = 56
warr[0] = U+df
warr[1] = U+6c34

참고 항목

(C++11) (C++11) (C++11)
가변 인수 목록을 사용하여 stdin , 파일 스트림 또는 버퍼에서 형식화된 입력을 읽음
(함수)
파일 스트림에서 문자열을 가져옴
(함수)
형식화된 출력을 stdout , 파일 스트림 또는 버퍼에 출력
(함수)
(C++17)
문자 시퀀스를 정수 또는 부동 소수점 값으로 변환
(함수)
C 문서 for scanf , fscanf , sscanf