Что такое код scanf


Содержание

Ввод данных в языке Си. Функция scanf

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

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

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

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

Чтобы считать данные, которые ввёл пользователь, и сохранить их в переменную, нужно вызвать функцию scanf со следующими параметрами:

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

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

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

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

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

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

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

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

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

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

Практика

Решите предложенные задачи. Для удобства работы сразу переходите в полноэкранный режим

Исследовательские задачи для хакеров:

  1. Попробуйте удалить в программе Листинг 2 символ & в какой-нибудь функции scanf . Посмотрите какую ошибку выдаст компилятор.
  2. Попробуйте использовать %f для типа double , а %lf для типа float . Каковы результаты? Напишите об этом в комментариях к этому уроку. Не забудьте указать название вашей IDE или компилятора.

scanf()

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

Эта функция возвращает количество тех элементов данных, которым было успешно присвоено значение. В случае ошибки scanf() возвращает EOF , управляющая_строка определяет преобразование считываемых значений при записи их переменные, на которые указывают элементы списка аргументов.

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

  • спецификаторов преобразования,
  • разделителей,
  • символов, не являющихся разделителями.

Теперь поговорим о каждом из этих видов.

Спецификаторы преобразования

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

Таблица 8.3. Спецификаторы преобразования для функции scanf()
Код Значение
%a Читает значение с плавающей точкой (только С99)
%c Читает одиночный символ
%d Читает десятичное целое число
%i Читает целое число как в десятичном, так и восьмеричном или шестнадцатеричном формате
%e Читает число с плавающей точкой
%f Читает число с плавающей точкой
%g Читает число с плавающей точкой
Читает восьмеричное число
%s Читает строку
%x Читает шестнадцатеричное число
%p Читает указатель
%n Принимает целое значение, равное количеству уже считанных символов
%u Читает десятичное целое число без знака
%[] Читает набор сканируемых символов
%% Читает знак процента

Ввод чисел

Для чтения целого числа используйте спецификатор преобразования %d или %i . A для чтения числа с плавающей точкой, представленного в стандартном или экспоненциальном виде, используйте спецификатор преобразования %e , %f или %g . (Кроме того, для чтения числа с плавающей точкой стандарт С99 разрешает использовать также спецификатор преобразования %a .)

Функцию scanf() можно использовать для чтения целых значений в восьмеричной или шестнадцатеричной форме, применяя для этого соответственно команды форматирования %o и %x , последняя из которых может быть как на верхнем, так и на нижнем регистре. Когда вводятся шестнадцатеричные числа, то буквы от А до F, представляющие шестнадцатеричные цифры, должны быть на том же самом регистре, что и литера-спецификатор. Следующая программа читает восьмеричное и шестнадцатеричное число:

Функция scanf() прекращает чтение числа тогда, когда встречается первый нечисловой символ.

Ввод целых значений без знака

Для ввода целого значения без знака используйте спецификатор формата %u . Например, операторы

выполняют считывание целого числа без знака и присваивают его переменной num .

Чтение одиночных символов с помощью scanf()

Как уже говорилось в этой главе, одиночные символы можно прочитать с помощью функции getchar() или какой-либо функции, родственной с ней. Для той же цели можно использовать также вызов функции scanf() со спецификатором формата %c . Но, как и большинство реализаций getchar() , функция scanf() при использовании спецификатора преобразования %c обычно будет выполнять построчно буферизованный ввод. В интерактивной среде такая ситуация вызывает определенные трудности.

При чтении одиночного символа символы разделителей читаются так же, как и любой другой символ, хотя при чтении данных других типов разделители интерпретируются как разделители полей. Например, при вводе с входного потока «x y» фрагмент кода

помещает символ x в a , пробел — в b , а символ y — в c .

Чтение строк

Для чтения из входного потока строки можно использовать функцию scanf() со спецификатором преобразования %s . Использование спецификатора преобразования %s заставляет scanf() читать символы до тех пор, пока не встретится какой-либо разделитель. Читаемые символы помещаются в символьный массив, на который указывает соответствующий аргумент, а после введенных символов еще добавляется символ конца строки (‘0’). Что касается scanf() , то таким разделителем может быть пробел, разделитель строк, табуляция, вертикальная табуляция или подача страницы. В отличие от gets() , которая читает строку, пока не будет нажата клавиша , scanf() читает строку до тех пор, пока не встретится первый разделитель. Это означает, что scanf() нельзя использовать для чтения строки «это испытание», потому что после пробела процесс чтения прекратится. Чтобы увидеть, как действует спецификатор %s , попробуйте при выполнении этой программы ввести строку «привет всем»:

