std::scanf, std::fscanf, std::sscanf
| Определено в заголовке <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 и сохраняет результаты в заданные места.
stream.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
|
Соответствует символу или последовательности символов.
|
N/A | N/A | char* |
wchar_t* |
N/A | N/A | N/A | N/A | N/A |
s
|
Соответствует последовательности непробельных символов (строка).
| |||||||||
[set ]
|
Соответствует непустой последовательности символов из набора символов.
| |||||||||
d
|
Соответствует десятичному целому числу.
|
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)
|
Соответствует беззнаковому двоичному целому числу.
| |||||||||
i
|
Соответствует целому числу.
| |||||||||
u
|
Соответствует беззнаковому десятичному целому числу.
| |||||||||
o
|
Соответствует беззнаковому восьмеричному целому числу.
| |||||||||
xX
|
Соответствует беззнаковому шестнадцатеричному целому числу.
| |||||||||
n
|
Возвращает количество прочитанных на данный момент символов.
| |||||||||
a (C++11)A (C++11)eEfF (C++11)gG
|
Соответствует числу с плавающей запятой.
|
N/A | N/A | float* |
double* |
N/A | N/A | N/A | N/A | long double* |
p
|
Соответствует последовательности символов, определяющей указатель, заданной реализацией.
|
N/A | N/A | void** |
N/A | N/A | N/A | N/A | N/A | N/A |
| Примечания | ||||||||||
|
Для каждого спецификатора преобразования, кроме За исключением спецификатора Все спецификаторы преобразования, кроме Спецификаторы преобразования Спецификаторы преобразования Правильные спецификации преобразования для целочисленных типов с фиксированной шириной (std::int8_t, и т.д.) определены в заголовке <cinttypes> (хотя SCNdMAX, SCNuMAX и т.д. являются синонимами Существует точка последовательности после действия каждого спецификатора преобразования; это позволяет хранить несколько полей в одной и той же «приёмной» переменной. При разборе неполного значения с плавающей запятой, которое заканчивается показателем степени без цифр, например, при разборе Если спецификация преобразования недействительна, поведение не определено. | ||||||||||
Возвращаемое значение
Количество успешно присвоенных принимающих аргументов (может быть равно нулю, если ошибка совпадения произошла до присвоения первого принимающего аргумента), или 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, файлового потока или буфера с использованием списка аргументов переменной длины (функция) |
| получает строку символов из файлового потока (функция) | |
(C++11) |
выводит форматированные данные в stdout, файловый поток или буфер (функция) |
(C++17) |
преобразует последовательность символов в целое число или значение с плавающей запятой (функция) |
Документация C по scanf, fscanf, sscanf
| |