Namespaces
Variants

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

С ru.cppreference.net
< cpp | io | c
 
 
Библиотека ввода/вывода
Манипуляторы ввода/вывода
Функции печати (C++23)
Си-стиль ввода/вывода
Буферы
(C++98/26*)
Потоки
Абстракции
Файловый ввод/вывод
Строковый ввод/вывод
Массивовый ввод/вывод
(C++98/26*)
(C++98/26*)
(C++98/26*)
Синхронизированный вывод
Типы
Интерфейс категории ошибок
(C++11)
 
Си-стиль ввода/вывода
Типы и объекты
Функции
Доступ к файлам
Прямой ввод/вывод
Неформатированный ввод/вывод
Форматированный ввод
(C++11)(C++11)(C++11)    
(C++11)(C++11)(C++11)    
Форматированный вывод
Позиционирование в файле
Обработка ошибок
Операции с файлами
 
Определено в заголовке <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" или другими пробельными символами в строке формата.
  • спецификаций преобразования. Каждая спецификация преобразования имеет следующий формат:
  • вводный символ %.
  • (необязательно) символ подавления присваивания *. Если эта опция присутствует, функция не присваивает результат преобразования никакому принимающему аргументу.
  • (необязательно) целое число (больше нуля), которое задает максимальную ширину поля, то есть максимальное количество символов, которое функция может потребить при выполнении преобразования, заданного текущей спецификацией преобразования. Обратите внимание, что %s и %[ могут привести к переполнению буфера, если ширина не указана.
  • (необязательно) модификатор длины, который задает размер принимающего аргумента, то есть фактический тип назначения. Это влияет на точность преобразования и правила переполнения. Тип назначения по умолчанию различается для каждого типа преобразования (см. таблицу ниже).
  • спецификатор формата преобразования.

Доступны следующие спецификаторы формата:

Спецификатор
преобразования
Пояснение Ожидаемый
тип аргумента
Модификатор длины→ hh h нет l ll j z t L
Доступно только с C++11→ Да Да Да Да Да
%
Соответствует литералу %.
N/A N/A N/A N/A N/A N/A N/A N/A N/A
c

Соответствует символу или последовательности символов.

  • Если используется спецификатор ширины, соответствует ровно width символам (аргумент должен быть указателем на массив достаточного размера).
  • В отличие от %s и %[, не добавляет нулевой символ в массив.
N/A N/A
char*
wchar_t*
N/A N/A N/A N/A N/A
s

Соответствует последовательности непробельных символов (строка).

  • Если используется спецификатор ширины, соответствует не более чем width символам или до первого пробельного символа, в зависимости от того, что встретится раньше.
  • Всегда сохраняет нулевой символ в дополнение к сопоставленным символам (поэтому массив аргумента должен иметь место как минимум для width+1 символов).
[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*
N/A
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.
N/A N/A
float*
double*
N/A N/A N/A N/A
long double*
p

Соответствует последовательности символов, определяющей указатель, заданной реализацией.

  • printf Семейство функций должно создавать ту же последовательность с использованием спецификатора формата %p.
N/A N/A
void**
N/A N/A N/A N/A N/A N/A
Примечания

Для каждого спецификатора преобразования, кроме n, потребляется самая длинная последовательность входных символов, не превышающая заданную ширину поля и которая либо является именно тем, что ожидает спецификатор преобразования, либо является префиксом последовательности, которую он ожидает. Первый символ после этой потреблённой последовательности, если он есть, остаётся непрочитанным. Если длина потреблённой последовательности равна нулю или если потреблённую последовательность невозможно преобразовать, как указано выше, происходит ошибка совпадения, если только конец файла, ошибка кодирования или ошибка чтения не помешали вводу из потока; в этом случае это ошибка ввода.

За исключением спецификатора %, входной элемент (или для %n количество входных символов) сначала преобразуется в тип, соответствующий спецификатору преобразования. Если присваивание не было подавлено с помощью *, результат преобразования записывается в объект, на который указывает следующий аргумент, который ещё не был записан. Если этот объект не имеет подходящего типа или если результат преобразования не может быть представлен в объекте, поведение не определено.

Все спецификаторы преобразования, кроме [, c и n, потребляют и отбрасывают все начальные пробельные символы (определяется как при вызове std::isspace) перед попыткой разбора входных данных. Эти потреблённые символы не засчитываются в указанную максимальную ширину поля.

Спецификаторы преобразования lc, ls и l[ выполняют преобразование многобайтового символа в широкий символ, как при вызове 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.

Если спецификация преобразования недействительна, поведение не определено.

Возвращаемое значение

Количество успешно присвоенных принимающих аргументов (может быть равно нулю, если ошибка совпадения произошла до присвоения первого принимающего аргумента), или 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 вызывается в цикле для многократного разбора значений из начала строки, ваш код может выполняться за квадратичное время (пример).

Пример

#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