Изучение и использование функций printf() и scanf(). Ввод данных в языке Си. Функция scanf

В данной статье функция scanf() рассматривается в общем виде без привязки к конкретному стандарту, поэтому сюда включены данные из любых стандартов C99, C11, C++11, C++14. Возможно, в некоторых стандартах функция работает с отличиями от изложенного в статье материала.

Функция scanf C - описание

scanf() - это функция, расположенная в заголовочном файле stdio.h(C) и cstdio(C++), она также называется форматированным вводом данных в программу. scanf читает символы из стандартного потока ввода (stdin) и преобразует их в соответствии с форматом, после чего записывает в указанные переменные. Формат - означает, что данные при поступлении приводятся к определенному виду. Таким образом, функция scanf C описывается:

scanf("%формат", &переменная1[, &переменная2,[…]]),

где переменные передаются в виде адресов. Причина такого способа передачи переменных в функцию очевидна: в результате работы она возвращает значение, указывающее на наличие ошибок, поэтому единственным способом изменять значения переменных является передача по адресу. Также, благодаря такому способу, функция может обрабатывать данные любых типов.

Некоторые программисты из-за аналогии с другими языками называют функции, подобные scanf() или printf(), процедурами.

Scanf позволяет осуществлять ввод всех базовых типов языка: char, int, float, string и т.д. В случае с переменными типа string нет нужды указывать знак адреса - «&», так как переменная типа string является массивом, и имя ее является адресом первого элемента массива в памяти компьютера.

Формат ввода данных или управляющая строка

Начнем с рассмотрения примера использования функции scanf C из описания.

#include int main() { int x; while (scanf("%d", &x) == 1) printf("%d\n", x); return 0; //требование linux-систем }

Формат ввода состоит из следующих четырех параметров: %[*][ширина][модификаторы] тип. При этом знак «%» и тип являются обязательными параметрами. То есть, минимальный вид формата выглядит следующим образом: “%s”, “%d” и так далее.

В общем случае символы, составляющие строку формата, делятся на:

  • спецификаторы формата - все, что начитается с символа %;
  • разделительные или пробельные символы - ими считаются пробел, табуляция(\t), новая строка (\n);
  • символы, отличающиеся от пробельных.

Функция может оказаться небезопасной.

Используйте вместо scanf() функцию scanf_s().

(сообщение от Visual Studio)

Тип, или спецификаторы формата, или литеры преобразования, или контролирующие символы

Описание scanf C обязано содержать, как минимум, спецификатор формата, который указывается в конце выражений, начинающихся со знака «%». Он сообщает программе тип данных, который следует ожидать при вводе, обычно с клавиатуры. Список всех спецификаторов формата в таблице ниже.

Значение

Программа ожидает ввод символа. Переменная для записи должна иметь символьный тип char.

Программа ожидает ввод десятичного числа целого типа. Переменная должна иметь тип int.

Программа ожидает ввод числа с плавающей точкой (запятой) в экспоненциальной форме. Переменная должна иметь тип float.

Программа ожидает ввод числа с плавающей точкой (запятой). Переменная должна иметь тип float.

7

Программа ожидает ввод числа с плавающей точкой (запятой). Переменная должна иметь тип float.

Программа ожидает ввод восьмеричного числа. Переменная должна иметь тип int.

Программа ожидает ввод строки. Строкой считается набор любых символов до первого встреченного разделительного символа. Переменная должна иметь тип string.

Программа ожидает ввод шестнадцатеричного числа. Переменная должна иметь тип int.

Переменная ожидает ввод указателя. Переменная должна иметь тип указателя.

Записывает в переменную целое значение, равное количеству считанных до текущего момента символов функцией scanf.

Программа считывает беззнаковое целое число. Тип переменной должен быть unsigned integer.

Программа ожидает ввод двоичного числа. Переменная должна иметь тип int.

Набор сканируемых символов. Программа ожидает ввод символов, из ограниченного пула, указанного между scanf будет работать до тех пор, пока на потоке ввода находятся символы из указанного множества.

Символы в строке формата

Символ звездочка (*)

Звездочка (*) - это флаг, указывающий, что операцию присвоения надо подавить. Звездочка ставится сразу после знака «%». Например,

Scanf("%d%*c%d", &x, &y); //игнорировать символ между двумя целыми числами. scanf("%s%*d%s", str, str2); //игнорировать целое число, между двумя строками.