Программа выведет только часть строки, то есть слово привет .

Ввод адреса

Для ввода какого-либо адреса памяти используйте спецификатор преобразования %p . Этот спецификатор преобразования заставляет функцию scanf() читать адрес в том формате, который определен архитектурой центрального процессора. Например, следующая программа вначале вводит адрес, а затем отображает то, что находится в памяти по этому адресу:

Спецификатор %n

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

Использование набора сканируемых символов

Функция scanf() поддерживает спецификатор формата общего назначения, называемый набором сканируемых символов (scanset). Набор сканируемых символов представляет собой множество символов. Когда scanf() обрабатывает такое множество, то вводит только те символы, которые входят в набор сканируемых символов. Читаемые символы будут помещаться в массив символов, который указан аргументом, соответствующим набору сканируемых символов. Этот набор определяется следующим образом: все те символы, которые предстоит сканировать, помещают в квадратные скобки. Непосредственно перед открывающей квадратной скобкой должен находиться знак % . Например, следующий набор сканируемых символов дает указание scanf() сканировать только символы X, Y и Z:

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

Введите 123abcdtye , а затем нажмите клавишу . После этого программа выведет 123 abed tye . Так как в данном случае ‘t’ не входит в набор сканируемых символов, то scanf() прекратила чтение символов в переменную str сразу после того, как встретился символ ‘t’. Оставшиеся символы были помещены в переменную str2 .

Кроме того, можно указать набор сканируемых символов, работающий с точностью до наоборот; тогда первым символом в таком наборе должен быть ^ . Этот символ дает указание scanf() принимать любой символ, который не входит в набор сканируемых символов.

В большинстве реализаций для указания диапазона можно использовать дефис. Например, указанный ниже набор сканируемых символов дает функции scanf() указание принимать символы от А до Z:

Следует обратить внимание на такой важный момент: набор сканируемых символов чувствителен к регистру букв. Если нужно сканировать буквы и на верхнем, и на нижнем регистре, то их надо указывать отдельно для каждого регистра.

Пропуск лишних разделителей

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

Символы в управляющей строке, не являющиеся разделителями

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

Функции scanf() необходимо передавать адреса

Для всех переменных, которые должны получить значения с помощью scanf() , должны быть переданы адреса. Это означает, что все аргументы должны быть указателями. Вспомните, что именно так в С создается вызов по ссылке и именно тогда функция может изменить содержимое аргумента. Например, для считывания целого значения в переменную count можно использовать такой вызов функции scanf() :

Строки будут читаться в символьные массивы, а имя массива без индекса является адресом первого его элемента. Таким образом, чтобы прочитать строку в символьный массив, можно использовать оператор

В этом случае str является указателем, и потому перед ним не нужно ставить оператор & .


Модификаторы форматат

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

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

то в str из-за спецификатора максимальной ширины поля будет помещено только 20 символов, то есть символы вплоть до Т. Это значит, что оставшиеся символы UVWXYZ пока еще не прочитаны. При следующем вызове scanf() , например при выполнении оператора

в str будут помешены буквы UVWXYZ. Ввод из поля может завершиться и до того, как будет достигнута максимальная длина поля — если встретится разделитель. В таком случае scanf() переходит к следующему полю.

Чтобы прочитать длинное целое, перед спецификатором формата поместите l (эль). А для чтения короткого целого значения перед спецификатором формата следует поместить n . Эти модификаторы можно использовать со следующими кодами форматов: d , i , o , u , x и n .

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

Если в компиляторе предусмотрена обработка двухбайтовых символов [1] , добавленных в язык С Поправкой 1 от 1995 года, то модификатор l можно также использовать с такими кодами формата, как c и s . l непосредственно перед c является признаком указателя на объект типа wchar_t . А l непосредственно перед s — признак указателя на массив элементов типа wchar_t . Кроме того, l также применяется для модификации набора сканируемых символов, чтобы этот набор можно было использовать для двухбайтовых символов.

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

