Осуществляющая ввод функция SCANF является аналогомPRINTF и позволяет проводить в обратном направлении многиеиз тех же самых преобразований. Функция SCANF(CONTROL, ARG1, ARG2, ...) читает символы из стандартного ввода, интерпретирует их всоответствии с форматом, указанном в аргументе CONTROL, ипомещает результаты в остальные аргументы. Управляющий аргу-мент описывается ниже; другие аргументы, каждый из которыхдолжен быть указателем, определяют, куда следует поместитьсоответствующим образом преобразованный ввод. Управляющая строка обычно содержит спецификации преобра-зования, которые используются для непосредственной интерпре-тации входных последовательностей. Управляющая строка можетсодержать:- пробелы, табуляции или символы новой строки ("символы пус- тых промежутков"), которые игнорируются. - Обычные символы (не %), которые предполагаются совпадающи- ми со следующими отличными от символов пустых промежутков символами входного потока.- Спецификации преобразования, состоящие из символа %, нео- бязательного символа подавления присваивания *, необяза- тельного числа, задающего максимальную ширину поля и сим- вола преобразования. Спецификация преобразования управляет преобразованиемследующего поля ввода. нормально результат помещается в пе-ременную, которая указывается соответствующим аргументом.Если, однако , с помощью символа * указано подавление прис-ваивания, то это поле ввода просто пропускается и никакогоприсваивания не производится. Поле ввода определяется какстрока символов, которые отличны от символов простых проме-жутков; оно продолжается либо до следующего символа пустогопромежутка, либо пока не будет исчерпана ширина поля, еслиона указана. Отсюда следует, что при поиске нужного ей вво-да, функция SCANF будет пересекать границы строк, посколькусимвол новой строки входит в число пустых промежутков. Символ преобразования определяет интерпретацию поля вво-да; согласно требованиям основанной на вызове по значениюсемантики языка "с" соответствующий аргумент должен бытьуказателем. Допускаются следующие символы преобразования:D - на вводе ожидается десятичное целое; соответствующий ар- гумент должен быть указателем на целое.O - На вводе ожидается восьмеричное целое (с лидирующим ну- лем или без него); соответствующий аргумент должен быть указателем на целое.X - На вводе ожидается шестнадцатеричное целое (с лидирующи- ми 0X или без них); соответствующий аргумент должен быть указателем на целое.H - На вводе ожидается целое типа SHORT; соответсвующий ар- гумент должен быть указателем на целое типа SHORT.C - Ожидается отдельный символ; соответствующий аргумент должен быть указателем на символы; следующий вводимый символ помещается в указанное место. Обычный пропуск сим- волов пустых промежутков в этом случае подавляется; для чтения следующего символа, который не является символом пустого промежутка, пользуйтесь спецификацией преобразо- вания %1S.S - Ожидается символьная строка; соответствующий аргумент должен быть указателем символов, который указывает на массив символов, который достаточно велик для принятия строки и добавляемого в конце символа \0.F - Ожидается число с плавающей точкой; соответствующий ар- гумент должен быть указателем на переменную типа FLOAT.Е - символ преобразования E является синонимом для F. Формат ввода переменной типа FLOAT включает необязательный знак, строку цифр, возможно содержащую десятичную точку и нео- бязательное поле экспоненты, состоящее из буквы E, за ко- торой следует целое, возможно имеющее знак. Перед символами преобразования D, O и X может стоять L,которая означает , что в списке аргументов должен находитьсяуказатель на переменную типа LONG, а не типа INT. Аналогич-но, буква L может стоять перед символами преобразования Eили F, говоря о том, что в списке аргументов должен нахо-диться указатель на переменную типа DOUBLE, а не типа FLOAT. Например, обращениеINT I;FLOAT X;CHAR NAME[50];SCANF("&D %F %S", &I, &X, NAME); со строкой на вводе 25 54.32E-1 THOMPSON приводит к присваиванию I значения 25,X - значения 5.432 иNAME - строки "THOMPSON", надлежащим образом законченнойсимволом \ 0. эти три поля ввода можно разделить столькимипробелами, табуляциями и символами новых строк, сколько выпожелаете. Обращение INT I; FLOAT X; CHAR NAME[50]; SCANF("%2D %F %*D %2S", &I, &X, NAME); с вводом 56789 0123 45A72 присвоит I значение 56, X - 789.0, пропустит 0123 и поместитв NAME строку "45". при следующем обращении к любой процеду-ре ввода рассмотрение начнется с буквы A. В этих двух приме-рах NAME является указателем и, следовательно, перед ним ненужно помещать знак &. В качестве другого примера перепишем теперь элементарныйкалькулятор из главы 4, используя для преобразования вводафункцию SCANF: #INCLUDE <STDIO.H> MAIN() /* RUDIMENTARY DESK CALCULATOR */ \( DOUBLE SUM, V; SUM =0; WHILE (SCANF("%LF", &V) !=EOF) PRINTF("\T%.2F\N", SUM += V); \) выполнение функции SCANF заканчивается либо тогда, когда онаисчерпывает свою управляющую строку, либо когда некоторыйэлемент ввода не совпадает с управляющей спецификацией. Вкачестве своего значения она возвращает число правильно сов-падающих и присвоенных элементов ввода. Это число может быть использовано для определения количества найденных элементовввода. при выходе на конец файла возвращается EOF; подчерк-нем, что это значение отлично от 0, что следующий вводимыйсимвол не удовлетворяет первой спецификации в управляющейстроке. При следующем обращении к SCANF поиск возобновляетсянепосредственно за последним введенным символом. Заключительное предостережение: аргументы функции SCANFдолжны быть указателями. Несомненно наиболее распространен-ная ошибка состоит в написании SCANF("%D", N); вместо SCANF("%D", &N);