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 и сохраняет результаты в заданные места.
stdin.stream.buffer.Параметры
| stream | - | входной поток файла для чтения |
| buffer | - | указатель на строку символов с нулевым завершением для чтения |
| format | - | указатель на строку символов с нулевым завершением, определяющую способ чтения входных данных |
| ... | - | принимающие аргументы |
Строка format состоит из
- неразрывных многобайтовых символов, кроме
%: каждый такой символ в строке format потребляет ровно один идентичный символ из входного потока или приводит к ошибке функции, если следующий символ в потоке не равен. - пробельных символов: любой одиночный пробельный символ в строке format потребляет все доступные последовательные пробельные символы из входного потока (определяются как при вызове
isspaceв цикле). Обратите внимание, что нет никакой разницы между"\n"," ","\t\t", или другими пробелами в строке format. - спецификаций преобразования. Каждая спецификация преобразования имеет следующий формат:
- вводный
%символ. - (необязательно) символ подавления присваивания
*. Если этот параметр присутствует, функция не присваивает результат преобразования ни одному из принимающих аргументов. - (необязательно) целое число (большее нуля), которое указывает максимальную ширину поля, то есть максимальное количество символов, которое функция разрешается потреблять при выполнении преобразования, указанного текущей спецификацией преобразования. Обратите внимание, что
%sи%[могут привести к переполнению буфера, если ширина не задана. - (необязательно) модификатор длины, который определяет размер принимающего аргумента, то есть фактический тип назначения. Это влияет на точность преобразования и правила переполнения. Значение типа назначения по умолчанию отличается для каждого типа преобразования (см. таблицу ниже).
- спецификатор формата преобразования.
Доступны следующие спецификаторы формата:
| Спецификатор преобразования | Описание | Тип аргумента | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Модификатор длины → |
hh (C++11) |
h | (нет) |
l |
ll (C++11) |
j (C++11) |
z (C++11) |
t (C++11) |
L |
|
% | Соответствует литералу %. | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д |
c | Сопоставляет символ или последовательность символов. Если используется спецификатор ширины, сопоставляет ровно ширину символов (аргумент должен быть указателем на массив с достаточным объемом). В отличие от %s и %[, не добавляет нулевой символ в массив. | Н/Д | Н/Д |
char* |
wchar_t* | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д |
s | Сопоставляет последовательность символов без пробелов (строка). Если используется спецификатор ширины, сопоставляет до ширины или до первого пробельного символа, что произойдёт раньше. Всегда сохраняет нулевой символ в дополнение к сопоставленным символам (следовательно, массив аргументов должен иметь место для по крайней мере ширины + 1 символов) |
|||||||||
[множество] | Сопоставляет непустую последовательность символов из набора символов множество. Если первый символ набора - |
|||||||||
d | Сопоставляет десятичное целое число. Формат числа такой же, как ожидается от |
signed char* или unsigned char*
|
signed short* или unsigned short*
|
signed int* или unsigned int*
|
signed long* или unsigned long*
|
signed long long* или unsigned long long*
|
intmax_t* или uintmax_t*
|
size_t* |
ptrdiff_t* | Н/Д |
i | Сопоставляет целое число. Формат числа такой же, как ожидается от |
|||||||||
u | Сопоставляет беззнаковое десятичное целое число. Формат числа такой же, как ожидается от |
|||||||||
o | Сопоставляет беззнаковое восьмеричное целое число. Формат числа такой же, как ожидается от |
|||||||||
x, X | Сопоставляет беззнаковое шестнадцатеричное целое число. Формат числа такой же, как ожидается от |
|||||||||
n | Возвращает количество прочитанных символов. Ввод не потребляется. Счет присваиваний не увеличивается. Если для спецификатора определен оператор подавления присваивания, поведение неопределено. |
|||||||||
a, A(C++11)e, Ef, Fg, G | Сопоставляет число с плавающей точкой. Формат числа такой же, как ожидается от | Н/Д | Н/Д |
float* |
double* | Н/Д | Н/Д | Н/Д | Н/Д |
long double* |
p | Сопоставляет реализацией определённую последовательность символов, определяющую указатель. Функции семейства | Н/Д | Н/Д |
void** | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д | Н/Д |
Для каждой спецификации преобразования, отличной от n, самая длинная последовательность входных символов, которая не превышает указанную ширину поля и которая либо точно соответствует ожидаемой спецификации преобразования, либо является префиксом последовательности, которую она ожидает, потребляется из потока. Первый символ, если таковой имеется, после этой последовательности остаётся непрочитанным. Если потребленная последовательность имеет нулевую длину или если потребленная последовательность не может быть преобразована, как указано выше, происходит неудача сопоставления, за исключением случаев окончания файла, ошибки кодирования или ошибки чтения из потока, в которых случае происходит ошибка ввода.
Все спецификаторы преобразования, отличные от [, c, и n, потребляют и отбрасывают все ведущие пробельные символы (определяемые как при вызове isspace) перед попыткой разобрать ввод. Эти потреблённые символы не учитываются в указанной максимальной ширине поля.
Спецификаторы преобразования lc, ls, и l[ выполняют преобразование многобайтовых символов в символы широкого типа так, как если бы они вызывали mbrtowc с объектом mbstate_t, инициализированным нулём перед преобразованием первого символа.
Спецификаторы преобразования s и [ всегда сохраняют нулевой терминатор в дополнение к соответствующим символам. Размер целевого массива должен быть по крайней мере на один больше, чем указанная ширина поля. Использование %s или %[, без указания размера целевого массива, так же небезопасно, как и std::gets.
Правильные спецификации преобразования для целочисленных типов фиксированной ширины (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, потока файла или буфераиспользуя список аргументов переменной длины (функция) |
| получает строку символов из потока файла (функция) |
|
|
(C++11) | выводит форматированный вывод в stdout, поток файла или буфер (функция) |
|
(C++17) | преобразует последовательность символов в целочисленное или с плавающей точкой значение (функция) |
Документация на C по scanf, fscanf, sscanf |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/io/c/fscanf