На заметку В С99 для функции scanf() имеются еще и другие модификаторы типа; о них рассказывается в части II.

Подавление ввода

scanf() может прочитать поле, но не присваивать прочитанное значение никакой переменной; для этого надо перед литерой-спецификатором формата поля поставить звездочку, * . Например, когда выполняется оператор

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

[1] Называются также символами в расширенном 16-битном алфавите или символами уникода . (Unicode (уникод) — 16-битовый стандарт кодирования символов, позволяюший представлять алфавиты всех существующих в мире языков.)

scanf

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

Описание функции имеет вид:

Функция возвращает целочисленное значение — количество считанных элементов, или EOF в случае ошибки.

Управляющая строка содержит спецификаторы, которые позволяют определить тип считываемого значения (аналогичны спецификаторам, используемым с функцией printf: %d, %f, %c и т.д.) и адрес, по которому должно будет записано введенное значение, или, другими словами указатель на переменную, в большинстве случаев адрес — это значок & и символ переменной.

Использование string в функциях scanf и printf

Могут ли функции scanf и printf работать с переменными типа string ? Если да, то как это сделать, например, в данном коде?

1 ответ 1

Это, конечно, бред — использовать функции C с классами C++, но в принципе можно, хотя и не так, как указали вы.

printf — очень просто, передавать надо результат вызова c_str() :

Со scanf все гораздо хуже! Непосредственно со scanf не поработаешь, нужно сначала выделить в строке место, а потом передать указатель, но так как до C++17 .data() возвращает const char* , то формально следует использовать &s[0] . Но все знакомые мне компиляторы кушают и .data() — см., например, http://ideone.com/nzJE2S. VC++ тоже съедает — с предупреждением.

Но! Беда в том, что string при этом не знает, что в нем находится какая-то строка, и если вы запросите длину строки — она будет нулевой. Это просто использован буфер. Поэтому здесь в принципе никто ничего гарантировать не может. Тот же VC++ ухитряется верно обновить длину с помощью s = s.data() , но GCC, например, при этом строку просто обнуляет. Указать корректный способ обойти это затруднение я не могу.

Но, по большому счету, это правильно, потому что даже такое изменение строки — не через ее интерфейс, а через указатель на внутренний буфер — уже нарушает принцип инкапсуляции.

Так что scanf ‘уйте в массив char , а им инициализируйте string — это корректно и надежно. Хотя и просто смешно при наличии соответствующий возможностей C++ для считывания строк.

Что означает% [^ \ n] в строке формата scanf ()

Я видел на этом сайте, что это: fscanf(fin, «%[^\n]», &p); может быть использован для чтения из моего входного файла ( fin ) в этот указатель типа символа ( *p ) все символы до первого попадания попадания. На некоторых входах это работает правильно, а на других — нет.

Это входные данные, которые я должен обработать, и я не могу:

Это весь мой код:

Решение

