Namespaces
Variants

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

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

10진 정수와 일치.

  • 숫자의 형식은 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)

부호 없는 2진 정수와 일치.

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

정수와 일치.

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

부호 없는 10진 정수와 일치.

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

부호 없는 8진 정수와 일치.

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

부호 없는 16진 정수와 일치.

  • 숫자의 형식은 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[는 첫 번째 문자가 변환되기 전에 0으로 초기화된 std::mbrtowc을 std::mbstate_t 객체와 함께 호출하는 것처럼 멀티바이트-와이드 문자 변환을 수행합니다.

변환 지정자 s 및 [는 일치된 문자 외에 항상 널 종결자를 저장합니다. 대상 배열의 크기는 지정된 필드 너비보다 적어도 하나는 커야 합니다. 대상 배열 크기를 지정하지 않고 %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는 공백이나 탭을 소비함).

%c와 같이 선행 공백을 소비하지 않는 변환 지정자는 형식 문자열에 공백 문자를 사용하여 그렇게 만들 수 있습니다:

std::scanf("%d", &a);
std::scanf(" %c", &c); // ignore the endline after %d, then read a char

일부 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ß水";
    // parse as follows:
    // %d: an integer 
    // %f: a floating-point value
    // %9s: a string of at most 9 non-whitespace characters
    // %2d: two-digit integer (digits 5 and 6)
    // %f: a floating-point value (digits 7, 8, 9)
    // %*d an integer which isn't stored anywhere
    // ' ': all consecutive whitespace
    // %3[0-9]: a string of at most 3 digits (digits 5 and 6)
    // %2lc: two wide characters, using multibyte to wide conversion
    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 문서 scanf, fscanf, sscanf
용