Урок 6.3. Форматный ввод
6.3. Форматный ввод
Для форматного ввода данных применяется функция scanf(), обращение к которой в общем виде можно записать следующим образом:
scanf(<управляющая строка>,<список ввода>); |
где <управляющая строка> является строкой Си, символами которой могут быть:
а) пробелы, символы табуляции и новой строки ("пустые" символы). Если они есть, то они игнорируются;
б) обычные символы (кроме %). Если они есть, то они должны совпадать с очередными символами во входном потоке данных;
в) форматы, начинающиеся с символа %, за которым может быть записан символ запрещения присваивания * , может быть число, задающее ширину поля входного данного, и обязательно должен быть символ преобразования. * <список ввода> состоит, как и для функции printf(), из элементов, отделенных друг от друга запятой.
Однако в качестве элемента ввода указывается адрес переменной, куда должно поступить значение, а не имя переменной. Чтобы получить адрес, нужно к переменной применить операцию взятия адреса & . Например, если name имя переменной, то ее адрес будет &name.
Для массивов имя массива является его адресом. Форматы в управляющей строке аналогичны форматам в строке вывода функции printf(), но имеются некоторые отличия. Формат ввода имеет следующую общую форму записи:
%*<ширина_l_символ_преобразования> |
В форматах управляющей строки используются следующие наиболее часто употребляющиеся символы преобразования:
Таблица. Спецификации формата функции scanf() |
|
Код |
Назначение |
%a,%A | читает значение с плавающей точкой (только C99) |
%c | на входе ожидается одиночный символ |
%d | на входе ожидается десятичное целое |
%i | читает целое в любом формате (десятичное, восьмеричное или шестнадцатеричное) |
%e,%E | на входе ожидается число с плавающей точкой в форме с точкой или с порядком |
%f | читает число с плавающей точкой |
%F | Аналогично коду %f (только С99) |
%g,%G | читает число с плавающей точкой |
%o | читает восьмеричное число |
%s | на входе ожидается строка символов. Соответствующий элемент ввода должен быть адресом массива, способного вместить всю строку, включая нуль-символ \0, который добавляет сама функция; |
%x,%X | читает шестнадцатеричное число |
%p | читает указатель |
%n | принимает целое значение, равное количеству прочитанных до сих пор символов, см. пример с printf() в предыдущей главе |
%u | читает десятичное целое без знака |
%[ ],%[^] | просматривает набор символов на допустимость/недопустимость |
%% | читает знак процента |
Перед символами преобразования u, x, o и d может стоять буква l, указывающая на то, что соответствующий элемент списка ввода является адресом данного целого типа, описанного с модификатором long. Если буква l стоит перед символом преобразования f или e, то соответствующий элемент списка ввода является адресом данного, описанного как long float или long double соответственно.
Если в формате записана <ширина> , то она определяет максимальный размер поля данного. Меньшее число позиций может быть прочитано, если во входном потоке встретится разделитель полей или символ, который нельзя преобразовать в соответствии с указанным форматом.
Если в формате после % указан знак * , то это обозначает, что данное по этому формату будет взято из входного потока, но не будет присвоено соответствующему элементу списка ввода. Отработка функции scanf() влечет за собой переход программы в состояние ожидания до тех пор, пока не будет подготовлена и введена входная строка исходных данных.
Первое поле данного во входной строке преобразуется в соответствии с первым форматом, и полученное значение заносится по адресу первого элемента списка ввода. Следующее поле переводится в соответствии со вторым форматом и т.д.
Поле данного во входной строке определяется как группа символов до (но не включая) символа-разделителя. Символами-разделителями могут быть пробелы, символы табуляции и символы перехода на новую строку; группа символов до такого символа, который не может быть преобразован в соответствии с текущим форматом; группа из n символов, где n – значение ширины поля. Например, обращение:
int r; float x; char city[50]; scanf("%d %f %s", &r,&x,city); //с входной строкой 25 54.32e-1 Кишинев |
присвоит значение 25 переменной r, значение 5.432 переменной x и строку "Кишинев" с добавлением в конце нуль-символа \0 пошлет в массив city. Обратите внимание на то, что для city не указана операция взятия адреса &, так как в Си значением имени массива является адресная константа, определяющая начальный адрес памяти, с которого располагаются элементы массива. Видоизмененное обращение:
scanf("r=%d x=%f city=%s", &r,&x,city);
с непустыми символами в управляющей строке требует входной строки с точно такими же непустыми символами:
r=25 x=54.32e-1 city=Кишинев
Обращение с указанием в форматах ширины поля данного и с применением символа запрещения присваивания:
scanf("%25d %f %*d %2s",&r,&x,city);
для которого подготовлена, например, входная строка
56789 0123 45a72 ,
присвоит переменной r значение 56, переменной x значение 789.0, пропустит данное 0123, так как в формате стоит символ запрещения присваивания, и поместит строку "45" в city. Последующее обращение к вводу приведет к чтению из буфера, начиная с позиции буквы a. Если бы были прочтены все данные из входного буфера, то даже в этом случае в буфере остается признак конца ввода, так как он является разделителем полей.
Этот факт необходимо учитывать в прикладных программах, которые неоднократно запрашивают исходные данные. Для того, чтобы повторный ввод отработал корректно, после функции scanf() рекомендуется записать getchar(), которая "скушает" признак конца ввода.
Соглашения по организации ввода данных с помощью функции scanf() достаточно громоздки, и здесь мы рассмотрели наиболее употребительные случаи. Более детальные подробности о работе функций ввода-вывода можно найти в пользовательской документации по Си.
Пример использования "шаблонов", формат [ ], [^ ].
Формат [ ] позволяет получить строку, содержащую любые символы, указанные в квадратных скобках. Как только на ввод поступает символ, не входящий в указанный набор, считывание данных прекращается. Формат [^ ], наоборот, помещает в строку символы, не входящие в указанный набор, до тех пор пока не встретит любой из указанных.
char str[30]=""; // строке str будет присвоена последовательность символов из цифр, // как только встретится не цифра ввод, будет прекращен scanf("%[0-9]", str); // строке будет присвоена последовательность символов // до любого из указанных знаков препинания, если на клавиатуре // набрать Hello, World! , то str будет присвоено Hello scanf("%[^;:,!?]", str); // можно ввести любые символы, до тех пор, пока не будет // введена b или m scanf("%[^b,^m]", str); |
Оставить комментарий