%[ В нотации вводится нечто, называемое «набором сканеров», которое в некоторой степени напоминает регулярное выражение (но не такое мощное).

В вашем конкретном примере это означает, что спецификатор формата указывает scanf продолжать сканирование символов, которые соответствуют чему-либо, кроме \n (при обнаружении несовпадающего символа сканирование будет прервано).

Из стандарта C11:

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

Даже сравнение с регулярным выражением растягивает его: стандарт просто говорит:Соответствует непустой последовательности символов из набора ожидаемых символов».

Настоящая проблема с вашим кодом, замеченная Джонатаном Леффлером, заключается в следующем:

Брось & так как вы хотите передать p, а не «адрес p».

Другие решения

% вводит спецификатор формата , [ означает, что это набор сканирования и открывает его, ^ на первой позиции в наборе сканирования меняется с «сопоставить все в» на «сопоставить все» не в», \n является символом новой строки, и ] закрывает набор сканирования

Таким образом, это означает: сопоставлять неограниченное количество символов, которые не являются \n и положить их в char[] на что указывает аргумент.

Таким образом, этот аргумент должен иметь тип char* ,
&p точно один адрес — слишком много, и буфер, указанный им ( new char[1001] ) бесконечные порядки величины слишком малы.

Ограничьте длину совпадения (поместив 1000 между набором параметров и % ).
В качестве альтернативы, и гораздо лучше, используйте fgets .

Ваш буфер должен быть распределен по стеку, так как он достаточно мал:

В качестве альтернативы, по крайней мере, используйте смарт-указатель, чтобы не забыть delete [] Это:

  • Почему вы цените это? Это лишнее. использование new char[1001] вместо new char[1001]() ,
  • Не забудьте проверить возвращаемое значение fscanf , это должно быть количество заданий на успех.
  • C ++ (и C99) имеет неявное return 0; в конце main ,
  • Вы действительно должны закрыть все файлы, которые вы открыли ( fopen ->fclose ).
  • Функция scanf

    Для считывания данных в языке C используется функция scanf. Ее использование похоже на функцию prinf — сначала задается форматная строка, потом передаются переменные, в которые необходимо записать результат. Например, для считывания двух целых чисел функция вызывается так:

    Основное отличие функции scanf в том, что при считывании чисел (или значений типа char) ей необходимо передавать адреса переменных (в языке C все параметры передаются по значению, поэтому чтобы функция scanf могла модифицировать переменную, необходимо передать в функцию адрес этой переменной). Поэтому перед названиями переменных мы пишем знак амперсанда («&»).

    В функции scanf могут быть явно записаны какие-то символы, кроме форматных строк. Например, вызов

    можно использовать для считывания времени, заданного в виде hh:mm — функция считает число, затем символ двоеточия, затем опять число.

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

    Особенности считывания чисел

    Функция scanf корректно считывает целые числа, если они начинаются с символа 0, или со знака «+». То есть числа «+123» или «0123» будут корректно считаны по форматной строке «%d», никаких дополнительных параметров задавать не нужно.


    Также при считывании чисел игнорируются пробелы перед числом. Это означает, что вызов

    scanf(«%d:%d», &a, &b) сможет корректно считать время, заданное в формате hh:mm при наличии пробела после двоеточия (такая запись успешно считает строки «12:34», «01:02», «01:␣23» или «␣01:␣23», поскольку дается указание считать число, затем сразу же двоеточие, затем — число, перед которым могут быть пробелы). Но такая запись не считает выражение, например, вида «01␣:␣23», поскольку после первого числа сразу должно идти двоеточие.

    Чтобы считать записать вида «01␣:␣23» можно использовать форматную строку «%d :%d», причем пробел в форматной строке может означать и отсутствие пробелов.

    Возможные форматные символы

    Возможные форматные символы функции scanf для разных типов данных в целом соответствуют форматным символам для функции printf , но имеют меньше различных модификаторов.

    Форматная
    строка
    Соответствующий ей тип
    %hhd Считать число (десятичное) и записать его в переменную типа char (для unsigned char нужно использовать %hhu)
    %hd short int (для unsigned short int нужно использовать %hu)
    %d int (для unsigned int нужно использовать %u)
    %ld long int (для unsigned long int нужно использовать %lu)
    %lld long long int (для unsigned long long int нужно использовать %llu)
    %f float
    %lf double
    %Lf long double
    char. Считывается один символ, он может быть пробелом или символом конца строки.
    %s Считывается последовательность непробельных символов (строка), записывается в C-строку (типа char * или char[])

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

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

    Особенность считывания строк

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

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

    Иногда бывает полезно считать всю строку целиком вместе с пробелами до конца строки. Для этого используется функция gets . Например:

    Функция gets считается опасной и не рекомендуется для использования, так как она не контролирует количество считанных символов и не учитывает длину передаваемой строки, что может привести к записи данных за пределами строки.

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

    fgets(s, 101, stdin);

    В данном случае мы использовали stdin для чтения со стандартного ввода.

    Не следует забывать, что в языке C в конец строки добавляется нулевой символ для обозначения конца строки. То есть если необходимо считать строку, в которой может быть 4 символа, то для нее нужно создать массив char[5] , и функции fgets нужно передавать число, не меньшее 5.

    Возвращаемое значение

    Функция scanf возвращает значение, равное числу успешно считанных и записанных в переданные параметры значений, что можно использовать для анализа входных данных.

    Например, пусть вызвали scanf(«%d:%d», &a, &b) .

    Тогда при вводе строки «12:34» функция scanf считает два числа, запишет их в переменные a и b и вернет значение 2. А при вводе «12 34» будет считано только одно число, поскольку после него должно идти двоеточие, то второе число считано не будет и функция scanf вернет значение 1.

    Что такое код scanf

    Для ввода данных в консоли может использоваться функция scanf() . Эта функция определена в заголовочном файле stdio.h (там же, где и функция printf) и имеет следующее формальное определение:

    И форматная_строка, и аргументы для функции scanf обязательны.

    Форматная_строка содержит спецификации преобразования, которые определяют вводимые данные. Общий вид спецификаций преобразования:

    Из этих элементов обязательны только два: знак процента % и спецификатор.

    Спецификатор определяет тип вводимых данных:

    %c : считывает один символ

    %d : считывает десятичное целое число

    %i : считывает целое число в любой системе (десятичной, шестнадцатеричной, восьмеричной)

    %u : считывает положительное целое число

    %e : считывает число с плавающей точкой в экспоненциальной форме

    %E : считывает число с плавающей точкой в экспоненциальной форме с заглавным символом экспоненты

    %f : считывает число с плавающей точкой

    %F : считывает число с плавающей точкой

    %g : считывает число с плавающей точкой

    %G : считывает число с плавающей точкой

    %o : считывает восьмеричное число

    %x : считывает шестнадцатеричное число

    %X : считывает шестнадцатеричное число

    %s : считывает строку

    %% : считывает символ процента

    Символ звездочки * в спецификации преобразования позволяет пропустить при вводе водимые символы для типа, указанного через спецификатор.

    Ширина_поля представляет целое положительное число, которое позволяет определить, какое количество байтов будет учитываться при вводе.

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

    h : для ввода значений типа short int ( %hd )

    l : для ввода значений типа long int ( %ld ) или double ( %lf , %le )

    L : для ввода значений типа long double ( %Lf , %Le )

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

    Например, введем с консоли числовое значение:

    Здесь вводится значение для переменной age, которая представляет тип int , поэтому в форматную строку в функции scanf передается спецификатор %d . Здесь не используется ни символ звездочки, ни ширина поля, ни модификаторы. Вторым параметром идет адрес переменной age — &age .

    После ввода значения мы можем его использовать, например, вывести на консоль:

    Аналогичен будет ввод данных других типов:

    Здесь для имени выделяется 10 символов. Теоретически мы можем ввести и большее количество символов, но чтобы только 10 из них учитывались, в строку форматирования передается ширина поля, которая представляет 10 символов — %10s . Возможный консольный вывод:

    Можно сразу вводить несколько значений. В этом случае в качестве разделителя используется пробел:

    Курс C с нуля: часть 2 — printf и scanf

    • функции printf() и scanf() включены в стандартную библиотеку C. Эти функции и связанные с ними макросы описываются в заголовочном файле stdio.h ;
    • нам потребуется подключить файл stdio.h , что бы получить доступ к этим функциям.

    Функция printf()

    • функция printf() используется для печати символов, строк и чисел на экран;
    • мы используем функцию printf() со спецификатором формата %d для отображения целочисленного значения;

    • аналогично — %c используется для печати символов, %f — для чисел с плавающей точкой и так далее — мы рассмотри типы данных в следующей части;
    • что бы перенести текст на новую строку — мы используем оператор « n «.

    Пример использования printf() :

    Тут мы видим, как работают спецификаторы формата для функции printf() в C:

    • спецификатор %d заменен значением целочисленной переменной no;
    • %c заменен значением симольной переменной ch;
    • %f заменен значением переменной с плавающей точкой flt;
    • %lf заменен значением переменной с двойной точностью dbl;
    • %s заменен значением строковой переменной str;
    • %o заменен восьмиричным значением целочисленной переменной no;
    • %x заменен шеснадцатиричным значениемелочисленной переменной no;
    • n заменен новой строкой.

    Что такое код scanf

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

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

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

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

    Спецификаторы формата — им предшествует знак процента(%) — сообщают, какого типа данное будет прочитано следующим. Например, спецификатор %s прочитает строку, а %d — целое значение. Строка форматирования читается слева направо, и спецификаторы формата по порядку сопоставляются с аргументами, перечисленными в списке аргументов. Эти коды приведены в следующей таблице.

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

    Чтобы прочитать длинное целое, поставьте перед спецификатором формата модификатор l, а чтобы прочитать короткое целое — модификатор h. Эти модификаторы можно использовать с кодами формата d, i, о, и и х.

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

    Если вы используете современный компилятор, который поддерживает добавленные в 1995 году средства работы с двухбайтовыми символами, можете задействовать модификатор l применительно к спецификатору с, чтобы обозначить указатель на двухбайтовый символ с типом данных whcar_t. Модификатор l можно также использовать с кодом формата s, чтобы обозначить указатель на строку двухбайтовых символов. Кроме того, модификатор l можно использовать для модификации набора сканируемых двухбайтовых символов.

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

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

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

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

    примет значения, введенные как 10 20, но наотрез откажется от «блюда», поданного в виде 10,20.

    Символ *, стоящий после знака % и перед кодом формата, прочитает данные заданного типа, но запретит их присваивание. Следовательно, оператор

    при вводе данных в виде 10/20 поместит значение 10 в переменную х, отбросит знак деления и присвоит значение 20 переменной у.

    Команды форматирования могут содержать модификатор максимальной длины поля. Он представляет собой целое число, располагаемое между знаком % и кодом формата, которое ограничивает количество символов, читаемых для любого поля. Например, если вы хотите прочитать в переменную address не более 20 символов, используйте следующий оператор.

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

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

    поместит символ х в переменную а, пробел — в переменную Ь и символ у — в переменную с.

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

    поместит 10 в переменную х и 20 — в переменную у. Символ t отбрасывается, так как он присутствует в управляющей строке.

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

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

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

    Многие компиляторы позволяют с помощью дефиса задать диапазон. Например, следующий оператор заставляет функцию scanf() принимать символы от А до Z.

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

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

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

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

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

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

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

    Что такое ‘|’ означает строку в формате scanf

    Что такое ‘|’ в строке формата. Я не могу найти официальную спецификацию. Есть ли кто-нибудь, кто может дать мне подсказку?

    Когда я вводил что-то с несколькими ‘|’ , последний по-прежнему работает (просто означает, что программа не разбивается). Не требуется ли два буфера после строки формата. Первый разбился, когда входную строку можно разделить на несколько строк. Таким образом, между ними еще есть другая разница. Что это?

    Поэтому я не могу понять, почему последний работает, когда номер буфера меньше директивного числа, а первый — неудачный. Или кто-то может дать мне входную строку, чтобы последняя из них вышла из строя.

    Что такое ‘|’ в строке формата. Я не могу найти официальную спецификацию. Есть ли кто-нибудь, кто может дать мне подсказку?

    Это означает, что код ожидает буквальный | во входном потоке.

    Сказав, что спецификатор формата не будет работать.

    Часть %[^a] будет захватывать все символы, которые не a . Это означает, что он захватит даже | из входного потока. Он перестанет захватывать, когда символ a встречается в потоке. Конечно, это не соответствует буквальному | в строке формата. Следовательно, ничто после этого не будет обработано.

    Если я предоставляю вход def|akdk в следующую программу

    Я получаю следующий вывод

    что имеет смысл. BTW, последняя строка на выходе — пустая строка. Я не уверен, как это показать в ответ.

    Когда я меняю строку scanf на

    Я получаю следующий вывод

    что имеет смысл.

    Это не один из спецификаторов формата, поэтому он буквальный | символ, то есть он должен присутствовать во входном потоке. Официальная спецификация — это раздел, озаглавленный The fscanf function найденная в стандарте ISO (например, C11 7.21.6.2 ), и в соответствующем разделе говорится:

    Формат состоит из нуля или более директив: одного или нескольких символов пробела, обычного многобайтового символа (ни%, ни белого пробела), ни спецификации преобразования.

    Директива, которая является обычным многобайтовым символом, выполняется путем чтения следующих символов потока. Если какой-либо из этих символов отличается от тех, которые составляют директиву, директива выходит из строя, а разные и последующие символы остаются непрочитанными.

    Вы можете увидеть эффект в следующей полной программе, которая не может сканировать «four|1» когда вы ищете литерал _ но отлично работает, когда вы ищете | ,

    Илон Маск рекомендует:  Dec2hex (без огpаничения на вводимое число)
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL