Сделай Сам Свою Работу на 5

Использование функции scanf()

Лабораторная работа №3

ВВОД В СИ/СИ++

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

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

В этой главе мы подробно рассмотрим ввод данных с клавиатуры.


Рис.1. Откуда бы ни поступали данные,компьютер хранит их в памяти как переменные

 

 

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


Рис.2. При вводе данных прежнее значение переменной теряется

Функция gets()

Функция gets() вводит строку в переменную. Параметром функции является имя переменной. Рассмотримтакуюпрограмму:

main() { char name[15]; gets(name); puts(name); }

Функция gets() будет рассматривать первые 14 символов, введенные с клавиатуры, как значение строковой переменной с именем name. Вы помните, что Си отводит строковой переменной столько элементов памяти, сколько указано в максимальном значении при определении переменной, а так как один элемент необходим для нулевого символа (\0), реально можно ввести на один символ меньше. Если вы хотите ввести в переменную name строку, состоящую из 15 символов, то укажите в квадратных скобках максимальное значение 16:



charname[16];

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

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

 

Рассмотрим более подробный пример:

main() { charname[25]; printf("Пожалуйста, введите Ваше имя: "); gets(name); printf("Подтвердите, Вашеимя: %s", name); }

Когда программа будет выполняться, вы увидите на экране подсказку:

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

 

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

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

После нажатия клавиши Enter Си присваивает введенные символы переменной name и вставляет нулевой символ в конце строки. Затем программа переходит к выполнению второй функции printf() и на экране появляется вторая надпись (предположим, что вас зовут Петр Иванов):

Пожалуйста, введите Ваше имя: Петр ИвановПодтвердите, Ваше имя: Петр Иванов

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

Таким образом, функция gets() прекрасно подходит для ввода в программу строк.

Функция getchar()

Функция getchar() вводит с клавиатуры единичный символ. Для большинства компиляторов безразлично, к какому типу (char или int) вы отнесете вводимый символ, что обусловлено способом определения символьной переменной в K&R-стандарте языка Си.

Для ввода символа можно использовать оба этих формата:

int letter; char letter; letter = getchar(); letter = getchar();

Обратите внимание на то, что вызов функции getchar() осуществляется не так, как вызов функций, которые мы рассматривали раньше. Вместо того чтобы поставить имя функции в начало строки инструкции, мы относим его к переменной с помощью знака «равно». Эта запись означает: «Присвоить переменной letter значение, полученное в результате выполнения функции getchar()». Практически, функция getchar() рассматривается программой как значение переменной (рис.3). При выполнении этой инструкции вызывается функция getchar() и осуществляется ввод символа, который присваивается переменной. Функцияgetchar() не имеет аргумента. Поэтому круглые скобки после имени функции остаются пустыми.

Когда пользователь нажимает клавишу, getchar() отображает введенный символ на экране. В данном случае нажимать Enter нет необходимости, так как getchar()


Рис.3. Функция getchar()

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

Некоторые компиляторы Си и Си++ используют функцию getch(), которая вводит символ без последующего нажатия Enter. Может оказаться, что при работе с getchar(), эти компиляторы требуют нажатия Enter после ввода символа. Проверьте документацию вашего компилятора.

 

Для чего может понадобиться ввод единичного символа? Вероятно, вам приходилось видеть программы, в которых необходимо ответить «Да» или «Нет» в ответ на запрос, или выбрать один из пунктов предложенного меню. Функция getchar() идеально подходит в этих случаях, ведь при работе с ней нет необходимости нажимать Enter, ввод одного из предложенных на выбор символов позволяет немедленно продолжить выполнение программы.

Если значение переменной введено с помощью функции getchar(), оно, независимо от того, определена переменная как int или как char, может быть отображено с помощью функции putchar() или printf(). В последнем случае используется указатель формата %c:

/*getchar.c*/main() { intinitial; puts("Пожалуйста, введите следующий инициал."); initial=getchar(); putchar('\n'); putchar(initial); putchar('\n'); printf("%c", initial); }

Данная программа вводит символ в переменную initial, а затем отображает значение переменной на дисплее, используя функции putchar() и printf(). Если в качестве инициала вы ввели букву 'А', то на экране увидите эту букву, повторенную трижды на отдельных строках. Первый раз она появляется при вводе ее с клавиатуры, еще два раза — в результате выполнения инструкций программы. Как правило, после ввода символа большинство компиляторов не выполняет автоматический перевод на новую строку.

Используя указатель формата %d, можно отобразить на экране ASCII-код символа:

/*ascii.c*/main() { int letter; letter=getchar(); printf("ASCII-кодомсимвола \ %c является %d\n", letter, letter); }

Здесь мы присваиваем значение переменной letter, используя функцию getchar(), а затем, используя функцию printf(), выводим на экран значение переменной, записанное в двух форматах. Указатель формата %c обеспечивает отображение символа в таком виде, как он был введен с клавиатуры, а указатель формата %d преобразует значение переменной в целое число, ASCII-код данного символа.

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

«Для продолжения нажмите Enter»

