Как настроить смартфоны и ПК. Информационный портал
  • Главная
  • Программы
  • Чтение файла использование scanf в c. Изучение и использование функций printf() и scanf()

Чтение файла использование scanf в c. Изучение и использование функций printf() и scanf()

] 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 тесно связанны с операциями сравнения . Для начала приведем всевозможные операции сравнения:

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

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

Формат

Тип выводимой информации

десятичное целое число

один символ

строка символов

экспоненциальная запись

число с плавающей точкой, десятичная запись

используется вместо записи %f или %e

десятичное целое число без знака

восьмеричное целое число без знака

шестнадцатеричное целое число без знака

Инструкции, передаваемые функции printf(), когда мы хотим напечатать некоторую переменную, зависят от того, какого типа эта переменная. Например, при выводе на печать целого числа применяется формат %d, а при выводе символа - %c. Форматы перечислены в таблице.

Посмотрим теперь, как эти формы применяются:

/* печать */

#include

#define PI 3.14159

int number = 2003;

printf("Интернет-университет информационных технологий был открыт в %d году \n", number);

printf("Значение числа pi равно %f.\n", PI);

Формат, указываемый при обращении к функции printf(), выглядит следующим образом:

printf(Управляющая строка, аргумент1, аргумент2,_);

аргумент 1, аргумент 2 и т.д. - это печатаемые параметры, которые могут быть переменными, константами или даже выражениями , вычисляемыми перед выводом на печать.

Управляющая строка - строка символов, показывающая, как должны быть напечатаны параметры. Например, в операторе

