Рассмотрим простой пример:
int num;
scanf("Hello %d", &num);
Вызов функции scanfбудет успешным, только если следующие пять символов в стандартном вводе — Hello. Затем, если следующие символы формируют распознаваемое десятичное число, оно будет считано и присвоено переменной num. Пробел в строке формата при вводе применяется для игнорирования во вводном файле всех пробельных символов (пробелы, табуляции, переводы страницы и переходы на новую строку) между спецификаторами преобразований. Это означает, что вызов, scanfбудет успешным и поместит 1234 в переменную numв случае следующих двух вариантов ввода.
Hello 1234
Hellol234
Пробельные символы обычно игнорируются во вводе, когда начинается преобразование. Это означает, что строка формата %dбудет продолжать чтение из вводного файла, пропуская пробелы и переходы на новую строку до тех пор, пока будет продолжаться цифровая последовательность. Если ожидаемые символы отсутствуют, преобразование аварийно завершается и выполнение функции прекращается.
Примечание
Если не соблюдать осторожность, могут возникнуть проблемы. В вашей программе может появиться бесконечный цикл, если во вводе оставить нецифровой символ при считывании целых чисел.
К другим спецификаторам преобразований относятся следующие:
□ %d— считывание десятичного целого;
□ %o, %x— считывание восьмеричного, шестнадцатеричного целого;
□ %f, %e, %g— считывание числа с плавающей запятой;
□ %c— считывание символа (пробельный символ не пропускается);
□ %s— считывание строки;
□ %[]— считывание множества символов (см. последующее обсуждение);
□ %%— считывание знака %.
Как и в случае printf, у спецификаторов преобразований функции scanfесть ширина поля, ограничивающая объем ввода. Спецификатор размера ( hдля коротких или lдля длинных целых) показывает, короче или длиннее стандартного получаемый аргумент. Таким образом, %hdобозначает число типа short int, %ld— число типа long intи %lg— число с плавающей точкой двойной точности.
Спецификатор, начинающийся со звездочки, указывает на то, что элемент игнорируется. Это значит, что информация не сохраняется, и, следовательно, для ее получения не нужна переменная.
Применяйте спецификатор %cдля чтения одиночного символа во вводе. Он не пропускает начальные пробельные символы.
Используйте спецификатор %sдля чтения строк, но будьте осторожны. Он пропускает ведущие пробельные символы, но останавливается перед первым пробельным символом, встретившимся в строке, поэтому лучше применять его для чтения слов, а не целых строк. Кроме того, длина строки, которую он может прочесть, ограничивается только спецификатором ширины поля, поэтому принимающая строка должна быть достаточной для хранения самой длинной строки из вводного потока.
Лучше применять спецификатор ширины поля или комбинацию функций fgetsи sscanfдля считывания строки ввода, а затем просматривать ее. Это защитит от возможных переполнений буфера, которые может спровоцировать злонамеренный пользователь.
Применяйте спецификатор %[]для чтения строки, составленной из символов, включенных в множество. Формат %[A-Z]будет читать строку из прописных букв латинского алфавита. Если в множестве первый символ — знак вставки ( ^), то спецификатор считывает строку, состоящую из символов, не входящих в множество. Итак, для того чтобы прочитать строку с пробелами, но остановиться на первой запятой, примените спецификатор %[^, ].
Если задана следующая строка ввода:
Hello, 1234, 5.678, X, string to the end of the line
приведенный далее вызов scanfкорректно считает четыре элемента:
char s[256];
int n;
float f;
char c;
scanf("Hello, %d, %g, %c, %[^\n]", &n, &f, &c, s);
Функции семейства scanfвозвращают количество успешно считанных элементов. Оно может быть нулевым, если сбой возник при чтении первого элемента. Если достигнут конец ввода прежде, чем найдено соответствие первому элементу, возвращается EOF. Если в файловом потоке возникает ошибка чтения, устанавливается флаг ошибки потока и тип ошибки задается в переменной errno. Более подробную информацию см. в разд. "Ошибки потока" далее в этой главе.
Читать дальше