Функцию getchar() можно использовать для приостановки выполнения программы, что может оказаться весьма полезно в некоторых ситуациях. Приведем простой пример. На экран можно одновременно вывести ограниченное количество строк (обычно 25). Если в программе используется длинный ряд инструкций puts(), при выполнении которых надо вывести больше строк, чем может поместиться на экране, первые появившиеся строки информации быстро уйдут за верхний край, и пользователь просто физически не успеет ознакомиться с их содержанием до того, как на этом месте появятся другие.

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

printf("Для продолжения нажмите Enter");getchar();

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


Рис.4. Использование функции getchar() для создания паузы в программе

Оператор получения адреса &

Вы уже знаете, что для каждой переменной, используемой в программе, отводится определенный объем памяти, который зависит от типа переменной. Каждый элемент памяти пронумерован от 0 и далее. Если компьютер имеет 2Мегабайта оперативной памяти, элементы будут пронумерованы от 0 до 2097151, как показано на рис.5. Эти номера и называют адресами элементов памяти.


Рис.5. Адреса элементов памяти

Когда вы определяете переменные, Си резервирует память для хранения их значений. Например, для целочисленной переменной с именем count, Си отведет два элемента (байта) памяти. Первый из них определяет адрес переменной.

На рис.6 показана переменная count, которая имеет значение 2341. Это значение хранится в элементах, имеющих номера 21560 и 21561, так что адрес переменной count (не значение!) — это число 21560. В качестве адреса достаточно указать номер первого элемента, поскольку Си знает, сколько памяти отводится для каждого типа данных. Если count относится к типу int, для нее требуется два элемента памяти, и если первый из них имеет номер 21560, то номер последнего — 21561.


Рис.6. Переменная и ее адрес

При ссылке на переменную (например, при выводе ее значения на экран) используется имя переменной. Можно также сослаться и на ее адрес, если поставить символ амперсанда (&) перед именем переменной, скажем, так: &count. Символ & называется оператором получения адреса. Он указывает Си, что вас в настоящий момент интересует адрес элемента памяти, где зарезервировано место для переменной, а не значение переменной, хранящееся в этом элементе. Поэтому, хотя переменная count имеет значение 2341, &count имеет значение 21560.

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

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

Функция scanf()

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

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

 

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


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

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

%d целые числа
%u беззнаковые целые числа
%f вещественные числа, float
%e вещественные числа в экспоненциальной форме
%g вещественные числа в наиболее коротком из форматов %f или %e
%c символы
%s строки
%o целые числа в восьмеричной системе счисления
%x целые числа в шестнадцатеричной системе счисления

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

main() { float amount; scanf("%f", &amount); }

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

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

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

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

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

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

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

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

main() { intcount; puts("Пожалуйста, введите число: "); scanf("%d", &count); printf("Число равно %d", count); }


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

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


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

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

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

charletter;scanf("%c", &letter);

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

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

main() { charname[25]; puts("Пожалуйста, введите Ваше имя: "); scanf("%s", name); puts(name); }

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


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

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

Использование функции scanf()

Давайте познакомимся с функцией scanf() поближе. Рассмотрим следующую программу:

main() {intcount;printf("Пожалуйста, введите целоечислоинажмитеEnter: ");scanf("%d", &count);printf("Подтвердите ввод числа: %d", count); }

Что произойдет во время работы программы?

  1. Функция printf() выведет на экран подсказку:
Пожалуйста, введите целое число и нажмите Enter:

Код «новая строка» отсутствует, поэтому курсор остановится в конце строки подсказки.

  1. Программа ждет, пока пользователь введет информацию.
  2. Вы набираете число и нажимаете Enter.
  3. Функция scanf() просматривает входной поток и определяет, какие символы можно ввести, а какие следует игнорировать. Если цифровые символы предшествуют нецифровым, она продолжает сканирование до тех пор, пока не встретится нецифровой символ или пробел. Цифровые символы преобразуются в число и заносятся по адресу переменной. Если нецифровые символы предшествуют цифровым, функция прекращает работу и вся напечатанная последовательность игнорируется.
  4. Курсор переходит к началу следующей строки.
  5. Функция printf() выводит на экран значение, присвоенное переменной, сопровождая его сообщением: «Подтвердите ввод числа».

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

Листинг 1. Программа, в которой вводятся четыре переменные. /*scanf3.c*/

main() { int count; float amount; char letter; char name[15]; puts("Введитецелоечислоинажмите Enter"); scanf("%d", &count); puts("Введите вещественноечислоинажмитеEnter"); scanf("%f", &amount); puts("Введите символ и нажмите Enter"); scanf("%c", &letter); puts("Введите строку и нажмите Enter"); scanf("%s", name); printf("%d %6.2f %c %s", count, amount, letter, name); }
Функцию scanf() можно использовать для ввода нескольких переменных в одной инструкции. Однако если пользователь не будет вводить данные точно в том порядке, в каком их ожидает функция, она может проигнорировать всю введенную информацию. Пока вы еще только изучаете Си, старайтесь избегать нескольких аргументов при вызове функции scanf(), лучше используйте отдельные инструкции для каждого элемента данных.

 

Разрешается определить символьную переменную как int, но для ввода ее значения следует использовать указатель %c, и ни в коем случае не %d. Указатель %d можно использовать, чтобы отобразить ASCII-код какого-либо символа с помощью функции printf().



©2015- 2019 stydopedia.ru Все материалы защищены законодательством РФ.