Scanf
scanf
Функция Выполняет форматированный ввод из потока stdin.
Синтаксис #include
int scanf(const char *format [,adress, ...]);
Файл, содержащий stdio.h прототип
Описание Функция scanf просматривают входные поля, символ за символом, считывая их из потока stdin. Затем каждое поле форматируется в соответствии со спе- цификацией формата, передаваемой scanf аргументом format. После этого она записывает отформатиро- ванный ввод по адресам, задаваемым аргументами, следующими за форматной строкой. Число специфика- ций формата должно соответствовать числу адресов.
Строка формата.
Строка формата, присутствующая в каждом вызове функций семейства ...scanf, управляет тем, каким образом каждая функция будет считывать, преобра- зовывать и записывать входные поля. Для заданных спецификаций формата должно быть достаточное ко- личество адресных аргументов; если это не соблю- дается, результат может быть непредсказуемым и, вероятно ошибочным. Лишние адресные аргументы (больше, чем требует формат) будут игнорированы.
Примечание. scanf часто приводит к непредсказуе- мым результаттам, когда вы отклоняетесь от точно- го шаблона. Вам необходимо помнить, что нужно указать scanf, каким образом синхронизировать ко- нец строки. В результате предпочтительнее на наш взгляд комбинация gets или fgets, за которыми следует sscanf.
Строка фомата - это символьная строка, содержащая три типа объектов: незначащие символы, значащие символы и спецификации формата.
Незначащие символы - это пусто ( ), знак табуля- ции (\t) и символ перехода на новую строку (\n). Как только функция семейства ...scanf встречает незначащий символ в строке формата, она считыва- ет, но не сохраняет все последующие незначащие символы до тех пор, пока не встретится первый значащий символ.
Значащие символы - это все символы ASCII, за иск- лючением знака процента (%). Если функция семейс- тва ...scanf встречает в форматной строке значаю- щий символ, она считывает, но не сохраняет данный символ.
Спецификация формата управляет процессом чтения и преобразования из входных полей в значения специ- альных типов и записывает их по адресам, постав- ляемых адресными аргументами.
Хвостовые незначащие символы остаются несчитанны- ми (включая символ перехода на новую строку), ес- ли они не встретились явно в строке формата.
Спецификации формата.
Спецификации формата функций ... scanf имеют сле- дующую форму:
%[*] [ширина] [F/N] [h/l/L] символ типа
Спецификация формата начинается со знака %. После этого знака следует спецификации в определенном порядке:
- необязательный символ подавления назначения [*]; - необязательный спецификатор ширины [width]; - необязательный модификатор размера указателя [F/N]; - необязательный модификатор типа аргумента [h/l/L]; - символ типа.
Необязательные компоненты форматной строки.
Далее перечислены основные принципы форматирова- ния и спецификаторы форматной строки:
-----------------T--------------------------------------------------- Символ или ¦ Каким образом он управляет форматом. спецификатор ¦ -----------------¦--------------------------------------------------- * ¦ подавляет назначение следующего входного поля; width ¦ максимальное число считываемых символов; если ¦ функция ...scanf встречает незначащий или непреоб- ¦ разуемый символ, могут быть прочитаны дополнитель- ¦ ные символы; size ¦ отвергает заданный по умолчанию размер адресного ¦ аргумента ¦ (N - ближний указатель, ¦ F - дальний указатель) тип ¦ отвергает заданный по умолчанию адресный аргумент аргумента ¦ (h - короткое целое, ¦ l - длинное целое, если символ типа указывает ¦ целочисленное преобразование ¦ l - двойной точности, если символ типа указывает ¦ на преобразование чисел с плавающей точкой ¦ L - длинное, двойной точности (допустимо только ¦ при преобразовании чисел с плавающей точкой -----------------+---------------------------------------------------
Символы типов для функций ...scanf.
В следующей таблице перечислены символы типов для функций семейства ...scanf, ожидаемый тип ввода и формат, в котором будет сохранен данный ввод.
Информация в данной таблице подразумевает, что никакие спецификаторы или модификаторы не были включены в спецификацию формата. Чтобы увидеть, как включение в формат некоторых спецификаторов или модификаторов влияет на вводимые данные, смотрите таблицу, следующую за данной:
-------T----------------T-------------------------------------------- Символ ¦ Ожидаемый ввод ¦ Тип аргумента типа ¦ ¦ -------+----------------+-------------------------------------------- Числовые данные. -------T----------------T-------------------------------------------- d ¦ десятичное ¦ указатель на целое (int *arg) ¦ целое ¦ D ¦ десятичное ¦ указатель на длинное целое (long *arg) ¦ целое ¦ o ¦ восьмеричное ¦ указатель на целое (int *arg) ¦ целое ¦ O ¦ восьмеричное ¦ указатель на длинное целое (long *arg) ¦ целое ¦ i ¦ десятичное, ¦ указатель на длинное целое (long *arg) ¦ восьмеричное ¦ ¦ или шестнадца- ¦ ¦ теричное целое ¦ u ¦ десятичное ¦ указатель на целое без знака (unsigned ¦ целое без знака¦ int *arg) U ¦ десятичное ¦ указатель на длинное целое без знака ¦ целое без знака¦ (unsigned long *arg) x ¦ шестнадцатерич-¦ указатель на целое (int *arg) ¦ ное целое ¦ X ¦ шестнадцатерич-¦ указатель на длиное целое (long *arg) ¦ ное целое ¦ e ¦ число с плаваю-¦ указатель на число с плавающей точкой ¦ щей точкой ¦ (float *arg) E ¦ число с плаваю-¦ указатель на число с плавающей точкой ¦ щей точкой ¦ (float *arg) f ¦ число с плаваю-¦ указатель на число с плавающей точкой ¦ щей точкой ¦ (float *arg) g ¦ число с плаваю-¦ указатель на число с плавающей точкой ¦ щей точкой ¦ (float *arg) G ¦ число с плаваю-¦ указатель на число с плавающей точкой ¦ щей точкой ¦ (float *arg) -------+----------------+-------------------------------------------- Символьные данные. -------T----------------T-------------------------------------------- s ¦ строка символов¦ указатель на массив символов (char arg[ ]) c ¦ символ ¦ указатель на символ (char *arg); если шири- ¦ ¦ на поля w задается вместе с символом типа c ¦ ¦ (как напр. %5c): указатель на массив из w ¦ ¦ символов (char arg[w]); % ¦ символ % ¦ Никакого преобразования не происходит; сим- ¦ ¦ вол % сохраняется. -------+----------------+-------------------------------------------- Указатели. -------T----------------T-------------------------------------------- n ¦ (отсутствует) ¦ указатель на целое (int *arg) ¦ ¦ данный указатель хранит количество считан- ¦ ¦ ных символов до %n. p ¦ шестнадцатерич-¦ указатель на данный объект (дальний * или ¦ ное число в ¦ ближний *). ¦ форме: ¦ Преобразования %p предусматривают стандарт- ¦ YYYY:ZZZZ ¦ ный размер указателя, принятый в данной мо- ¦ или ZZZZ ¦ дели памяти. -------+----------------+--------------------------------------------
Входные поля.
Входным полем может быть одно из следующих выра- жений:
- все символы до (но не включая) следующего по порядку незначающего символа;
- все символы до первого встретившегося, который не может быть преобразован текущей спецификаци- ей формата (такие, например, как цифры 8 и 9 при восьмеричном формате).
- до n символов, где n - это заданная ширина по- ля.
Соглашения.
Далее перечислены некоторые соглашения, принятые для определенных спецификаций формата.
преобразование %c
Данная спецификация позволяет считывать 1, следу- ющий по порядку символ, включая и незначащие. Чтобы пропустить один незначащий и прочесть сле- дующий значащий символ, используйте %1s.
Преобразование %Wc (W - спецификация ширины).
Адресный аргумент является указателем на массив символов; массив состоит из W элементов (char arg[W]).
Преобразование %s
Адресный аргумент является указателем на массив символов (char arg[]).
Размер массива должен быть по крайней мере (n+1) байтов, где n = длина строки s (в символах). Входное поле оканчивается пробелом или символом перехода на новую строку. К символьной строке ав- томатически добавляется нулевое окончание и запи- сывается, как последний элемент массива.
Преобразование %[search set]
Набор символов, заключенный в квадратные скобки, может быть заменен на символ типа s. Адресный ар- гумент является указателем на массив символов (char arg[]). В квадратные скобки заключен набор символов, который определяет "искомый набор" воз- можных символов, формирующих строку (входное по- ле).
Если первый символ в скобках - это символ (^), искомый набор инвертируется таким образом, чтобы содержать все символы ASCII кроме тех, что пере- числены между квадратными скобками. (Обычно, сим- вол будет включен в инвертированный искомый на- бор, если он не указан явно в списке символов после первого знака).
Входное поле представляет собой строку символов, не ограниченную незначащими символами. Функции семейства ...scanf будут считывать входное поле до тех пор, пока не появится первый символ, от- сутствующий в искомом наборе (или в инвертирован- ном искомом наборе). Далее приведены два примера данного типа преобразования:
%[abcd] будет производиться поиск во входном поле любых из символов a, b, c, d.
%[^abcd] будет производиться поиск во входном поле любых символов, кроме a, b, c, d.
Здесь вы можете также указать диапазон (чисел или символов). Это короткая запись. К примеру для по- иска десятичной цифры во входном потоке можно указать: %[0123456789] или тоже самое, но короче: %[0-9] Для поиска символов вы можете использовать следу- ющие сокращения:
%[A-Z] Все символы верхнего регистра %[0-9A-Za-z] Все десятичные цифры и все сим- волы (и верхнего и нижнего ре- гистра). %[A-FT-Z] Все символы верзхнего регистра с A по F и c T по Z
В такой сокращенной записи необходимо придержи- ваться следующих правил:
- Символ предшествующий тире (-) должен быть лек- сически меньше символа, находящегося правее ти- ре;
- Символ тире не должен быть ни первым, ни пос- ледним в наборе символов. Если он первый или последний, то он рассматривается просто как символ, а не как указатель диапазона.
- Символы являющиеся краями диапазона (т.е. слева и справо от тире) не должны входить в другой диапазон.
Ниже приведено несколько примеров, в которых символ тире выступает не в качестве указателя диапазона, а в качестве обычного символа.
%[-+*/] Четыре арифметических операции %[z-a] Символы z, - и a. %[+0-9-A-Z] Символы + и - и диапазон от 0 до 9 и от A до Z %[+0-9A-Z-] Также символы + и - и диапазон от 0 до 9 и от A до Z %[^-0-9+A-Z] Все символы, исключая + и - и символы в диапазоне от 0 до 9 и от A до Z
преобразования %e, %E, %f, %g, %G (с плавающей точкой.
Числа с плавающей точкой во входном поле должны соответствовать следующему формату:
[+/-]ddddddddd [.]dddd [E|e] [+/-]ddd,
где заключение знаков в квадратные скобки означа- ет их необязательность, а ddd- представляет деся- тичные, восьмеричные и шестнадцатеричные цифры.
Кроме этого +INF, -INF, +NAN, -NAN распознаются как числа сплавающей точкойю При этом знак должен присутсвовоать обязательно (INF - бесконечность, NAN - не число). преобразования %d,%i,%o,%x,%D,%I,%O,%X,%c,%h.
В любом преобразовании, в котором разрешены ука- затели на символ, целое, длинное целое, могут быть использованы указатели на символ без знака, целое без знака, длинное целое без знака.
Символ подавления присвоения.
Символом подавления назначения является звездочка (*); Не путайте его символом адресации в языке СИ (также звездочка).
Если данный символ (*) следует за знаком % в спе- цификации формата, следующее входное поле будет считано, но не будет присвоено соответствующему адресному аргументу. Предполагается, что подавля- емое входное поле соответствует типу, объявленно- му вслед за символом *. Точное символьное соот- ветствие и подавление присвоения не связаны между собой непосредственно.
Спецификаторы ширины.
Спецификатор ширины (n), десятичное целое, конт- ролирует максимальное число символов, которое бу- дет прочитано из текущего входного поля.
Если входное поле содержит менее n символов, фун- кции семейства ...scanf прочтут все символы дан- ного поля, затем перейдут к следующему полю и со- ответствующей ему спецификации формата.
Если до того, как будет прочитано n символов, встретится незначащий символ или неконвертируемый символ, то все символы до данного будут считаны и преобразованы, затем функция перейдет к следующе- му полю и спецификации формата.
Неконвертируемым символом считается такой символ, который не может быть преобразован в соответствии с данной спецификацией формата (например, символы 8 или 9 при восмеричном формате, или символы J или K при шестнадцатеричном или десятичном форма- те). --------------T------------------------------------------------------ Спецификатор ¦ Как спецификатор ширины влияет на сохраняемый ширины ¦ ввод. --------------+------------------------------------------------------ n ¦ До n символов будет считано, преобразовано и запи- ¦ сано в текущий адресный аргумент. --------------+------------------------------------------------------
Модификаторы размера ввода и типа аргумента.
Модификаторы размера ввода (N и F) и типа аргу- мента (h,l и L) оказывают влияние на то, каким образом функции ...scanf интерпретируют соответс- твующие адресные аргументы arg.
Модификаторы F и N отвергают заданные стандартно или объявленные размеры аргумента arg.
Модификаторы h, l и L обозначают, какой тип пре- образования будет использоваться для следующих за ними входных данных (h- короткое целое, l- длин- ное целое, L - длинное двойной точности). Входные данные будут преобразованы в заданный тип, и ар- гумент arg для входных данных будет адресовать объект соответствующего размера ("короткий" объ- ект для %h и длинный или двойной точности объект для %l или %L). -------------T------------------------------------------------------- Модификатор ¦ Как он влияет на преобразование -------------+------------------------------------------------------- F ¦ Отвергает заданный по умолчанию или объявленный раз- ¦ мер; ¦ arg интерпретируется, как дальний указатель. N ¦ Отвергает заданный по умолчанию или объявленный раз- ¦ мер; ¦ arg интерпретируется, как ближний указатель. ¦ В сверхбольшой моделе не может использоваться ни с ¦ какими преобразованиями. h ¦ Для типов d,i,o,u,x: конвертирует ввод в короткое це- ¦ лое, записывает в "короткий" объект. ¦ Для типов D,I,O,C,X: не оказывает влияния. ¦ Для типов e,f,c,s,n,p: не оказывает влияния. l ¦ Для типов d,i,o,u,x: преобразует ввод в длинное целое, ¦ записывает в "длинный" объект. ¦ Для типов e,f: преобразует ввод в число двойной точ- ¦ ности, записывает в объект двойной точности. ¦ Для типов D,I,O,U,X: не оказывает влияния. ¦ Для типов c,s,n,p: не оказывает влияния. L ¦ Для типов e, f, g: преобразует введенные данные в ¦ длинное двойной точности, и сохраняет их в объекте с ¦ тем же типом. На остальные форматы влияния не оказы- ¦ вает. -------------+-------------------------------------------------------
Когда функции ...scanf прекращают считывание.
Функции семейства ...scanf могут прекратить счи- тывание определенного входного поля до достижения нормального конца данных (незначащий символ), или считывание может завершиться на середине данных (по различным причинам).
Функции ...scanf прекратят считывание, запишут текущее поле и перейдут к обработке следующего поля в следующих случаях:
-Символ подавления присвоения (*) появляется в спецификации формата после знака процента %; те- кущее поле считывается, но не запоминается.
-Считано width символов (width - спецификатор ши- рины, положительное десятичное целое).
-Следующий считанный символ не может быть конвер- тирован при действующем формате (например, сим- вол A, если формат-десятичный).
-Следующий считанный символ входного поля отсутс- твует в "поисковом" наборе (или, наоборот, при- сутствует в инвертированном "поисковом" наборе).
Когда одна из функций ...scanf прекращает считы- вание текущего входного поля по одной из вышеопи- санных причин, подразумевается, что следующий несчитанный символ будет первым символом следую- щего входного поля, или первым символом следующей операции чтения.
Функции семейства ...scanf заканчивают свою рабо- ту при следующих ситуациях:
-Следующий по порядку символ входного поля не со- ответствует относящемуся к нему значащему симво- лу в строке формата.
-Следующий символ во входном поле - EOF.
-Строка формата исчерпана.
Если в строке формата появляется последователь- ность символов, не являющаяся частью спецификации формата, она должна совпадать с текушей последо- вательностью символов входного поля; функции ...scanf считывают, но не сохраняют совпадающие символы. Когда встречается конфликтный символ, он остается во входном поле, как бы непрочитанным.
Возвращаемое Функция scanf возвращают количество успешно прочи- значение танных, преобразованных и запомненных входных по- лей; возвращаемое значение не включает в себя прочитанные поля, которые не были сохранены.
Если одна из данных функций делает попытку чтения в конце файла (EOF), возвращаемым значением будет EOF.
Если не было записано ни одного поля, возвращает- ся значение 0.
Переносимость scanf поддерживается на системах UNIX и определена в стандарте ANSI C. Определены у Кернигана и Рит- чи.
Смотрите также
#include
#include
int main(void) { char label[20]; char name[20]; int entries = 0; int loop,age; double salary; struct Entry_struct { char name[20]; int age; float salary; } entry[20]; /* ввести заглавие, как строку, длиной до 20 символов */ printf("Введите заглавие для диаграммы: "); scanf("%20s",label); fflash(stdin); /* сбросить входной поток, в случае ошибки */ /* ввести число элементов в виде целого */ printf("Сколько элементов (не > 20): "); scanf("%d",&entries); fflash(stdin); /* сбросить входной поток, в случае ошибки */ for(loop = 0; loop < entries; ++loop) { printf("Элемент %d\n",loop); /* ввести имя, только буквы в верхнем или нижнем регистре */ printf("Имя: "); scanf("%[A_Za-z]",entry[loop].name); fflash(stdin); /* сбросить входной поток, в случае ошибки */ /* ввести возраст, как целое число */ printf("Возраст: "); scanf("%d",&entry[loop].age); fflash(stdin); /* сбросить входной поток, в случае ошибки */ /* ввести размер зарплаты как float */ printf("Зарплата: "); scanf("%f",&entry[loop].salary); fflash(stdin); /* сбросить входной поток, в случае ошибки */ } /* ввести имя, возраст и зарплату как строку, целое и число с пла- вающей точкой, соответственно */ printf("Пожалуйста, введите свое имя, возраст и зарплату.\n"); scanf("%20s %d %lf",name,&age,&salary); /* напечатать введенные данные */ printf("\n\AТаблица %s\n",label); printf("Вычислена %s, возраст %d, $%15.2lf\n",name,age,salary); printf("-----------------------------------------------------\n"); for(loop = 0; loop