То есть, если ввести в консоли строку «45-20» программа сделает следующее:

  1. Переменной «x» будет присвоено значение 45.
  2. Переменной «y» будет присвоено значение 20.
  3. А знак минус(тире) «-» будет проигнорирован благодаря «%*c».

Ширина (или ширина поля)

Это целое число между знаком «%» и спецификатором формата, которое определяет максимальное количество символов для считывания за текущую операцию чтения.

Следует иметь в виду несколько важных моментов:

  1. scanf прекратит свою работу, если встретит разделительный символ, даже если не считал 20 символов.
  2. Если на ввод подается больше 20 символов, в переменную str будут записаны только первые 20 из них.

Модификаторы типа (или точность)

Это специальные флаги, которые модифицируют тип данных, ожидаемых к вводу. Флаг указывается слева от спецификатора типа:

  • L или l (маленькая L) При использовании «l» со спецификаторами d, i, o, u, x, флаг сообщает программе, что ожидается ввод данных типа long int. При использовании «l» со спецификатором e или f, флаг сообщает программе, что она должна ожидать ввод значения типа double. Использование «L» сообщает программе, что ожидается значение типа long double. Использование «l» со спецификаторами «c» и «s» сообщает программе, что ожидаются двухбайтовые символы типа wchar_t. Например, "%lc", "%ls", "%l".
  • h - флаг, указывающий на тип short.
  • hh - обозначает, что переменная является указателем на значение типа signed char или unsigned char. Флаг можно использовать со спецификаторами d, i, o, u, x, n.
  • ll (две маленькие L) - обозначает, что переменная является указателем на значение типа signed int или unsigned long long int. Флаг используется со спецификаторами: d, i, o, u, x, n.
  • j - обозначает, что переменная является указателем на тип intmax_t или uintmax_t из заголовочного файла stdint.h. Используется со спецификаторами: d, i, o, u, x, n.
  • z - обозначает, что переменная является указателем на тип size_t, определение которого находится в stddef.h. Используется со спецификаторами: d, i, o, u, x, n.
  • t - обозначает, что переменная является указателем на тип ptrdiff_t. Определение на этот тип находится в stddef.h. Используется со спецификаторами: d, i, o, u, x, n.

Более явно картину с модификаторами можно представить в виде таблицы. Такое описание scanf C для програмистов будет понятнее.

Остальные символы

Любые символы, которые будут встречены в формате, будут отбрасываться. При этом стоит отметить, что наличие в управляющей строке пробельных или разделительных символов (новая строка, пробел, табуляция) может приводить к разному поведению функции. В одной версии scanf() будет читать без сохранения любое количество разделителей до момента, пока не встретит символ, отличный от разделителя, а в другой версии - пробелы (только они) не играют роли и выражение "%d + %d" эквивалентно "%d+%d".

Примеры

Рассмотрим ряд примеров, позволяющих поразмыслить и точнее понять работу функции.

Scanf("%3s", str); //если ввести в консоли строку «1d2s3d1;3», в str запишется только «1d2» scanf("%dminus%d", &x, &y); //символы «minus» между двумя числами будут отброшены scanf("%5", str); //ввод символов в str будет происходить до тех пор, пока их не будет 5 и символы являются числами от 0 до 9. scanf("%lf", &d); //ожидается ввод данных типа double scanf("%hd", &x); //ожидается число типа short scanf("%hu", &y); //ожидается число типа unsigned short scanf("lx", &z); //ожидается число типа long int

Из приведенных примеров видно, как меняется ожидаемое число с использованием различных символов.

scanf C - описание для начинающих

Данный раздел будет полезен новичкам. Зачастую нужно иметь под рукой не столько полное описание scanf C, сколько детали работы функции.

  • Функция является отчасти устаревшей. Существует несколько разных реализаций в библиотеках различных версий. Например, усовершенствованная функция scanf S C, описание которой можно найти на сайте microsoft.
  • Количество спецификаторов в формате должно соответствовать количеству переданных функции аргументов.
  • Элементы входного потока должны отделяться только разделительными символами: пробел, табуляция, новая строка. Запятая, точка с запятой, точка и т. д. - эти символы не являются разделительными для функции scanf().
  • Если scanf встретит разделительный символ, ввод будет остановлен. Если переменных для чтения больше одной, то scanf перейдет к чтению следующей переменной.
  • Малейшее несоответствие формата вводимых данных приводит к непредсказуемым результатам работы программы. Хорошо, если программа просто завершится с ошибкой. Но нередко программа продолжает работать и делает это неверно.
  • scanf("%20s …", …); Если входной поток превышает 20 символов, то scanf прочитает первые 20 символов и, либо прекратит работу, либо перейдет к чтению следующей переменной, если она указана. При этом следующий вызов scanf продолжит чтение входного потока с того места, где остановилась работа предыдущего вызова scanf. Если при чтении первых 20 символов будет встречен разделительный символ, scanf прекратит свою работу или перейдет к чтению следующей переменной, даже если не считал 20 символов для первой переменной. При этом все несчитанные символы прицепятся к следующей переменной.
  • Если набор сканируемых символов начать со знака «^», то scanf будет читать данные до тех пор, пока не встретит разделительный символ или символ из набора. Например, "%[^A-E1-5]" будет считывать данные из потока, пока не будет встречен один из символов английского алфавита от А до Е в верхнем регистре или одно из чисел от 1 до 5.
  • Функция scanf C по описанию возвращает число, равное успешному количеству записей в переменные. Если scanf записывает 3 переменные, то результатом успешной работы функции будет возврат числа 3. Если scanf не смог записать ни одной переменной, то результат будет 0. И, наконец, если scanf вообще не смог начать работать по каким-либо причинам, результатом будет EOF.
  • Если функция scanf() завершила свою работу некорректно. Например, scanf("%d", &x) - ожидалось число, а на ввод пришли символы. Следующий вызов scanf() начнет свою работу с того места в потоке ввода, где завершился предыдущий вызов функции. Чтобы преодолеть эту проблему, необходимо избавиться от проблемных символов. Это можно сделать, например, вызвав scanf("%*s"). То есть, функция прочитает строку символов и выбросит ее. Таким хитрым образом можно продолжить ввод нужных данных.
  • В некоторых реализациях scanf() в наборе сканируемых символов недопустимо использование «-».
  • Спецификатор “%c” читает каждый символ из потока. То есть символ -разделитель он также читает. Чтобы пропустить символ разделитель и продолжить читать нужный символ, можно использовать “%1s”.
  • При использовании спецификатора «c» допустимо использовать ширину “%10c”, однако тогда в виде переменной функции scanf нужно передать массив элементов типа char.
  • “%” - это значит "все маленькие буквы английского алфавита", а “%” - значит просто 3 символа: ‘z’, ‘a’, ‘-’. Иными словами, символ «-» означает диапазон только в том случае, если стоит между двумя символами, которые находятся в правильном порядке следования. Если «-» находится в конце выражения, в начале или в неверном порядке символов по обеим сторонам от них, то он представляет собой просто символ дефиса, а не диапазон.

Заключение

На этом завершается описание scanf C. Это хорошая удобная функция для работы в небольших программах и при использовании процедурного метода программирования. Однако главным недостатком является количество непредсказуемых ошибок, которые могут возникнуть при использовании scanf. Поэтому, описание scanf C при програмировании лучше всего держать перед глазами. В крупных профессиональных проектах используются потоки iostream, ввиду того, что обладают более высокоуровневыми возможностями, лучше позволяют отлавливать и обрабатывать ошибки, а также работать со значительными объемами информации. Также следует отметить, описание scanf C на русском доступно на сетевых многих источниках, как и примеры ее использования, ввиду возраста функции. Поэтому при необходимости всегда можно найти ответ на тематических форумах.

Пожалуйста, приостановите работу AdBlock на этом сайте.

Вернёмся к последнему листингу прошлого шага:

Листинг 1.

#include int main(void) { int a, b, res; a = 10; b = 7; res = a + b; printf("%d + %d = %d\n", a, b, res); return 0; }

Основная задача этого шага научиться получить данные от пользователя.

Для этого можно использовать функцию scanf . Она, так же как и функция printf , описана в заголовочном файле stdio.h . Т.к. он у нас уже подключен в первой строке, то мы можем свободно использовать функцию scanf в своей программе.

Рис.1. Общий синтаксис функции scanf.

В двойных кавычках указывается спецификатор формата. В зависимости от того в какую переменную мы собираемся сохранять введенное значение, необходимо использовать соответствующий спецификатор формата.