printf("%d студентов получили оценку %f.\n",

управляющей строкой служит фраза в кавычках, а number и z - аргументы или в данном случае значения двух переменных.

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

    Символы, печатаемые текстуально.

    Идентификаторы данных, называемые также спецификациями преобразования .

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

printf("Эта книга не очень дорогая!\n");

printf("%c%d\n","$",cost);

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

Например:

printf("Только %d%% населения способно учиться самостоятельно! \n",i);

Результат работы программы будет выглядеть следующим образом:

Только 5% населения способно учиться самостоятельно!

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

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

Значение

Аргумент будет печататься с левой позиции поля заданной ширины. Обычно печать аргумента оканчивается в самой правой позиции поля. Пример: %-10

строка цифр

Задает минимальную ширину поля. Большее поле будет использоваться, если печатаемое число или строка не помещается в исходном поле Пример: %4d

строка цифр

Определяет точность: для типов данных с плавающей точкой число печатаемых цифр справа от десятичной точки; для символьных строк - максимальное число печатаемых символов Пример:

%4.2f(две десятичные цифры для поля шириной в четыре символа)

Соответствующий элемент данных имеет тип long, а не int Пример: %ld

printf("/%d/\n",135);

printf("/%2d/\n",135);

printf("/%10d/\n",135);

printf("/%-10d/\n",135);

Первая спецификация преобразования %d не содержит модификаторов. Это так называемый выбор по умолчанию, т. е. результат действия компилятора в случае, если вы не дали ему никаких дополнительных инструкций. Вторая спецификация преобразования - %2d. Она указывает, что ширина поля должна равняться 2, но, поскольку число состоит из трех цифр, поле автоматически расширяется до необходимого размера. Следующая спецификация %10d показывает, что ширина поля равна 10. Последняя спецификация %-10d также указывает ширину поля, равную 10, а знак - приводит к сдвигу всего числа к левому краю.

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

Управляющая строка, на которую указывает format, состоит из символов трех типов:

  • Спецификаторы формата
  • Специальные символы
  • Прочие символы (не специальные)

Спецификаторы формата следуют за символом процент и сообщают scanf(), данные какого типа будут считаны следующими. Коды спецификаторов приведены в таблице.

Табпица: Коды форматов для scanf()
Код Значение
Считать один символ
%d
%i Считать десятичное число целого типа
%f Считать число с плавающей запятой
%g Считать число с плавающей запятой
Считать восьмеричное число
%s Считать строку
Считать шестнадцатиричное число
Считать указатель
%n Принимает целое значение, равное количеству считанных до текущего момента символов
%u Считывает беззнаковое целое
% Просматривает набор символов
%% Считывает символ %

Например, %s считывает строку, a %d считывает переменную целого типа.

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

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

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

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

Scanf("%d", &count);

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

Scanf("%s", address);

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

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

Scanf("%d%d", &r, &с);

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

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

Scanf ("%d%*c%d", &х, &у);

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

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

Scanf ("%20s", address);

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

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

Scanf("%с%с%с", &а, &b, &с);

Поместит символ х в переменную а, пробел - в переменную b и y - в переменную c.

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

Scanf ("%st%s", &х, &у);

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

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

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

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

С помощью кавычек можно задать диапазон воспринимаемых символов. Например, следующее выражение дает указание scanf() принимать буквы от «А» до «Z»:

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

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

При использовании Borland С++ в 16-разрядной среде можно изменить модель памяти, ис­пользуемую по умолчанию для компилирования программы, путем явного указания размера каж­дого указателя, используемого при вызове scanf(). Ближний указатель задается модификатором N, а дальний - модификатором F. (Нельзя использовать модификатор N, если программа ском­пилирована для модели памяти huge.)

Функция scanf() является многоцелевой функцией, дающей возможность вводить в компьютер данные любых типов. Название функции отражает ее назначение- функция сканирует (просматривает) клавиатуру, определяет, какие клавиши нажаты, и затем интерпретирует ввод, основываясь на указателях формата (SCAN Formatted characters). Так же, как и функция printf(), scanf() может иметь несколько аргументов, позволяя тем самым вводить значения числовых, символьных и строковых переменных в одно и то же время.

Так же, как список параметров printf(), список параметров функции scanf() состоит из двух частей: строки формата и списка данных (рис.5.7). Строка формата содержит указатели формата, здесь они носят название преобразователей символов *, которые определяют то, каким образом должны быть интерпретированы вводимые данные. Список данных содержит переменные, в которые должны быть занесены вводимые значения.

Рис. 5.7. Список параметров функции scanf() делится на две части

Указатели формата аналогичны тем, которые используются функцией printf():

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

scanf("%f", &amount);

* В оригинале conversion characters. (Прим.перев.)

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

На время работы функции scanf(), выполнение программы приостанавливается, и программа ожидает ввода данных. Ввод заканчивается нажатием клавиши Enter .

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

Входной поток

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

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

Принято говорить, что scanf() получает данные из входного потока . Входным потоком называется последовательность символов, поступающих из некоторого источника. В случае функции scanf() источником служит клавиатура. После нажатия клавиши Enter все данные, которые были введены к этому времени, передаются функции scanf() в виде пока еще бессмысленного набора символов, в том же порядке, в каком их набирали. Затем scanf() определяет, какие символы соответствуют типу, заданному указателем формата, а какие следует игнорировать. Указатели формата называют преобразователями символов, так как они берут исходные символы из входного потока и преобразуют их в данные, относящиеся к определенному типу. Рис.5.8 иллюстрирует этот процесс.

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

puts("Пожалуйста, введите число: ");

scanf("%d", &count);

printf("Число равно %d", count);

Рис. 5.8. Функция scanf() читает входной поток и определяет,какие данные следует ввести, а какие- игнорировать

Перед тем как ввести число, вы можете нажимать на клавишу пробела столько, сколько хотите- Си будет игнорировать пробелы, в ожидании первого значимого символа. Затем Си попытается преобразовать символы в соответствии с указателями формата в строке формата функции scanf(). Если эти символы соответствуют формату (в данном случае- если это цифры), они будут внесены в переменную. Ввод данных прекратится, если встретится символ, формат которого не соответствует ожидаемому, то есть он не является цифрой. Например, если набрать на клавиатуре последовательность «123abc», то число 123 в нашем примере будет присвоено переменной count, а буквы «abc»- проигнорированы, как это показано на рис.5.9. Остановку ввода данных может вызвать пробел. Например, если напечатать «123», то переменной будет присвоено значение 12, а число 3- проигнорировано.

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

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

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

scanf("%c", &letter);

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

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

puts("Пожалуйста, введите Ваше имя: ");

scanf("%s", name);

Обратите внимание, оператор получения адреса не используется с именем строковой переменной. Если вы наберете на клавиатуре «Нэнси» и нажмете Enter, эти символы будут присвоены переменной name. Даже если набрать «Нэнси Чезин», scanf() начнет присвоение символов с первого значимого символа и остановит, встретив первый пробел, так что значением переменной все равно станет только имя Нэнси, а остальное программа проигнорирует (рис.5.10).

Рис. 5.10. Функция scanf() прекращает чтение символов в строкепри появлении первого пробела

Из-за этой особенности функции scanf(), она является не слишком удобной для ввода строк. В этих случаях лучше использовать функцию gets().

Лучшие статьи по теме