Основные спецификаторы формата:

%d - целые числа
%f - вещественное число типа float
%lf - вещественное число типа double (обозначение lf от long float)
%c - символ

Обратите внимание, что в функции scanf для типов float и double используются различные спецификаторы формата.

После формат-строки нужно указать адрес переменной, в которую нужно сохранить данные. Чтобы указать адрес переменной достаточно перед её именем записать знак & (амперсанд), как на рисунке выше.

Напишем, наконец-таки, программу сложения двух чисел.

Листинг 2.

#include int main(void) { int a, b, res; scanf("%d", &a); // считываем целое значение в переменную a scanf("%d", &b); // считываем целое значение в переменную b res = a + b; printf("%d + %d = %d\n", a, b, res); return 0; }

Скомпилируйте и запустите эту программу. После того, как программа запущена она будет ждать пока вы введёте данные. Мы с вами знаем какие данные нужно вводить, т.к. мы писали эту программу. Для других пользователей, которые код программы не увидят, хорошо бы вывести на экран подсказку, какие данные нужно ввести. Посмотрите как это реализовано в следующем примере.

Эта программа будет полезна тем, кто следит за своим здоровьем. Данная программа подсчитывает уроверь базового обмена веществ по формуле Миффлина-Сан Жеора исходя из данных, которые вы введёте (возраст, рост и вес).

Листинг 3.

#include int main(void){ int age, height, weight; double bov_m, bov_f; printf("Vash vozrast?(god)\n"); scanf("%d", &age); // считываем целое значение в переменную age printf("Vash rost?(cm)\n"); scanf("%d", &height); // считываем значение в переменную height printf("Vash ves?(kg)\n"); scanf("%d", &weight); // считываем значение в переменную weight bov_m = 10*weight + 6.25*height - 5*age + 5; bov_f = 10*weight + 6.25*height - 5*age - 161; printf("| BMR |\n"); printf("| male | female |\n"); printf("|%8.2f|%8.2f|\n",bov_m, bov_f); return 0; }

На самом деле, функция scanf – функция форматного ввода. Она устроена чуть ли не сложнее, чем printf . Но рассказывать новичку об особенностях её работы значит понапрасну грузить его лишней информацией. На данном этапе вам будет достаточно и этих знаний, а когда появится необходимость использовать что-то большее, вы с этим сможете сами разобраться. А может и я в каком-нибудь уроке расскажу.

] SCANF #include int scanf(format-string[[, argument...]]); char *format-string. строка управления форматом. Описание. Функция scanf читает данные из стандартного потока stdin в место, определяемое аргументами arguments. Каждый аргумент должен быть указателем на значение с типом, который соответствует типу, заданному в строке формата. Строка формата управляет преобразава- ниями полей ввода. Эта строка может содержать следующее: "Пробельные" символы, т.е. символ пробела " ", табуляции \t, новой строки "\n". Для функции scanf символом пробела определяет- ся считывание, но без запоминания, всех вводимых последующих сим- волов пробела вплоть до первого символа, не являющегося пробелом. При вводе один символ пробела в строке формата соответствует лю- бому числу, включая 0, или любой комбинации символов пробела. Любой символ управления, не являющийся пробелом и символом знака процента %. Тогда по этому символу для функции scanf опре- деляется считывание, но без запоминания соответствующих символов управления. Если следующий символ в не соответствует сим- волам управления, то scanf оканчивает свою работу. Спецификацию формата, введенную со знаком %. В этом случае scanf читает и преобразовывает введенные символы к значениям за- данного типа, причем значения определяются соответствующими аргу- ментами из списка аргументов. Строка формата читается слева направо. Символы вне специфи- кации формата предполагаются согласованными с последовательностью символов в потоке stdin; эти согласованные символы в stdin скани- руются, но не запоминаются. Если символ в stdin противоречит строке формата, scanf оканчивает свою работу. Этот конфликтующий символ остается в stdin, так как он не может быть прочитан. Когда встречается первая спецификация формата, тогда значение первого поля ввода преобразовывается в соответствии со спецификацией фор- мата и запоминается в месте, заданном первым аргументом. По вто- рой спецификации формата выполняется преобразование второго поля ввода и запоминание его по второму аргументу; и так до конца строки формата. Поле ввода ограничивается первым "пробельным" символом или первым символом, который не может преобразоваться по заданному формату, или случаем достижения поля width, которое идет первым. Если для выбранной спецификации формата задано больше аргу- ментов, чем требуется, то лишние аргументы игнорируются. Спецификация формата имеет следующую форму. %<.precision><{F:N:h:I}>. Каждое поле в формате спецификаций является отдельным сим- волом или числом, выражающим отдельную опцию формата. Символ type, появляющийся после последнего необязательного поля формата, определяет тип поля ввода как символьного, строкового или числен- ного. Простейший формат спецификации содержит только символ знака процента и символ типа (например, %S). Каждое поле спецификации формата описывается ниже. Если за знаком процента % следует символ, не являющийся символом управления форматом, то этот символ и идущие за ним сим- волы, вплоть до следующего знака %, трактуются как обычная после- довательность символов, т.е. последовательность, которая должна быть введена. Например, чтобы ввести символ знака %, используется комбинация %%. Звездочка (*), идущая за знаком %, подавляет назначение следующего поля ввода, задающегося как поле, определяемое типом type. Это поле сканируется, но не запоминается. Widht является положительным десятичным целым и управляет максимально возможным числом символов, считываемых из stdin. Пре- образовываются и запоминаются по соответствующему аргументу толь- ко те символы, которые не превышают width. Если в width встреча- ются "пробельные" символы, т.е. символы пробела, табуляции или новой строки, то по выбранному формату они не преобразовываются, пока не будет достигнут размер width. Необязательные префиксы F и N не учитывают принятое по умолчанию адресное соглашение используемых моделей памяти. F мо- жет быть префиксом к аргументу argument, указыващему на far-объ- ект; а N - на near-объект. Необязательный префикс l свидетельствует о том, что исполь- зуется версия long; а префикс h - указывает на использование вер- сии short. Соответствующий argument указывает на long или double-объект (при помощи префикса l) или на short-объект (при помощи префикса h). Модификаторы l и h могут использоваться вмес- те с типами символов d, i, o, x, u. Модификатор l также может ис- пользоваться с символами type e и f. Если определен любой другой type, модификаторы l и h игнорируются. Символы type и их значения описаны в таблице R.4. Таблица R.4 Типы символов функции scanf СИМВОЛ ПРЕДПОЛАГАЕМЫЙ ТИП ТИП АРГУМЕНТА ВВОДА d десятичный целый указатель на int. D десятичный целый указатель на long. o восьмеричный целый указатель на int. O восьмеричный целый указатель на long. x шестнадцатеричный указатель на int. целый X шестнадцатеричный указатель на long. целый i десятичный, вось- указатель на int. меричный или шест- надцатеричный це- лый I десятичный, вось- указатель на long. меричный или шест- надцатеричный це- лый u беззнаковый деся- указатель на unsigned тичный целый int. U беззнаковый деся- указатель на unsigned тичный целый long. e значение с плава- указатель на float f ющей точкой, со- держащее необяза- тельный знак ("+", "-"), одну или больше десятичную цифру, обычно со- держащую десятич- ную точку и экспо- ненту ("е", "Е"), которая записы- вается за знаковым целым значением. c символьный. Симво- указатель на char лы пробела, табу- ляции или новой строки, так назы- ваемые "пробельные символы", которые обычно пропускают- ся, при задании этого типа считы- ваются. Для считы- вания следующего символа, не являю- щегося "пробель- ным", используется комбинация %1s. s строковый. указатель на символь- ный массив, достаточ- но большой для вводи- мого поля вместе с нулевым символом окончания "\0", по- являющимся автомати- чески. n чтение при вводе указатель на int, в из stream или котором записывается буфера не проис- число успешно счи- ходит. танных символов из потока или буфера, вплоть до указанных в вызове scanf. p значение в форме указатель на far- xxxx: yyyy, где группу данных. цифры x и y явля- ются шестнадцате- ричными цифрами верхнего регистра. При чтении строк, не ограниченных символами пробела, мно- жество символов в квадратных скобках должно заменяться строко- вым типом s. Соответствующее поле ввода читается вплоть до перво- го символа, не содержащегося в ограниченном квадратными скобками множестве символов. Если в этом множестве первым символом являет- ся caret (^), результат сохраняется: поле ввода считывается до первого символа, не входящего в это множество символов. Чтобы за- помнить строку без нулевого символа "\0", применяется специфика- ция %nc, где n - десятичное целое. В этом случае символьный тип s определяет аргумент, который указывает на массив символов. Сле- дующие n символов считываются из входного потока в определенное местоположение и нулевой символ не записывается. Функция scanf для каждого поля ввода сканирует символ за символом. Она может окончить чтение отдельного поля при достиже- нии символа пробела, если либо достигнуто поле width; либо следу- ющий вводимый символ не может быть преобразован по заданному фор- мату; либо следующий символ конфликтует с соответствующим ему символом в управляющей строке формата; либо же следующий символ отсутствует в выбранном множестве символов. Когда происходит вы- нужденный процесс окончания считывания, то следующее поле ввода рассматривается с самого первого конфликтующего символа. Этот символ, если он один, рассматривается как непрочитанный, либо как первый символ следующего поля ввода, либо как первый символ в последующих операциях чтения потока stdin. Возвращаемое значение. Эта функция возвращает число успешно преобразованных и наз- наченных полей. В возвращаемом значении не содержится число про- читанных но не назначенных полей. При попытке считывания конца файла возвращается значение EOF. Возвращаемое значение 0 указыва- ет, что нет назначенных полей. См. также fscanf, printf , sscanf , vfprintf, vprintf, vsprintf. Пример 1. #include int i; float fp; char c, s; scanf("%d %f %c %s", &i, &fp, &c, s); /* ввод различных данных */. Пример 2. #include main () /* преобразование шестнадцатеричного ** или восьмеричного целого к ** десятичному целому */ { int numassigned, val; pintf("Enter hexadecimal or octal #, or 00 to guit:\n"); do { printf("# = "); numassigned = scanf("%i", &val); printf("Decimal # = %i\n", nal); } while (val && numassigned); /* конец цикла, если значение ввода равно 00, или если scanf не способна назначить поле */. } Тогда на выходе будет следующее. Enter hexadecimal or octal #, or 00 to guit: # = 0xf Decimal # = 15 # = 0100 Decimal # = 64 # = 00 Decimal # = 0.

Как хорошо когда все данные даны, и ничего вводить не надо. Но, поверьте мне, так практически не бывает. Вспомните школу, когда вы измеряли определенные вещи, а потом полученные значения вставляли в нужные формулы.

scanf

В языке Си кроме функции вывода printf, существует так же функция scanf для ввода. Вот функцию scanf мы щас и рассмотрим подробнее:

int i;
scanf("%d", &i);

Вроде очень похоже на функцию printf. Так же есть в двойных кавычках спецификатор формата , но разница как раз находится во второй части функции. Обратили внимание на появление знака (&)? Так вот этот знак означает взятие адреса. Щас объясню для чего это нужно.

Мы должны записывать введенное значение не куда-то там, а именно по адресу, по которому находится наша переменная. Т.е. без знака (&) наше введенное значение попадет во все места, кроме того что нам нужно. Поэтому всегда, когда вам нужно вводить значения с клавиатуры, ставьте перед переменной знак взятия адреса (&).

Спецификаторы формата

Ну теперь пробежимся по спецификаторам формата :
  1. %d - прочитать целое число
  2. int i;
    scanf ("%d", &i);

  3. %o - прочитать восьмеричное число
  4. int i;
    scanf ("%o", &i);

  5. %x - прочитать шестнадцатеричное число
  6. int i;
    scanf ("%x", &i);

  7. %e(%f) - прочитать вещественное число
  8. float t;
    scanf ("%f", &t);

  9. %с - прочитать символ
  10. char ch;
    scanf ("%c", &ch);

  11. %s - прочитать строку
  12. char *str;;
    scanf ("%s", str);

    Пока не вникайте в работу со строками. Почему нету знака взятия адреса? Эту тему мы рассмотрим чуть позднее.

Операции сравнения

В компьютер изначально заложена булева логика, т.е. все построено на 0 и 1. Если не понимаете о чем речь, то пересмотрите фильм Матрица, где каждая зеленая заставка как раз состояла из этих двух магических цифр.

Конечно, 0 и 1 это хорошо, но нам нужен логический смысл, поэтому в логических операциях 0 - это FALSE, а 1 - это TRUE. Эти понятия TRUE и FALSE тесно связанны с операциями сравнения . Для начала приведем всевозможные операции сравнения:

В принципе, самая распространенная ошибка, которую делают новички - это путают операцию присваивания (=) с операцией сравнения (==). Это абсолютно разные вещи. Но у всех на первых порах кодирования возникают ошибки именно на этой почве, поэтому будьте внимательнее.

#include
int scanf (const char *format, ...);

Функция scanf() представляет собой процедуру ввода общего назначения, которая читает поток stdin и сохраняет информацию в переменных, перечисленных в списке аргументов. Она может читать все встроенные типы данных и автоматически преобразовывать их в соответствующий внутренний формат.

В версии С99 к параметру format применен квалификатор restrict .

Управляющая строка, задаваемая параметром format , состоит из символов трех категорий:

  • спецификаторов формата;
  • пробельных символов;
  • символов, отличных от пробельных.

  • Спецификации формата начинаются знаком % и сообщают функции scanf() тип данного, которое будет прочитано. Например, по спецификации %s будет прочитана строка, а по спецификации %d - целое значение. Строка форматирования читается слева направо, и спецификации формата сопоставляются аргументам в порядке их перечисления в списке аргументов.

    Спецификации формата функции scanf() :
    Читает значение с плавающей точкой (только С99)
    Аналогично коду (только С99)
    Читает один символ
    %d Читает десятичное целое
    %i Читает целое в любом формате (десятичное, восьмеричное или шести ад цате ричное)

    Аналогично коду
    %f Читает число с плавающей точкой
    %F Аналогично коду %f (только С99)
    %g Читает число с плавающей точкой
    %G Аналогично коду %g
    %o Читает восьмеричное число
    %s Читает строку
    Читает шести ад цате ричное число
    Аналогично коду
    Читает указатель
    %n Принимает целое значение, равное количеству прочитанных до сих пор символов
    %u Читает десятичное целое без знака
    % Просматривает набор символов
    %% Читает знак процента

    По умолчанию спецификации a , f , е и g заставляют функцию scanf() присваивать данные переменным типа float . Если перед одной из этих спецификаций поставить модификатор l , функция scanf() присвоит прочитанные данные переменной типа double . Использование же модификатора L означает, что полученное значение присвоится переменной типа long double .

    Современные компиляторы, поддерживаюшие добавленные в 1995 году средства работы с двухбайтовыми символами, позволяют к спецификации с применить модификатор l ; тогда будет считаться, что соответствующий указатель указывает на двухбайтовый символ (т.е. на данное типа wchar_t ). Модификатор l также можно использовать с кодом формата s ; тогда будет считаться, что соответствующий указатель указывает на строку двухбайтовых символов. Кроме того, модификатор l можно использовать для того, чтобы указать, что набор сканируемых символов состоит из двухбайтовых символов.

    Если в строке форматирования встретится разделитель, то функция scanf() пропустит один или несколько разделителей во входном потоке. Под разделителем, или пробельным символом, подразумевается пробел, символ табуляции или разделитель строк (символ новой строки). По сути, наличие одного разделителя в управляющей строке приведет к тому, что функция scanf() будет читать, не сохраняя, любое количество (возможно, даже нулевое) разделителей до первого символа, отличного от разделителя.

    Если в строке форматирования встретился символ, отличный от разделителя, то функция scanf() прочитает и отбросит его. Например, если в строке форматирования встретится %d , %d , то функция scanf() сначала прочитает целое значение, затем прочитает и отбросит запятую и, наконец, прочитает еще одно целое. Если заданный символ не найден, функция scanf() завершает работу.
    Все переменные, получающие значения с помощью функции scanf() , должны передаваться посредством своих адресов. Это значит, что все аргументы должны быть указателями на переменные.
    Элементы входного потока должны быть разделены пробелами, символами табуляции или разделителями строк. Такие символы, как запятая, точка с запятой и т.п., не распознаются в качестве разделителей. Это означает, что оператор
    scanf ("%d%d", &r, &c); примет значения, введенные как 10 20, но откажется от последовательности символов 10,20.

    Символ * , стоящий после знака % и перед кодом формата, прочитает данные заданного типа, но запретит их присваивание. Следовательно, оператор
    scanf ("%d%*c%d", &x, &y); при вводе данных в виде 10/20 поместит значение 10 в переменную х, отбросит знак деления и присвоит значение 20 переменной у.

    Команды форматирования могут содержать модификатор максимальной длины поля. Он представляет собой целое число, располагаемое между знаком % и кодом формата, которое ограничивает количество читаемых для всех полей символов. Например, если в переменную address нужно прочитать не более 20 символов, используется следующий оператор.
    scanf ("%20s", address);
    Если входной поток содержит более 20 символов, то при последующем обращении к операции ввода чтение начнется с того места, в котором "остановился" предыдущий вызов функции scanf() . Если разделитель встретится раньше, чем достигнута максимальная длина поля, ввод данных завершится. В этом случае функция scanf() переходит к чтению следующего поля.

    Хотя пробелы, символы табуляции и разделители строк используются в качестве разделителей полей, при чтении одиночного символа они читаются подобно любому другому символу. Например, если входной поток состоит из символов х у, то оператор
    scanf ("%c%c%c", &a, &b, &c); поместит символ х в переменную а, пробел - в переменную b, а символ у - в переменную с.

    Помните, что любые символы управляющей строки (включая пробелы, символы табуляции и новой строки), не являющиеся спецификациями формата, используются для установки соответствия и отбрасывания символов из входного потока. Любой соответствующий им символ отбрасывается. Например, если поток ввода выглядит, как 10t20, оператор
    scanf ("%dt%d", &x, &y); присвоит переменной х значение 10, а переменной у - значение 20. Символ t отбрасывается, так как он присутствует в управляющей строке.

    Функция scanf() поддерживает спецификатор формата общего назначения, называемый набором сканируемых символов (scanset) , В этом случае определяется набор символов, которые могут быть прочитаны функцией scanf() и присвоены соответствующему массиву символов. Для определения такого набора символы, подлежащие сканированию, необходимо заключить в квадратные скобки. Открывающая квадратная скобка должна следовать сразу за знаком процента. Например, следующий набор сканируемых символов указывает на то, что необходимо читать только символы А, B и С.
    % При использовании набора сканируемых символов функция scanf() продолжает читать символы и помещать их в соответствующий массив символов до тех пор, пока не встретится символ, отсутствующий в заданном наборе. Соответствующая набору переменная должна быть указателем на массив символов. При возврате из функции scanf() этот массив будет содержать строку из прочитанных символов, завершающуюся символом конца строки.

    Если первый символ в наборе является знаком ^ , то получаем обратный эффект: входное поле читается до тех пор, пока не встретится символ из заданного набора сканируемых символов, т.е. знак ^ заставляет функцию scanf() читать только те символы, которые отсутствуют в наборе сканируемых символов.
    Во многих реализациях допускается задавать диапазон с помощью дефиса. Например, функция scanf() , встречая набор сканируемых символов в виде % , будет читать символы, попадающие в диапазон от А до Z.

    Важно помнить, что в наборе сканируемых символов различаются прописные и строчные буквы. Следовательно, чтобы сканировать как прописные, так и строчные буквы, в наборе сканируемых символов придется задать их отдельно.

    Функция scanf() возвращает число, равное количеству полей, для которых успешно присвоены значения. К этим полям не относятся поля, которые были прочитаны, но присвоение не состоялось в связи с использованием модификатора * , подавляющего присваивание. При обнаружении ошибки до присвоения значения первого поля функция scanf() возвращает значение EOF .

    Модификаторы формата, добавленные к функции scanf() Стандартом С99

    В версии С99 для использования в функции scanf() добавлены модификаторы формата hh , ll , j , z и t . Модификатор hh можно применять к спецификациям d , i , о , u , х и n signed char или unsigned char . Модификатор ll также можно применять к спецификациям d , i , о , u , х и n . Он означает, что соответствующий аргумент является указателем на значение типа signed long long int или unsigned long long int .

    Модификатор формата j d , i , о , u , х и n , означает, что соответствующий аргумент является указателем на значение типа intmax_t или uintmax_t . Эти типы объявлены в заголовке и служат для хранения целых максимально возможной разрядности.

    Модификатор формата z , который применяется к спецификациям d , i , о , u , х и n size_t и служит для хранения результата операции sizeof .

    Модификатор формата t , который применяется к спецификациям d , i , о , u , х и n , означает, что соответствующий аргумент является указателем на объект типа ptrdiff_t . Этот тип объявлен в заголовке и служит для хранения значения разности между двумя указателями.



    Понравилась статья? Поделиться с друзьями: