Программирование для решения задач
Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
2 лекция
Программирование
Решение многих задач, возникающих в самых различных сферах человеческой деятельности, было бы невозможно без применения компьютеров. Причем компьютеры — это не только вычислительные устройства с дисплеем, которые стоят в классе информатики или дома на столе. Они окружают нас повсюду: «притаились» в плеере, мобильном телефоне, фотоаппарате, в турникетах в метро и в школе, и даже в домашних бытовых приборах.
Для каких бы целей ни было предназначено устройство: полет ракеты на Марс, расчет зарплаты, выдача денег в банкомате, пропуск учеников в школу — надо «научить» его решать поставленную задачу, т. е. написать инструкции, детально разъясняющие, как действовать во всех возможных ситуациях. Деятельность по написанию таких инструкций (команд) для вычислительных машин или управляющих чем-либо устройств называется программированием, а сами инструкции — программами.
Этапы решения задачи
Предположим, что перед нами стоит задача, для решения которой необходимо написать программу. Решение задачи разбивается на этапы.
1. Постановка задачи. Необходимо определить, каковы будут исходные данные (что подается «на вход») и каких результатов надо достичь (что получить «на выходе»). При решении учебных задач этот этап иногда может отсутствовать, так как исходные данные и конечные результаты определены в формулировке задания.
2. Выбор метода решения и разработка алгоритма. Это один из основных, главных этапов решения задачи. От правильности выбора метода и эффективности алгоритма зависят размер программы и ее быстродействие.
3. Составление программы и ввод ее в память компьютера. Часто именно этот этап неправильно называют программированием. На самом деле, составление программы — лишь некоторая часть решения задачи с помощью компьютера. Сейчас этот процесс принято называть кодированием.
4. Отладка программы. Созданная программа может содержать ошибки, допущенные как в процессе кодирования, так и на любом из предыдущих этапов (может быть, неправильно разработан алгоритм, неверно выбраны исходные данные и т. д.). Ошибки выявляются в процессе отладки и тестирования — выполнения программы с заранее подготовленными наборами исходных данных, для которых известен результат.
5. Вычисление и обработка результатов.
Остановимся подробнее на главном этапе — разработке алгоритма.
Что такое алгоритм?
Алгоритм — это система правил, набор инструкций, позволяющий решить некоторую задачу, детально разработанное описание методов ее решения.
С алгоритмами мы сталкиваемся в математике (алгоритм сложения многозначных чисел в столбик), физике, химии, при изучении языков (правила правописания); они подстерегают нас и в повседневной жизни: алгоритм перехода улицы, правила пользования лифтом и др. Поваренная книга так же является сборником алгоритмов для приготовления блюд.
Любой алгоритм рассчитан на то, что его инструкции будет кто-то выполнять. Назовем этого кого-то «исполнителем» и будем иметь в виду, что наши инструкции должны быть понятны ему, он должен уметь выполнять действия, записанные в алгоритме.
Существуют разные способы представления алгоритмов: с помощью формул, схем, рисунков, также можно записать алгоритм в виде программы и, конечно же, просто словами на обычном (естественном) языке.
Блок-схема. Основные конструкции
Для алгоритма с разветвлениями словесная запись в виде перечня инструкций не всегда удобна, в этом случае часто применяется графическая запись алгоритма в виде блок-схемы: каждая инструкция помещается в блок (на чертеже — геометрическая фигура), блоки соединяются стрелочками, определяющими порядок выполнения инструкций. Этот способ представления алгоритмов достаточно популярен и общепринят, существует даже Государственный стандарт на изображение блок-схем. Мы не будем детально его изучать и слишком буквально ему следовать, используем некоторые конструкции, с помощью которых удобно графически представлять изучаемые нами алгоритмы.
Каждый алгоритм должен иметь начало (точка входа), для его обозначения будем использовать значок овал, а для обозначения конца (выхода) — значок овал с крестиком внутри. Каждый алгоритм имеет ровно один вход, а вот выходов может быть несколько (но никак не менее одного!), так как процесс решения задачи должен когда-то заканчиваться с некоторым результатом, причем в зависимости от условий результаты могут получаться разные.
Рассмотрим наиболее часто используемые типы блоков (рис. 1). Сразу заметим, что в любой из этих блоков должен быть хотя бы один вход.
Прямоугольник. В нем приводится описание некоторых действий, которые необходимо выполнить. Из прямоугольника всегда выходит только одна стрелочка (т. е. следующая инструкция всегда четко определена).
Параллелограмм. В нем записываются данные, которые необходимо ввести или вывести (исходные или выходные данные). Из параллелограмма выходит тоже только одна стрелочка.
Ромб. Используется для обозначения ветвления. В ромбе размещается вопрос (условие), на который возможен ответ «да» или «нет» (забегая вперед, скажем, что такая конструкция называется «логическое выражение»). Из ромба должны выходить две стрелочки. Одна помечается словом «да» (или «верно», «истинно»), другая — словом «нет» (или «неверно», «ложно»). В зависимости от значения истинности помещенного в ромбик условия далее выполняется переход по одной из стрелочек.
Рисунок 1- Основные блоки алгоритма
Переменная. Присваивание
Составим алгоритм для решения следующей задачи. Человек приобрел огород треугольной формы. Какой длины забор ему понадобится, чтобы ого родить свой участок?
Понятно, что надо измерить все стороны треугольника и найти его периметр, сложив полученные величины. Для записи формул в математике, физике обычно используют буквенные обозначения. Мы тоже ими воспользуемся, обозначив длины сторон треугольника a, b и c, а периметр — P. Блок-схема алгоритма изображена на рис. 2.
Рисунок 2-Блок-схема
Обозначенные буквами величины мы будем называть переменными. При разных начальных условиях (разных огородах) они будут принимать разные числовые значения, меняться.
Обратите внимание на запись формулы P := а + b + c. Здесь вместо принятого в математике знака «=» использован знак, состоящий из двух символов «:=». Будем называть его присваиванием.
В математике знак равенства используется в двух случаях: когда надо проверить, равна ли правая часть левой (например, «если x = 0, то…»), и в формулах, когда надо подсчитать значение правой части и положить переменную в левой части равной этому значению (то есть присвоить ей это значение). Чтобы избежать двойного толкования этого знака, будем в первом случае использовать знак равенства «=» и называть это действие сравнением, а во втором — знак присваивания «:=», а действие — присваиванием переменной нового значения.
Этот значок произошел от такой стрелочки: 🢦. В записи программ для первых компьютеров эта стрелочка показывала, что некоторое число пересылается в определенную ячейку, то есть запись X🢦5 обозначала инструкцию: «число 5 переслать (положить) в ячейку, предназначенную для X». Таким образом, в левой части операции присваивания всегда пишется переменная, которая должна получить новое значение, а в правой — само значение (оно может вычисляться, то есть записываться в виде выражения).
С точки зрения компьютера переменная — это фрагмент оперативной памяти, в котором хранится значение. Компьютер обращается к этому участку памяти и записывает туда новое значение или считывает то, что там находится. Для наглядности память компьютера можно представить себе как большой шкаф с ящиками. Каждый ящик — это место для переменной. Для того чтобы можно было найти нужный ящик, наклеиваем на него табличку с именем. Теперь при необходимости туда можно положить значение или посмотреть, что лежит в ящике. И еще одна важная особенность: при обращении к переменной мы забираем из ящика не само значение, а его копию, то есть само значение остается в ящике без изменения.
При выполнении действия P := а + b + c сначала вычисляется правая часть, затем результат вычисления помещается в ящик с именем (табличкой) Р. Это и есть операция присваивания переменной значения. Она всегда работает справа налево.
Получившийся алгоритм — линейный. Займемся теперь нелинейными алгоритмами.
Условие. Виды разветвлений
Простейшая задача с разветвлением, пожалуй, такая: из двух чисел выбрать наибольшее (договоримся, что, если числа равны, «наибольшим» будет любое из них). Блок-схема этого алгоритма представлена на рис. 3.
Рисунок 3- Блок-схема алгоритма.
На рис. 4 вы видите, как выглядит блок проверки условия (разветвление) в общем случае. Официально он называется полной условной конструкцией.
Рисунок 4 - Блок-схема (полная условная конструкция).
В таком алгоритме выполняется одно из двух действий в зависимости от истинности условия. Однако часто бывают случаи, когда в подобной схеме присутствует только одно действие, которое надо реализовать при выполнении некоторого условия, а в противном случае делать ничего не надо. (Из жизни можно привести такой пример: «Если идет дождь, возьми зонт».) На рис.1.6 изображен частный случай разветвления — неполная условная конструкция, которую удобно называть обходом.
Рисунок 5 - Блок-схема (неполная условная конструкция).
Чтобы реализовать присваивание X := |X|, понадобится именно обход, так как значение X надо изменять только в том случае, когда значение X отрицательно (рис.6):
Рисунок 6 –Блок – схема программы.
Задача 1. Компьютеру сообщается значение X, а он печатает значение Y, которое находит по формуле:
Блок-схема решения представлена на рис. 7.
Рисунок 7 - Блок – схема программы.
Задача 2. Заданы 3 числа. Определить, можно ли построить треугольник с такими сторонами.
Чтобы определить, можно ли построить треугольник с заданными длинами сторон, существует несколько способов:
1. Наибольшая сторона должна быть меньше суммы двух других сторон.
2. Наименьшая сторона должна быть больше разности двух других сторон.
3. Каждая сторона должна быть меньше суммы двух других сторон.
4. Каждая сторона должна быть больше модуля разности двух других сторон.
Выбираем третий способ. Обратите внимание: если окажется, что какое - то неравенство не выполняется, то другие проверять уже не надо. Блок- схема решения задачи представлена на рис. 8.
Рисунок 8 - Блок – схема программы.
В этой схеме у нас один и тот же блок — параллелограмм, в котором записано, что построение невозможно, — повторяется трижды. Можно ли сократить схему, нарисовав только один такой блок и подведя к нему три стрелочки? Этого делать не стоит: получившаяся схема уже не разделится на блоки, описанные выше (условные конструкции в ней нельзя будет считать ни полными, ни конструкциями обхода). Мы будем в наших схемах использовать только описанные выше блоки, так как потом научимся их
«переводить» в программы на языке Паскаль.
Первая программа на языке Паскаль
Пусть наша первая программа будет такой (это достаточно известная стандартная программа, используемая при изучении языков программирования):
Program FIRST;
{Первая программа}
Begin
Writeln('Здравствуй, мир!');
End.
Рисунок 9 – Текст программы
Заметим, что, печатая текст этой программы на компьютере, вы должны в точности повторить все, как это написано здесь, соблюдая разбиение на строки, ставя все значки: пробелы, скобочки и т. п. Впоследствии мы узнаем, что некоторые из них обязательны, другие же нужны «для красоты». Не забудьте точку в конце текста, обратите внимание, что русский текст в предпоследней строчке — в апострофах, на клавиатуре этот значок справа, на той же клавише, что и русская буква «э», в нижнем регистре.
Понятие об алфавите языка
Первое, что мы узнаем — какие же буквы, символы, значки можно использовать в программе на Паскале. Ведь алфавит — конечный набор знаков, из которых строятся все конструкции, — является основой любого языка. Далее перечислены составляющие алфавита языка Паскаль:
• цифры (обычные десятичные арабские);
• латинские буквы, прописные и заглавные (будем их в дальнейшем называть маленькими и большими). К буквам еще относится символ «_» (подстрочник или нижнее подчеркивание), так как он используется именно в качестве буквы. Во многих конструкциях языка маленькие и большие буквы не различаются.
• специальные символы.
К специальным символам относятся разделители (пробел, разные скобки, знаки препинания, апострофы), знаки арифметических операций, операций сравнения, например:
+ - * / = ' . : ; < > [ ] ( ) { }
Есть среди специальных символов и такие, которые при печати на клавиатуре обозначаются двумя значками (парные символы):
<> <= >= := (* *) (. .)
В языке они интерпретируются как один символ (писать символы, входящие в пару, надо обязательно подряд, в одной строке без пробела).
Особое место среди специальных символов занимают служебные (зарезервированные) слова. В языке имеется фиксированный небольшой набор (несколько десятков) слов, зарезервированных для определенных целей (для любых других целей их использовать запрещается). Для того чтобы отличить служебные слова от других наборов символов, в учебниках их принято выделять жирным шрифтом или курсивом, писать с большой буквы, на письме — подчеркивать. Служебные слова состоят из букв — символов алфавита, однако мы их выделяем как особые неделимые единицы алфавита языка.
Мы здесь не задаемся целью привести полностью весь набор символов, допустимых в языке, не предъявляем список служебных слов для заучивания — со всеми этими объектами мы познакомимся в процессе изучения материала.
Перечисленные символы входят в стандарт языка и используются для написания его конструкций. Однако для написания подсказок пользователю или некоторых конструкций в процессе работы программы этих символов бывает недостаточно. Для адаптации программы под пользователей разных стран в язык ввели четвертую группу символов, не входящую в стандарт языка. Это символы национального алфавита, они имеют особый статус, их использование ограничено.
В естественном языке из символов алфавита составляются слова, фразы. Так и в Паскале из символов алфавита строятся сложные конструкции: имена, константы, операторы и, в конце концов, целая программа.
Вернемся к нашей программе, посмотрим, какие элементы алфавита мы в ней использовали.
Слова Program, Begin, End относятся к служебным. Как видим, служебные слова «заимствованы» из английского языка, так что выучить их будет несложно. Большие и маленькие буквы в служебных словах Паскаль не различает.
В нашей программе использовано много разделителей, а вот никаких знаков операций нет. Во второй строке мы видим текст на русском языке. Это — комментарий, пояснение к программе. Комментарий представляет собой один из особых случаев, где можно использовать символы национального алфавита.
Также в нашей программе использованы имена и константы.
Константы. С точки зрения языка, константы определяют изображения значений, запись которых подчиняется определенным правилам. Константы могут быть числовые, логические, символьные и строковые (об этом мы, естественно, поговорим подробнее позже).
В нашей программе присутствует одна константа-строка:
'Здравствуй, мир!'
Текст, составляющий содержимое константы-строки, заключен в символы-апострофы. В строковой константе (внутри апострофов) также можно использовать символы национального алфавита (и вообще любые символы, которые есть на клавиатуре). При этом большие и маленькие буквы различаются. Так, константы 'TIGR', 'tigr' и 'Tigr' — различные.
Имена. Объекты программы (переменные, функции, процедуры) должны иметь имена (идентификаторы). Иногда эти имена определены заранее, они называются стандартными (например, существует функция sin). В отличие от служебных слов назначение стандартного идентификатора может быть переопределено программистом (но делать это без особых причин во избежание путаницы не следует). Большинство же имен в своей программе придумывает программист.
В нашей программе именем является слово FIRST, мы его придумали, оно не определено языком. Writeln — тоже имя, но оно стандартное.
Имена (часто их называют идентификаторы) могут состоять из букв и цифр, начинаться должны с буквы, причем под буквами мы здесь подразумеваем только латинские буквы и значок «_». Большие и маленькие буквы в именах язык не различает. Длина имени, вообще говоря, не ограничивается (хотя понятно, что превышать длину строки она никак не может), но различаются идентификаторы по некоторому количеству первых символов (в большинстве версий — 63). Например, имена
A, A234, X45G, Dlina, Summa_Otr, Cos3 — правильные;
234A, СТОЛ, Summa-otr, cos(3) — неправильные;
KROKODIL, krokodil, Krokodil, KrokoDil — одинаковые.
Принципы записи и «внешний вид» программы
По правилам языка программа на Паскале может записываться вся в одну строчку, может в столбик (в любом месте, где стоит разделитель, может быть и конец строки); буквы, как мы уже говорили, можно использовать большие и маленькие вперемешку. До и после некоторых разделителей (например, пробел, знаки арифметических операций, скобки) разрешается добавлять любое количество пробелов. Таким образом, одна и та же программа может выглядеть совершенно по-разному. Какой способ записи предпочесть? Такой, при котором программа будет наиболее понятна человеку (для компьютера способ записи не важен), удобна для чтения и редактирования. Поэтому в процессе знакомства с конструкциями языка мы выработаем правила их записи, от которых постараемся не отступать.
О больших и маленьких буквах можем договориться уже сейчас. Не рекомендуется их использование «вперемешку»: компьютер прекрасно поймет и слово BeGiN, и bEGin, человеку же придется напрягаться, чтобы уловить смысл такой программы.
Допустимы три способа записи программы:
• вся программа пишется либо маленькими, либо большими буквами;
• слова, используемые в программе, начинаются с большой буквы (все остальные буквы в слове — маленькие); этот способ использован в нашей программе;
• часть программы целиком пишется маленькими буквами, часть — большими; этот способ применяется, когда кусок программы хочется особо выделить (например, чтобы были видны последние добавления).
Об именах было сказано, что они представляют из себя любую последовательность букв и цифр, начинающуюся с буквы. Слово «любую» не надо понимать буквально и давать имена объектам программы «бесконтрольно». Не стоит также и впадать в обратную крайность и давать всем объектам почти одинаковые имена типа A1, A2, A21 и т. п.
Имена должны быть не слишком длинными, легко читаться и отражать суть объекта. Например: Summa, Kvo_Otr, Factorial. В математике многие величины часто по традиции обозначаются некоторыми «стандартными» именами. От этой традиции без особых причин нет оснований отступать и в Паскале. Например, стороны прямоугольного треугольника можно называть A, B, C, угол — Alfa, радиус — R. В программировании тоже есть свои
«древние» традиции именования переменных. Например, счетчики, т. е. переменные, служащие для пересчета чего-то, обычно называются буквами I, J, K, L, M, N или словами, начинающимися с этих букв.
Этапы подготовки программы. Паскаль-среда
Как записывать программу, мы выяснили, а вот как ее ввести в компьютер и, главное, что делать с ней дальше, как заставить компьютер ее выполнять? В этом нам поможет специальная программа, точнее, комплекс программ, называемый Паскаль-среда.
Этапы подготовки программы
Ввести программу в память компьютера можно с помощью какого-либо текстового редактора (можно использовать, например, Блокнот, а вот Word — нельзя, он вставляет в текст дополнительные символы). Таким образом, на первом этапе программа представляет собой обычный текст, ее можно хранить в текстовом файле.
Назвать этот файл можно как угодно, однако для дальнейшей работы будет удобно, если при именовании файлов придерживаться некоторых принципов. Во-первых, будем давать файлам с программой на Паскале расширение PAS. Во-вторых, имена будем составлять только из латинских букв и цифр, и длина их не будет превышать 8 символов.
Но вся беда в том, что компьютер не понимает обычного текста, в том числе и текста на языке Паскаль, не понимает буквы, десятичные числа, а понимает только нули и единицы. Программа, которую может выполнять компьютер, должна быть написана на специальном машинном языке (его алфавит состоит только из нулей и единиц и больше ни единого символа, даже пробела, не содержит!). Кто же выполнит эту нудную работу, переведет программу с языка Паскаль на машинный язык? Не волнуйтесь, самим это делать не придется. Для этого существуют специальные программы- переводчики — трансляторы (от translate — переводить).
Есть разные методы трансляции. Транслятор с Паскаля кроме непосредственно перевода может выполнять еще некоторые действия, например? добавлять в программу нужные фрагменты, собирать ее из разных частей, поэтому он называется «компилятор» (от compile — собирать, составлять). Результатом работы компилятора является создание так называемого исполняемого файла (он имеет расширение EXE, от слова execute — выполнить), этот файл написан на машинном языке и может быть выполнен компьютером.
Таким образом, решение задачи на компьютере разбивается на следующие этапы:
1. Ввод текста программы в память компьютера. Создание соответствующего текстового файла.
2. Перевод программы на машинный язык, компиляция, создание EXE-файла.
3. Выполнение EXE-файла, получение результатов.
В разделе 1 мы говорили, что важной частью программирования является отладка программы, в процессе ее выполнения все эти этапы приходится выполнять несколько раз, только ввод текста заменяется его редактированием.
Основные функции Паскаль-среды
Чтобы нам не думать, с помощью какой программы какой файл обрабатывать, быстро переходить от одного вида работы к другому, и создан набор программ, который мы будем называть Паскаль-среда. Основные виды ее деятельности таковы.
1. Ввод и редактирование текста программы. Встроенный в среду Паскаль- редактор отличается от обычных текстовых редакторов тем, что ориентирован непосредственно на Паскаль, например, «знает» служебные слова и выделяет их специальным шрифтом или цветом, автоматически устанавливает курсор на нужное место при переходе на следующую строку (делает отступы слева), автоматически дает имени файла расширение PAS, дает возможность пользоваться справочной системой и т. п.
2. Трансляция (компиляция) программы, создание выполняемого файла.
3. Выполнение полученной программы, вывод результатов.
4. Работа с файлами: загрузка, сохранение, переименование, копирование и т. п.
5. Отладка программы (можно проследить ход выполнения программы «по шагам», узнать значения переменных в нужных точках).
Существует несколько сред для работы с Паскалем с разными названиями (к слову Паскаль добавляется приставка BORLAND, FREE, GNU, ABC и др.), некоторые из них имеют разные версии, могут запускаться из-под Windows или Linux; в средах могут использоваться разные версии языка Паскаль, разные компиляторы. Однако различия между ними невелики и проявляются лишь в весьма несущественных деталях, как правило, при работе с достаточно сложными и емкими программами, поэтому здесь углубляться в эти подробности не будем.
Дело в том, что язык Паскаль был разработан в 1970 году (автор — швейцарский ученый Никлаус Вирт (Niklaus Wirth)). Язык создавался как средство для удобной, наглядной записи алгоритмов и обучения программированию, но получил широкое распространение не только для этих целей и нашел практическое применение. При переносе этого «академического», разработанного «на бумаге» языка на реальные компьютеры разработчики программного обеспечения допускали различные отклонения от стандарта, предложенного автором, вносили добавления и изменения. Так появлялись различные «диалекты» языка. Понятно, что в 1970-х гг. не было графики, разных шрифтов, дисплеи были черно-белые. Новые возможности постепенно добавлялись в разные версии языка, иногда с некоторыми различиями. Мы будем здесь использовать версию Turbo Pascal 7.0. Подавляющее большинство программ будет работать и во всех прочих версиях (например, на Free Pascal), другие вы легко сможете адаптировать, так как, повторим, это должны быть весьма сложные программы, и вы к моменту их написания уже будете обладать достаточными знаниями (некоторые различия мы постараемся отметить).
Рассмотрим основные правила работы в Паскаль-среде (Turbo Pascal или Free Pascal — они очень похожи даже внешне).
Структура Паскаль-программы
Паскаль-программа состоит из заголовка и программного блока. Заголовок и блок отделяются друг от друга точкой с запятой, а за блоком, в конце всей программы, ставится точка. Эта точка является для транслятора признаком конца текста программы, дальше он читать ничего не будет. Именно поэтому в файл имеет смысл помещать только одну программу, если поместить несколько — компилироваться будет только первая.
Заголовок начинается со служебного слова Program, далее идет имя программы. Отметим сразу, что имя программы в наших примерах носит чисто информативный характер, оно не обязательно должно совпадать с именем файла, в котором хранится программа. В заголовке может содержаться еще некоторая информация, но мы ее рассматривать не будем, более того, в некоторых программах заголовок будем вообще опускать, так как в наших программах он никакой смысловой нагрузки не несет.
Блок программы состоит из раздела описаний и раздела операторов.
Они отделяются друг от друга точкой с запятой.
Все объекты, используемые в программе (имена, вводимые пользователем), должны быть описаны. В разделе описаний описываются метки, константы, типы данных, переменные, процедуры и функции. Нам в первую очередь понадобятся описания переменных и констант, а затем мы научимся описывать и более сложные объекты.
Раздел описаний может быть пустым (как в нашей первой программе), а может занимать почти весь текст программы.
В разделе операторов задаются действия, которые программа должна выполнить — операторы. Операторы отделяются друг от друга точкой с запятой, а весь раздел заключается в операторные скобки Begin-End.
Посмотрев на нашу программу, мы обнаружим в ней заголовок (мы дали программе имя FIRST) и раздел операторов, состоящий из одного оператора Writeln ('Здравствуй, мир!'), именно он и обеспечивает вывод текста на экран.
В программе есть еще одна строка, мы уже упоминали, что это — комментарий. Комментарием может быть любой текст, заключенный в фигурные скобки или в скобки, состоящие из двух символов: (* и *). Комментарии не оказывают никакого влияния на работу программы, можно даже сказать, что и не являются частью программы, предназначены они не для компьютера, а для человека. Комментарии используются для внесения пояснений в программу, дают возможность сделать ее более понятной, облегчить дальнейшую работу с ней. В комментариях может быть указана фамилия автора программы, номер решаемой задачи, дата последних изменений программы, может поясняться алгоритм, назначение переменных и т. п. Мы настоятельно рекомендуем вам комментировать свои программы, чтобы их легче было использовать при подготовке к контрольным работам, экзаменам.
Основные типы данных. Описания переменных. Присваивание
Имена, вводимые программистом (в том числе переменные и константы), должны быть описаны в программе в разделе описаний.
Описания переменных начинаются служебным словом Var (Variation — изменение, переменная). Далее идет список переменных какого-либо одного типа через запятую, затем двоеточие и указание типа.
Описания переменных разного типа отделяются друг от друга точкой с запятой, а слово Var можно не повторять:
Var K,M : Integer;
Stroka : String;
Здесь описаны две переменные K и M типа Integer и переменная Stroka типа String. Имена переменных мы придумали сами, а вот имена использованных здесь типов определены языком, это стандартные имена, их описывать не надо.
Язык не запрещает помещать несколько описаний в одной строке, но лучше описания разных типов писать в отдельных строках. Можно добавлять комментарии, поясняющие, для чего будет использоваться та или иная переменная.
Самым существенным в описании переменной является ее тип. Тип указывает, что собой представляет значение переменной — символ, число, массив чисел и т. п. Зачем важно знать тип переменной? Во-первых, для размещения переменных разных типов в памяти компьютера нужен разный объем памяти, данные по-разному кодируются, имеют разный допустимый диапазон значений. Во-вторых, над данными разных типов возможны разные операции. Например, числа можно делить друг на друга, а применительно к символам такая операция недопустима.
Интересно, что данные разных типов при записи на бумаге и даже при выводе на экран могут выглядеть совершенно одинаково. Например, число
«5» и символ «5» на экране передаются одной и той же «картинкой», однако в памяти компьютера выглядят совершенно по-разному (по-разному кодируются) и в программе имеют совершенно разный смысл.
Типы данных можно разделить на две группы: основные (простые) и производные. Переменная простого типа имеет какое-то одно значение, переменная производного типа может обозначать целую структуру, состоящую из нескольких компонент. В этом разделе предметом нашего изучения будет простой тип.
Некоторые типы данных и работа с ними
Нам чаще всего придется иметь дело с числами, поэтому с них и начнем.
Числа в языке Паскаль подразделяются на целые и вещественные. Вещественные числа — это числа, у которых есть целая и дробная части, пусть даже равные нулю. Различия между целыми и вещественными числами весьма существенные, хотя числа, «выглядящие» совершенно одинаково на экране компьютера, могут быть как целыми, так и вещественными.
Во-первых, у них разный диапазон значений, во-вторых, разный набор допустимых арифметических операций, а главное — целый тип относится к так называемым ординальным типам (от order — порядок), а вещественный тип — не ординальный.
Разберемся сейчас с этим понятием, так как оно неоднократно понадобится нам в будущем. Ко всем значениям ординального типа применима стандартная функция Ord, которая дает номер значения в типе. Целые числа можно пронумеровать, для любого числа (кроме самого большого и самого маленького) найдется единственное предыдущее и последующее. Например, для числа «5» предыдущим является «4», а следующим — «6». Для вещественных чисел это совсем не так. Какое вещественное число непосредственно следует за вещественным «5»? Может быть, «5.1»? Или «5.01»? Или «5.0000001»? Эти и некоторые другие различия между целыми и вещественными числами, которые мы в обычной жизни практически не замечаем, оказываются очень важными в программировании, поэтому при изучении каждой новой темы, новых операторов, в которых встречаются числа, всегда следует обращать внимание, о каких числах идет речь.
Целые числа
Для описания целых чисел обычно используется стандартное имя типа Integer. В реальной жизни диапазон целых чисел не ограничен, при работе на компьютере это совсем не так. Для хранения числа отводится фиксированный объем памяти, поэтому существует минимальное (отрицательное) и максимальное значение типа Integer. Они, вообще говоря, могут различаться в разных версиях языка, и значение максимального целого числа зафиксировано в константе MaxInt (это стандартная константа, ее не надо описывать).
Обычно минимальное целое число: -MaxInt-1.
Диапазон значений этого типа невелик, но, так как тип в основном используется для разного рода счетчиков (например, количество учеников в классе), его обычно хватает. В разных версиях языка есть и другие описатели для целых чисел: LongInt, ShortInt, Word, Byte. Информацию о них (диапазон значений) вы можете посмотреть сами, используя «помощь» в Паскаль-среде. Наберите в редакторе слово Integer, подведите к нему курсор, вызовите справку нажатием Ctrl + F1.
Все указанные типы отличаются только диапазоном значений, поэтому, когда далее мы будем говорить о типе Integer, следует понимать, что все сказанное относится и к другим типам целых чисел. В программах мы будем использовать в основном тип Integer. Когда в отдельных случаях нам понадобится использование какого-либо другого целого типа, мы оговорим это особо.
Изображаются целые числа обычным образом: в виде последовательности цифр, причем, если перед числом записать один или несколько нулей (незначащие нули), это не будет ошибкой. Перед числом может стоять знак («+» или «–»), знак «+» можно не писать.
Примеры изображения целых чисел:
1 100 0125 -53 +3200 -0007
Пример описания данных целого типа:
Var K,M : Integer;
Вещественные числа
Для описания вещественных чисел обычно используется стандартное имя типа Real. Как и в случае целых чисел, на вещественные числа, которые может использовать компьютер, наложены ограничения. Ограничения связаны с диапазоном и с точностью представления чисел (количеством верных значащих цифр в числе). Сразу скажем, что кроме Real в разных версиях Паскаля существуют другие типы вещественных чисел, отличающиеся друг от друга как раз этими показателями. Мы будем использовать Real, а посмотреть, какие еще бывают описатели, оценить характеристики описываемых ими чисел вы можете с помощью справочника Паскаль-среды.
Примеры описания данных вещественного типа:
Var S,D : Real;
Изображаются вещественные числа двумя способами: с фиксированной и с плавающей точкой. Оба типа представления могут иметь или не иметь знак «+» или «–».
Запись с фиксированной точкой — это та запись, к которой вы привыкли в школе (только целая часть числа отделяется от дробной знаком «.», а не «,»). Сначала записываются цифры целой части, потом ставится точка, а затем пишутся цифры дробной части (без пробелов!). Ни целая, ни дробная части не могут быть пустыми, обязательно хотя бы одна цифра (например, ноль) должна присутствовать.
Примеры:
Правильные числа с фиксированной точкой
Неправильные числа
0.5
+3.141591
–123.456789
0.0000000004
.5
124.
3,14159
25h
Если число очень большое или очень маленькое (как последнее из правильных в нашем примере), запись с фиксированной точкой неудобна: приходится, напрягая глаза, подсчитывать количество нулей. В этом случае удобно применять запись с плавающей точкой.
При записи чисел с плавающей точкой число представляется в виде произведения мантиссы на степень числа 10 (показатель степени называется
«порядок»); например, 1234 = 1.234 * 103, 0.00123 = 1.23 * 10–3. В Паскале все записи делаются одинаковым шрифтом и в одну строку, поэтому нельзя показатель степени записать, как это принято, маленькими цифрами сверху. Для того чтобы отделить порядок от мантиссы, используется буква E (латинская, большая или маленькая), а символ умножения и число 10 не пишутся вообще. Получается вот такая непривычная запись числа: цифры (возможно, разделенные точкой), затем буква E (e), за которой следует изображение целого числа (как положительного, так и отрицательного). Например: 12E – 5, 34.7e + 6, 0.04E21.
Заметим, что после буквы E стоит показатель степени, он может быть только целым; до буквы E стоит мантисса, она может быть представлена как целым числом, так и числом с фиксированной точкой. Число в любом случае понимается как вещественное. Все «части» числа обязательно должны присутствовать, поэтому вот такие числа: 12.е45, .34E5, 123E — являются неправильными.
В качестве примеров запишем одни и те же числа в разном представлении.
С плавающей точкой
Привычное представление
С фиксированной точкой
3.1415E0
3,1415 * 100
3.1415
5E–7, 5E–07, 0.5E–006
5 * 10–7, 0,5 * 10–6
0.0000005
4E5, 04E05, 4.0E+5
4 * 105
400000
1.2345E4, 0.12345E5
1,2345 * 104, 0,12345 * 105
12345
1.2345E–4, 123.45Е–6
1,2345 * 10–4, 123,45 * 10–6
0.00012345
Операции над числами
Конечно, и над вещественными, и над целыми числами в Паскале определены привычные нам арифметические операции.
Сложение, вычитание и умножение
Вычитание и сложение обозначаются теми же знаками, что и в математике, умножение обозначается звездочкой, причем, в отличие от математических формул и уравнений, где знак умножения часто опускается, в Паскале его писать обязательно (в математике запись 5X допустима и понимается как умножение, в программе на Паскале нужно писать 5*X).
При целых аргументах результат операции получается целый, если хотя бы один из аргументов вещественный — результат вещественный. Заметим, что важен именно тип аргумента, а не его значение: при сложении вещественных чисел 2.7 и 4.3 получается число 7, которое «по внешнему виду» можно принять за целое, однако в компьютере оно будет кодироваться как вещественное (иногда, чтобы это было понятнее, такое число записывают как 7.0).
Деление
В Паскале три операции деления.
1. «Обычное» деление обозначается знаком «/». Независимо от аргументов результат такого деления вещественный (Real). На это стоит особо обратить внимание: даже если результат выглядит целым (например, 5/1 = 5, 20/2 = 10), для компьютера он является вещественным числом с дробной частью, равной нулю.
Следующие две операции применимы только к целым числам (оба числа должны быть типа Integer). Результат тоже будет целым. Обе эти операции — части действия, которое в школе называется «деление с остатком». Поскольку значков для этих операций не хватило, они обозначаются с помощью служебных слов div и mod. Между названием операции и операндами (делимым и делителем) обязательно должны быть пробелы.
2. Нахождение целой части от деления числа — div.
3. Нахождение остатка от деления — mod.
Соответственно, возможны записи: X div Y; 35 div 21; A mod 4.
Естественно, ни один из видов деления невозможен, когда делитель равен 0. Операции mod и div обычно применяются к положительным числам, но на всякий случай заметим, что для отрицательных чисел они в разных версиях Паскаля могут давать разный результат.
Деление с остатком обычно проходят в начальной школе и «с возрастом» основательно забывают. Давайте вспомним, что это такое.
Повторим, операция выполняется только над целыми числами и все результаты тоже целые. А результатов два: неполное частное и остаток. Пусть M и N положительные. Чтобы число M разделить на N с остатком, надо подобрать такое максимальное число K ≤ M, которое нацело делится на N. Результат деления K на N — неполное частное, разность M – K — остаток. Заметим, что если M делится на N нацело, то остаток равен 0. Если M < N, то неполное частное равно 0, а остаток равен самому числу M. Остаток всегда меньше делителя.
Если частное обозначить С (С:=M div N), а остаток T (T:=M mod N), выполняется соотношение: С*N+T=M.
Несколько примеров:
Делимое M
Делитель N
Частное
M div N
Остаток
M mod N
10
5
2
13
5
2
3
4
5
4
Отметим интересную особенность деления с остатком на 10. Остаток от деления числа на 10 равняется последней цифре этого числа, а частное — числу без последней цифры:
12345 mod 10 = 5;
12345 div 10 = 1234.
Первую цифру числа можно получить, если поделить его на 10k–1, где k — количество цифр в числе: 543 div 100 = 5 — при этом остаток от деления будет равен числу без первой цифры: 543 mod 100 = 43.
Функции
В языках программирования часто возникает необходимость проведения одинаковых вычислений с разными исходными данными. Для упрощения таких вычислений можно написать специальным образом оформленный программный блок и подключать его к своей программе. Такой блок называется функцией. Функции может писать программист, но есть и набор стандартных функций, входящий в состав языка.
Большую часть функций, известных из математики, можно использовать в Паскале. При записи функций надо учитывать, что их аргумент всегда пишется в круглых скобках.
Некоторые функции записываются так же, как в математике, например, можно написать: sin(x); cos(3*z-5).
Для функций, которые в математике записываются специальными значками, в Паскале пришлось придумать буквенные названия:
• abs — взятие модуля (от слов «абсолютная величина»);
• sqr — возведение в квадрат (square — квадрат);
• sqrt — извлечение квадратного корня (square root — квадратный корень).
Чтобы список математических функций был полным, остается упомянуть arctan (арктангенс), ln (натуральный логарифм, то есть логарифм по основанию e) и exp (экспоненту, степень числа e). Возможно, эти названия вам еще незнакомы, но как только вы их изучите в школе, использование соответствующих функций в Паскале не составит труда.
Все эти функции имеют один аргумент (целый или вещественный), результат у abs и sqr того же типа, что и аргумент, а у всех остальных функций результат всегда вещественный.
В Паскале определены не только математические функции, есть еще логические, строковые, мы с ними познакомимся в дальнейшем.
Сейчас остановимся на тех функциях, которые часто используются в математике, но отсутствуют в Паскале. Это в первую очередь тангенс и возведение в степень.
Думаю, любой читатель сможет выразить тангенс через имеющиеся в Паскале функции. Кстати, аргументы тригонометрических функций в Паскале выражаются в радианах.
Для представления функции возведения в степень также существует формула (в ней используются exp — экспонента и ln — натуральный логарифм). Кто уже знаком с этими функциями из школьного курса, легко сможет вывести эту формулу (воспользовавшись основным логарифмическим тождеством), остальным придется немного подождать, поэтому здесь мы ее приводить не будем.
Иногда возникает необходимость «перевести» вещественное число в целое, округлить. Для этого существуют специальные функции, аргументами которых являются вещественные числа, а результаты — целыми:
• trunc — дает целое число, которое получается отбрасыванием цифр после точки и самой точки: trunc(1.8)=1; trunc(1.1)=1; trunc(-2.6)=-2; trunc(-10.4)=-10;
• round — дает округленное целое число: round(1.8)=2; round(1.1)=1; round(-2.6)=-3; round(-10.4)=-10.
Чтобы хорошо понять, как работают эти функции, полезно знать, что они связаны формулой:
Запись и вычисление арифметических выражений
В арифметическом выражении на Паскале могут использоваться константы и имена переменных, знаки арифметических операций, функции. Скобки можно использовать только круглые. Порядок выполнения операций привычный, как в математике: сначала вычисляются аргументы функций и сами функции, потом выполняются действия в скобках, потом слева направо операции 1-го ранга: *, /, div, mod, затем — операции 2-го ранга: + и –. Запись арифметического выражения на Паскале должна быть линейной,
из-за этого часто возникают «лишние» скобки, которые не нужны в обычной записи, например, в дробях:
— на Паскале будет выглядеть (a+b)/(x–y).
Пример. Вспомним формулу вычисления дискриминанта и корней квадратного уравнения и запишем ее на Паскале.
Получим дискриминант: sqr(b)–4*a*c.
Один из корней(-b+sqrt(D))/(2*a) или (-b+sqrt(D))/2/a,
где sqr(x) — это x2, а sqrt(x) — это .
Сравнение чисел
Понятно, что числа можно сравнивать по величине. В Паскале определены все известные нам из математики операции сравнения, записываются они обычным образом, только для некоторых приходится использовать два символа:
= — равно;
>= — больше или равно;
<= — меньше или равно;
<> — не равно.
Со сравнением целых чисел никаких проблем не возникает, а вот о вещественных придется поговорить. Дело в том, что если два вещественных числа почти одинаковы, они могут «выглядеть» одинаково (например, будучи напечатанными на экране), но различаясь, например, в самом последнем знаке после запятой, одинаковыми (равными) не являться. Следует знать, что, если из вещественного числа извлечь корень, а потом обратно возвести его в квадрат, может получиться величина, чуть-чуть отличная от первоначальной, т. е. sqr (sqrt(x)) не всегда равно x. Эта ситуация не должна быть новой для вас, если вам приходилось считать на калькуляторе: например, иногда можно подобрать такие числа (ненулевые), что результат деления одного на другое будет равен нулю. Эта проблема может вызвать неприятности, если в программе надо проверить, не равны ли друг другу два вещественных числа. В таком случае для подстраховки проверяют числа не на точное равенство (x=y), а на приблизительное (abs(x–y) := <выражение>
Здесь и далее, если в определении потребуется указать не конкретное слово или значение, а некоторое понятие, будем заключать его в угловые скобки.
С понятиями «переменная» и с самим знаком присваивания мы уже сталкивались в разделе 1, а понятие «выражение» имеет общепринятый смысл: переменные и константы, связанные допустимыми знаками операций. Простейшими примерами выражений являются единичная переменная или константа.
Переменная и выражение должны быть совместимых типов. Нельзя переменной, описанной как Char (предназначенной для символов), присвоить значение арифметического выражения, а переменной целого типа — строку. В то же время мы не говорим, что типы обязаны совпадать. Дело вот в чем. Переменной типа String можно присвоить значение типа Char, так как символ — частный случай строки. Переменной типа Real можно присвоить значение типа Integer. Конечно, нельзя сказать, что целые числа являются частным случаем вещественных, просто при таком присваивании транслятор автоматически получившееся в правой части оператора целое число превращает в вещественное (создает ему дробную часть, равную нулю). Важно знать, что обратная операция автоматически не выполняется. Если результат какой-либо операции вещественный, его нельзя присвоить целой переменной, вначале надо его округлить с помощью специальных встроенных функций, о которых мы говорили выше.
Примеры правильных операторов присваивания мы не сможем показать, не указывая типа используемых в них переменных. Следовательно, придется написать программу, так как нужен раздел описаний. Эта программа ничего не делает, ее текст следует рассматривать лишь как пример правильных операторов присваивания с переменными разного типа.
Var H,C : Char; St : String;
I,J : Integer; X,Y : Real;
Begin
St:='123'; H:='%'; C:=H; St:=C;
I:=ord(C); J:=I+1; H:=chr(J); X:=1.1; Y:=J*2;
I:= 10 mod 3; X:=100/4
End.
Рисунок 10 –Текст программы
В рамках тех же описаний неправильными операторами присваивания будут:
St:=123 — строке нельзя присвоить число;
H:='12' — символьной переменной нельзя присвоить строку;
I:=Ord(X) — аргумент функции Ord должен быть целым числом;
J:=I/2 — результат операции деления «/» всегда вещественный, его нельзя присвоить целой переменной.
На этом мы закончим список неправильных операторов присваивания — скоро вы самостоятельно начнете писать программы и сможете его пополнить.
Пример программы с разными типами данных и операторами присваивания
Все представленные выше сведения о языке полезно проверить на практике, с помощью соответствующих программ. Приведем пример.
Program Types;
Const Stroka=’##############################’;
Ot=’Ответ таков:’;
Var M,N, Celoe,Ost : Integer; {Делимое, делитель, целая
часть и остаток от деления}
Var A,B,C:Real; {катеты и гипотенуза треугольника} Begin
Writeln (Stroka);
M:=150; N:=45;
Celoe:=M div N; Ost:=M mod N;
Writeln(Ot);
Writeln(Celoe);
Writeln(Ost);
Writeln(Stroka);
A:=1.5; B:=2.9;
C:=Sqrt(A*A+B*B); {Теорема Пифагора}
Writeln(Ot);
Writeln(C)
End.
Рисунок 11 –Текст программы
В этой программе мы использовали две строковые константы (Stroka и Ot), что позволяет не выписывать каждый раз текст, который надо напечатать.
С помощью операторов присваивания сначала переменным придаются начальные значения, потом вычисляются значения арифметических выражений.
Присмотримся еще раз к нашей программе. В ней несколько операторов присваивания. Сначала некоторым переменным присваиваются начальные значения. В следующем операторе присваивания вычисляется значение другой переменной, которое зависит от начальных значений. А что случится, если мы вдруг забудем переменным присвоить начальные значения? Кто обнаружит ошибку? Будет ли компьютер производить вычисления с переменными, которым программист ничего не присвоил?
К сожалению, будет. Конечно, работа с переменной без значения является серьезной ошибкой, но не все трансляторы в состоянии ее обнаружить. Дело в том, что в памяти компьютера не бывает «пустоты», в каждом мельчайшем ее элементе обязательно хранится ноль или единица, не бывает так, чтобы там «не было ничего». Поэтому в том месте памяти, которое было отведено для хранения значения некоторой переменной, обязательно находится какое-нибудь значение. Часто вновь описанная переменная именно его и приобретает. Компьютер не отличает случайно приобретенного значения от того, которое дает переменной пользователь, и выполняет вычисления обычным образом. Естественно, результаты вычислений с такими случайными данными совершенно не похожи на правду.
Некоторые из используемых сейчас трансляторов часто числовым переменным без значения по умолчанию присваивают 0, что, естественно, не всегда совпадает с начальным значением, нужным программисту. Даже если начальные значения ваших переменных равны нулю, не присваивать им этот ноль «вручную», надеяться на транслятор совершенно неправильно. Таким образом, не всегда надейтесь на помощь транслятора в поиске ошибок, тестируйте программу, проверяйте, правильные ли результаты она дает.
Ввод с клавиатуры и вывод на экран
Ввод и вывод служат для связи программы с внешним миром: таким образом она получает начальные данные и выдает ответ. Программа без вывода (под выводом понимается не только отображение результатов на экране) бессмысленна: зачем же что-то считать, если результаты работы никто не видит, и они пропадают. Вот и в нашей первой программе был оператор вывода.
Операторы ввода и вывода в Паскале правильнее было бы называть «процедуры», но мы пока не знаем точного значения этого термина в языках программирования, так что оставим такое, не совсем корректное название. Операторы ввода-вывода служат для обмена информацией между программой и какими-либо внешними устройствами. Можно ввести данные из файла, с клавиатуры, можно вывести в файл, на принтер, на экран. Пока нас будет интересовать только ввод с клавиатуры и вывод на экран. Позже мы узнаем, как с помощью этих операторов работать с файлами.
Операторы выглядят так.
Оператор ввода:
Read и Readln
(Read по-английски означает «читать»).
Оператор вывода:
Write и Writeln
(Write по-английски означает «писать»).
Дополнение «ln» в операторах происходит от слова line — линия, строка. Оператор с этим окончанием после своих действий переводит строку в отличие от своего «собрата». Подробнее: после работы Write (печати на экране) курсор остается справа от последнего напечатанного символа, а после WriteLn будет переведен на новую строку, в ее начало. После работы Read очередные данные будут считываться из той же строки, а после ReadLn будут считываться с новой, игнорируя незадействованные значения в первой строке.
Операторы могут использоваться без параметров (в Турбо Паскале пишется просто соответствующее слово и ничего больше, а во Free Паскале еще добавляются скобочки) и с параметрами. Параметры — список ввода (вывода) — записываются после оператора в круглых скобках. Друг от друга параметры в списке отделяются запятыми. Количество параметров, вообще говоря, может быть любым.
Например:
Read(X,Y,Z); Readln(Alfa); Write(X, Y, Z); Writeln (Alfa); Writeln
Оператор ввода
В списке ввода могут находиться только переменные. Встретив в программе оператор ввода, компьютер останавливается и ждет, когда с клавиатуры будут введены данные (цифры, символы). Ввод завершается нажатием Enter, работа программы продолжается. Введенные значения последовательно присваиваются переменным, перечисленным в скобках. Если переменная до этого имела какое-то значение, оно утрачивается, заменяется новым, введенным.
Тип вводимого значения должен совпадать с типом переменной, которой он присваивается: Integer, Real или Char, String.
Например, если переменная X описана как Real, при вводе Read(X)
можно набирать только числа, как вещественные, так и целые (они понимаются как вещественные с нулевой дробной частью). Если же ввести символ, при попытке присвоить его значение переменной X возникнет ошибка, программа прекратит работу. На экране появится окно редактора, а в нем — красная строка с сообщением об ошибке «неверный числовой формат».
Если переменная описана как Integer, вводить можно только целые числа. А вот в случае, когда переменная имеет тип Char, вводить можно и буквы, и цифры. Только надо иметь в виду, что все введенное будет понято как символ. Для типа String можно вводить несколько любых символов.
С помощью одного оператора Read можно ввести несколько значений: Read(A,C,N). При вводе числа должны отделяться друг от друга пробелами, символы записываются подряд. Вот здесь возникают некоторые неприятности. Во-первых, очередность вводимых значений легко перепутать. Во- вторых, можно ошибиться и ввести несколько лишних значений — какие из них будут приняты компьютером — первые или последние? Неприятности особого рода возникают при вводе одним оператором Read нескольких символьных величин (типа Char). Если при этом по ошибке ввести символы не подряд (в одну строку), а по одному (нажимая Enter после каждого символа) или разделяя их чем-либо (пробелом, запятой), то разделитель или Enter будет принят программой за очередной вводимый символ. Соответственно, она работать будет не так, как хотелось бы автору.
Чтобы подобных проблем не возникало, рекомендуем на первых порах каждым оператором ввода вводить только одно значение и пользоваться оператором Readln. Позже, по мере приобретения опыта программирования, мы будем отмечать случаи, когда удобно (или даже необходимо) ввести сразу несколько значений, а также более точно проясним разницу между Read и Readln.
Выше говорилось, что оператор ввода может использоваться без параметров: Readln. Зачем это нужно, если никакой информации в компьютер не поступает? Вспомним, что при выполнении этого оператора программа останавливается и ждет ввода. В данном случае, так как список ввода пуст, она ждет просто нажатия клавиши Enter. Оператор Readln без параметров может использоваться для организации задержки — программа не выполняется, картинка на экране не меняется, пока человек не нажмет на клавиатуре Enter. Часто такой оператор ставят в конце программы, например, для ее отладки. Тогда до тех пор, пока не нажата Enter, выполнение программы не заканчивается, переход в окно редактора не происходит, и можно, пока не надоест, любоваться результатами работы своей программы.
Оператор вывода
В списке вывода должны быть объекты только тех типов, которые можно выводить. Да, да, бывают типы данных, значения которых нельзя выводить на экран. Но мы с вами такие пока не изучали. То, о чем мы уже говорили, — числа, символы и строки — на экран выводить можно.
В качестве элемента списка вывода могут фигурировать:
• переменные — Writeln(Summa);
• константы (числовые, символьные, строковые) — Writeln(25); Writeln('X'); Writeln('Ответ');
• выражения, в частности арифметические — Writeln(sin(2*X)/ 35+1); Writeln(M div N mod 3).
Как уже говорилось, операторы Writeln и Write различаются тем, что первый, напечатав на экране все элементы своего списка вывода, осуществляет перевод строки (следующий оператор вывода будет печатать значения уже на новой строчке), а второй оставляет курсор в той позиции, где закончился вывод (следующий оператор вывода будет писать свои значения на той же строчке, рядом с напечатанными ранее). Два подряд оператора Write(X); Write(Y) можно заменить одним Write(X,Y) — работать они будут совершенно одинаково.
Оператор вывода может не иметь параметров. В этом случае пишутся только сами слова Writeln и Write (в Турбо Паскале скобки не ставятся, а во Free и ABC Паскале ставятся «пустые» скобки). Writeln без списка вывода переводит курсор на следующую строку (таким образом, выполнив 20 раз Writeln можно очистить экран). Write без списка вывода не делает ничего, «печатает пустоту». Зачем он нужен? Можно таким образом пометить, что потом в этом месте будет какой-то вывод.
Итак, количество параметров в списке вывода может быть от нуля до бесконечности. Ну, конечно же, не до бесконечности, текст программы не может быть бесконечным, но, строго говоря, их количество никакими правилами не ограничено.
Посмотрим, как работает оператор вывода, у которого в списке вывода несколько элементов:
Оператор
Напечатает
Writeln (1,2,3)
123
Writeln(100,200)
100200
Writeln(10, 'умножить', 'на', '5')
10умножитьна5
Почему в последнем примере получается так некрасиво и непонятно, почему элементы списка вывода «склеиваются» между собой? Да потому, что это мы сами так приказали компьютеру их напечатать. Если мы хотим, чтобы элементы вывода разделялись, например, пробелом, надо этот пробел явно указывать (выводить его как символ внутри кавычек). Например (для наглядности заменим здесь пробел знаком «нижнее подчеркивание»):
Writeln(1, '_', 2, '_', 3)
Writeln(10, '_умножить_на_', '5')
Форматный вывод
Для того чтобы сделать текст на экране понятным, а числа удобочитаемыми, хорошо расположенными, существует так называемый форматный вывод. В форматном выводе указывается количество позиций, которые при выводе надо отвести под выводимое число, символ или строку.
Для вывода символов, строк и целых чисел формат — это одно целое число. Оно указывается после выводимого элемента через двоеточие. Именно столько позиций будет отведено под выводимое значение. Выравнивание происходит по правому краю. То есть если остаются «лишние» позиции (число трехзначное, а под него отведено 7 позиций), то сначала выводится 4 пробела, а потом 3 цифры числа. Если по ошибке под выводимый элемент отводится меньше позиций, чем ему минимально необходимо, формат игнорируется.
Примеры Будет напечатано
A:=12345; S:='abcde';
Writeln(A:5;S:10);
Writeln(A:10,S:5);
Для вывода вещественных чисел используется формат из двух чисел, разделенных двоеточием. Например, X:10:2. Первое число — сколько позиций отводится для всего числа, второе число — количество цифр после точки. Обратите внимание, что никакого округления при отбрасывании «лишних» цифр не происходит, они просто «отрезаются». Понятно, что для правильного вывода (если формат неверный, он игнорируется) необходимо, чтобы первое число формата было больше второго, ведь кроме дробной части в числе есть целая часть, точка, возможно, знак числа.
Если разные вещественные числа выводить в нескольких строках в одинаковом формате, они будут выводиться, как это принято при написании их в столбик: точка под точкой, соответствующие разряды друг под другом (см. две последние строчки примера).
Примеры Будет напечатано
X:=123.456789; Y:=9.8;
Writeln(X:10:1).
Writeln(X:10:0);
Writeln(X:10:4);
Writeln(Y:10:4);
Для вывода вещественных чисел формат применяется особенно часто, уж очень «некрасиво» они выводятся по умолчанию. Если при выводе вещественного числа не указать формат, оно будет напечатано в виде с плавающей запятой. Например, Writeln(300/3) напечатает нам не 100 и не 100.0, а 1.00000000000E+02. Использование формата значительно увеличивает наглядность: Writeln(300/3:10:1) печатает 100.0.
Грамотное использование операторов ввода и вывода
Мы уже говорили, что будем пристальное внимание уделять «красоте» программы, ее понятности. Результат работы программы — то, что остается на экране после ее работы, — должен выглядеть так, чтобы было понятно, что программа делала. Хорошо выглядит программа, работа которой начинается с оператора вывода, поясняющего ее назначение. Например, «Решение квадратного уравнения». В таком случае и текст программы становится понятнее (ведь строку для вывода мы видим и в тексте при редактировании, и на рабочем экране при выводе).
Хорошая программа не только правильно производит вычисления, но и еще красиво их распечатывает. Плохо, если результатом программы является просто набор чисел (даже разделенных запятыми или пробелами), — вы вскоре забудете, что эти числа означают: скорость и расстояние, объем и площадь, синус и косинус? Выводимые значения следует пояснять: что каждое из них означает, для каких параметров подсчитано и т. п.
Особое внимание следует уделить «понятности» ввода. Если начать программу с оператора ввода (что часто, по сути, и бывает нужно), человек, сидящий за компьютером, может просто не понять, что от него требуется. Компьютер, увидев оператор Readln, остановится и будет ждать ввода нужного количества значений, а человек будет сидеть перед экраном и ждать, когда же на нем что-нибудь появится. Так и будут «смотреть» друг на друга… В конце концов, может быть, человек догадается, что он должен что-то ввести. Но что? Числа? Символы? В каком порядке? Поэтому хорошо, когда операторы ввода предваряются подсказкой: что требуется ввести. Вводить каждым оператором желательно одно значение. Отступление от этих правил может привести к ошибкам ввода (человек может перепутать, в каком порядке надо вводить значения, ввести вместо чисел символы и т. п.).
Пояснения к вводу, как и пояснения к ответу, должны быть понятными, совпадающими с условиями задачи, а не содержать имена придуманных вами переменных, которые используются внутри программы. Например, если в программе по двум сторонам треугольника и углу ищется третья сторона, а вы назвали стороны X, Y, Z, не следует писать подсказку «Введите X» или выводить результат «Ответ Z=». Работающему с программой (в том числе и ее автору — спустя несколько дней после написания) для правильного ввода придется смотреть в текст программы — что же там этими буквами обозначено. Буквы со знаком равенства в подсказке (Write('R=')) уместны, когда их назначение пояснено предыдущими операторами вывода. Например, если вы напечатали название задачи «Решение линейного уравнения KX+B=0», то после этого можно использовать подсказки «K=» и «B=».
Подсказку к вводу обычно выводят с помощью оператора Write, а не Writeln, в этом случае текст подсказки и введенное значение находятся рядом, на одной строчке.
В операторах вывода строк используйте пробелы в конце строки (ставится внутри апострофов), чтобы последующий объект не «приклеился» к выведенной строке.
Примеры программ с вводом-выводом
Задача. Найти сумму цифр трехзначного числа (число целое, положительное).
Кроме ввода-вывода для решения этой задачи нужен алгоритм, который не настолько очевиден, чтобы не сказать о нем хоть немного. Цифры числа можно искать с помощью операций целочисленного деления mod и div. Остаток от деления любого целого положительного десятичного числа на 10 дает его последнюю цифру (операция mod). Неполное частное при делении этого числа на 10 — первоначальное число без последней цифры.
Вторую цифру исходного числа можно искать, используя такое «усеченное» число, определяя его последнюю цифру. Чтобы узнать число сотен в числе (первую цифру), надо найти неполное частное от деления его на 100.
Можно действовать и другими способами. Например, сначала найти число сотен, а потом уменьшить число, отняв от него сотни, оставив две последние цифры.
Program Summa_Cifr;
Var K, C1, C2, C3 : Integer; {число и цифры слева направо} S : Integer; {сумма цифр}
Begin Writeln('сумма цифр трехзначного числа'); Write('Введите трехзначное число '); Readln(K); C3:=K mod 10;
C1:=K div 100;
C2:=(K div 10) mod 10; {Скобки здесь необязательны,
они для большей наглядности}
S:=C1+C2+C3;
Writeln(C1, '+', C2, '+', C3, '=', S);
End.
Рисунок 12 –Текст программы.
Отметим, что эта программа будет правильно работать, только если вводить именно трехзначное число. Позже мы напишем похожую программу, которая будет работать и с другими числами.
Давайте повнимательнее посмотрим, как организован список вывода у последнего оператора Writeln. В нем 7 элементов, все они отделяются друг от друга запятыми. Некоторые из них в апострофах, некоторые — без. Как понять, что писать в апострофах, а что без них? Если сразу разобраться сложно, советуем поступить вот так: выпишите, что получится при выводе для каких-нибудь заданных значений. Например, если ввести число 203, выведено должно быть 2 + 0 + 3 = 5. Если ввести другое число, будет выведена другая строка (при 162 получится 1 + 6 + 2 = 9). Что в ней изменится, а что останется таким же, как и в первой строке?
Подчеркнем те элементы, которые изменяются, волнистой чертой (это переменные), а те, которые постоянны, — прямой чертой (это константы). Ну, а теперь все совсем просто. Переменные в списке вывода записываются без апострофов — тогда на экран выведется не имя переменной, а ее значение, а вот символьные и строковые константы, содержащие текст для вывода, — в апострофах. Мы запишем это в табличке, чтобы было ясно видно, что как подчеркнуто:
2
+
+
3
=
5
1
+
6
+
2
=
9
Задача. Дана площадь круга. Определить радиус этого круга и длину окружности.
Обратите внимание, что в этой задаче все величины — вещественные. Для написания программы понадобится вспомнить формулы для вычисления площади круга и длины окружности, а также число π. В Турбо Паскале есть такая стандартная константа, она называется Pi.
Program Krug;
Var R, C, S : Real; {pадиус, длина окpужности
и площадь кpуга}
Begin Write ('Введите площадь кpуга '); Readln(S); R:=SQRT(S/Pi);
C:=2*Pi*R;
Writeln('Радиус кpуга площади', S:8:4, ' pавен ',
R:5:2);
Writeln('Длина окpужности pадиуса', R:5:2,' pавна',
C:6:2)
End.
Рисунок 13 –Текст программы.
Задача. По одной букве ввести слово из четырех букв. Составить новое «слово» из 3-й, 4-й и 1-й букв (именно в таком порядке), напечатать его. Например, если ввести слово «кора», напечатается «рак».
Program Slovo;
Var B1,B2,B3,B4 : Char; {буквы слова}
Begin Writeln('Введите слово из 4 букв по одной букве'); Write ('Введите 1-ю букву '); Readln(B1);
Write ('Введите 2-ю букву '); Readln(B2); Write ('Введите 3-ю букву '); Readln(B3); Write ('Введите 4-ю букву '); Readln(B4); Writeln('Hовое слово'); Writeln(B3:10,B4,B1)
End.
Ввод в этой программе можно оформить и короче.
Program Slovo1;
Var B1,B2,B3,B4 : Char; {буквы слова} Begin Write('Введите слово из 4 букв ');
Readln(B1,B2,B3,B4);
Writeln('Hовое слово'); Writeln(B3:10,B4,B1)
End.
Рисунок 14 –Текст программы.
Смотрится это гораздо эффектнее: и текст, и работа программы. Ведь человек вводит слово целиком, а компьютер как бы сам разбивает его на буквы. В первом случае вводятся именно 4 буквы (у нас в программе 4 оператора ввода, человек каждый раз знает, какую букву надо вводить). Во втором случае человек может ввести любое слово. Попробуйте! Если букв в слове будет больше четырех, компьютер отберет 4 первые и будет с ними работать, а вот если меньше четырех, он остановится, ничего не напишет, а просто будет ждать ввода недостающих букв.
Разветвления
Условный оператор
Записывая алгоритмы с помощью блок-схем, мы видели, что часто разветвление выглядит так: указываются действия, которые надо делать в случае выполнения условия, и действия, которые надо сделать, если условие не выполнено (рис. 15).
Рисунок 15- Блок-схема
В Паскале для реализации такой блок-схемы служит условный оператор, который в общем виде выглядит так:
If <условие> Then <Оператор1> Else <Оператор2>
Обратите внимание, что никаких знаков (в том числе «;» перед Else) в этой конструкции нет, «;» ставится между операторами, а здесь вся строчка — один оператор.
В операторе используются служебные слова If — «если», Then — «то». Else — «иначе». Если условие истинно, выполняется <Оператор1>, если нет — <Оператор2>.
Условие (или логическое выражение) — это некоторое выражение, которое может принимать значение «истина» или «ложь». Пока в качестве логических выражений будем использовать отношения: выражения, в которых две части (символы, константы или выражения), связаны одной из операций логического отношения (в математике это операции сравнения). Позже мы узнаем, что логические выражения могут быть достаточно длинными и сложными.
Значения обеих частей в отношении должны быть либо числового типа (Integer или Real), либо символьного (Char, String). Сравнивать символ с числом нельзя! В отношении может присутствовать только один знак сравнения:
X>=1, Y/2<3*X-1, A=B, H<>'#' — правильные отношения;
-1 и <Оператор2> — это любые операторы языка. Например, операторы присваивания или вывода или даже опять условный:
If X<>0 Then Y:=1/X Else Writeln('Нет решения'); If X>0 Then Writeln(X, '- положительное')
Else Writeln(X, '- отрицательное или 0');
If A>B Then If A>C Then Writeln (A, '- наибольшее')
Else Writeln (C, '- наибольшее') Else If B>C Then Writeln (B, '- наибольшее')
Else Writeln (C, '- наибольшее');
Как видите, Else в программах часто бывает удобно писать под Then.
Посмотрим, какие задачи решаются в предложенных выше примерах. В первом примере вычисляется число, обратное к X, причем учитывается, что сделать это можно только в том случае, когда X не равно 0. Во втором случае определяется, является ли X положительным числом. А в третьем примере находится наибольшее из трех чисел. Этому оператору соответствует следующая блок-схема (рис. 7.2)
Оба оператора (и после Then, и после Else) могут быть пустыми. Пустой оператор — это «пустота» и есть, он никак не записывается и не выполняет никаких действий. Но так как в Паскале между операторами ставится знак «;», то, если в тексте есть пустые операторы, иногда появляются дополнительные знаки «;». Например X:=1;;Y:=2 — здесь 3 оператора. Таким образом, запись:
If X>0 Then Else X:=-X
совершенно правильная, между Then и Else находится пустой оператор.
Следующая запись тоже совершенно правильная:
If X<0 Then X:=-X Else; Writeln(X)
А означает она вот что: если X отрицательное, у него изменится знак, в противном случае никаких действий сделано не будет. После условного оператора стоит оператор вывода, поэтому значение X выведется в любом случае, какое бы оно ни было.
Рисунок 16- Блок-схема
Сравните эту запись с очень похожим фрагментом (отсутствует всего один знак — какой?)
If X<0 Then X:=-X Else Writeln(X)
(2)
Здесь работа будет вестись по-другому: если X отрицательное, у него изменится знак, а если неотрицательное — оно напечатается. Отрицательное X печататься не будет — здесь, в отличие от первого фрагмента, оператор Writeln(X) находится внутри условного оператора, как действие после Else. В первом фрагменте после Else — пустой оператор, а оператор Writeln — самостоятельный оператор, который стоит после условного.
Посмотрите (рис. 7.3), как различаются блок-схемы для первого и второго рассмотренных фрагментов (слева и справа соответственно):
Рисунок 17-Блок схема
Впрочем, для тех случаев, когда «иначе» (Else) делать ничего не надо (при изучении блок-схем мы называли такие ветвления «обходом»), существует неполная форма условного оператора. Последняя часть Else <Опе- ратор2> опускается:
If X<0 Then X:=-X; Writeln(X)
Это аналог фрагмента 1 с неполной формой условного оператора. Работать он будет точно так же — напечатает |X|.
Составной оператор
Что произойдет, если вместо одного оператора ничего не написать, мы разобрались. А вот как быть, если в том месте, где «по закону» положен только один оператор, нужно написать несколько? Ведь по правилам языка в условном операторе и после Then, и после Else допускается писать только один оператор!!! Несложно придумать соответствующую задачу, и можно видеть на примерах блок-схем из первого раздела книги, что нередко и на одной, и на другой «веточке» «висит» несколько блоков. В этом случае надо несколько операторов «превратить» в один. Это делается с помощью так называемых «операторных скобок» Begin—End.
Получается конструкция:
Begin
Оператор1; Оператор2; и т.д.
End
Сколько бы внутри такой конструкции операторов ни было, для языка она превращается в один так называемый составной оператор. Превращать много операторов в один требуется не только для использования этой конструкции в условном операторе, так что составной оператор бывает нужен очень часто.
Записывать составные операторы удобно «лесенкой»: Begin и End писать друг под другом, а операторы, входящие в составной, — с небольшим отступом вправо. Так будет видно, где оператор закончился.
Паскаль-редактор позволяет удобно вводить составные операторы в тексте программы. Можно написать Begin и End, поставить курсор между ними, нажать Enter — End окажется на следующей строчке под Begin. После этого поставить курсор после Begin и вставлять операторы между операторными скобками. Кстати, такой способ ввода текста позволит сократить количество ошибок, связанных с несоответствием количества слов Begin и End.
В условном операторе после Then и Else могут стоять любые операторы, в том числе и условные.
If X<>0 Then If X>0 Then Writeln ('положительное')
Else Writeln ('отрицательное')
В этом фрагменте по два If и Then и всего один Else. В Паскале четко определено (чтобы не было никаких неоднозначностей), что в этом случае Else относится к идущей непосредственно перед ним конструкции If-Then, как это и изображено с помощью отступов во фрагменте. Напомним, кстати, что отступы при записи текста программы мы делаем для себя, а не для транслятора, неправильную конструкцию правильные отступы не спасут.
Этот фрагмент можно записать и по-другому. В подобных конструкциях внутренний условный оператор часто заключают в операторные скобки, несмотря на то что он всего один. Это делают, чтобы не перепутать внешний оператор с внутренним (особенно легко запутаться, если один из операторов укороченный).
If X<>0 Then Begin If X>0 Then Writeln ('положительное')
Else Writeln ('отрицательное')
End
Этим фрагментам соответствует одна и та же блок-схема (рис. 18):
Рисунок 18 –Блок-схема.
Если же мы хотим, чтобы блок-схема была другой (рис. 19), чтобы Else соответствовал первому Then, операторные скобки надо поставить в другом месте:
If X<>0 Then Begin If X>0 Then Writeln ('положительное') End
Else Writeln ('нулевое')
Рисунок 19 – Блок-схема.
Обратите внимание, и в том, и в другом случае существуют значения X, при которых не выводится никакого «ответа»: в первом случае это X = 0, во втором это X < 0.
Решение задач с условным оператором.
Решим задачу про треугольник (задача 2).
Посмотрев на блок-схему, видим, что фразу «Треугольник построить нельзя» придется выводить три раза. Заведем строковую константу с таким текстом.
Const net ='Треугольник построить нельзя';
Var a,b,c:real;
Begin writeln('Можно ли построить треугольник с такими сторонами?');
Writeln('Введите 3 числа');
Writeln('Первое число');
Readln(a);
Writeln('Второе число');
Readln(b);
Writeln('Третье число');
Readln(c);
If a1 и <1) значениях аргумента пользоваться разными форматами вывода (для этого придется написать целиком другой оператор вывода). Сделайте это самостоятельно.
Задача. Пусть зависимость Y от X задана графиком (рис. 22). Написать программу, в которой вводится с клавиатуры значение X, а выводится соответствующее ему значение Y.
Рисунок 22 – График зависимости X и Y .
В данном случае совершенно все равно, в каком порядке рассматривать части функции, но все же будем это делать слева направо.
Обратите внимание (рис. 23): во втором блоке-условии мы не проверяем принадлежность X всему промежутку [1, 3], нам важно проверить, что X<3. Условие X ≥ 1 на этой ветви уже выполнено. А для третьей части функции мы вообще не проверяем X, все лишние значения мы уже «отмели».
Рисунок 23- Блок-схема
Задача. Дано уравнение AX2 + BX + C = 0 (коэффициенты целые, вводятся с клавиатуры). Определить, имеет ли оно корни; если имеет, то сколько. Напечатать их.
Readln(B);
Write('C=');
Readln(C); D:=B*B-4*A*C;
If D<0 Then Writeln('Коpней нет')
Else
Begin
If D=0 Then
Begin
Writeln('1 коpень');
X1:=-B/(2*A);
Writeln('X=',X1:8:3)
End
Else
Begin
Writeln('2 коpня');
D:= Sqrt(D); X1:=(-B-D)/(2*A);
X2:=(-B+D)/(2*A);
Writeln ('X1=',X1:8:3,' X2=',X2:8:3);
End;
End;
End.
Рисунок 24 –Текст программы
После вычисления дискриминанта в программе написан один большой условный оператор, который и завершает решение задачи. Посмотрите: в случае D < 0 после оператора, печатающего, что корней нет, программа завершается, несмотря на то что в тексте ниже еще много строчек. Никаких завершающих действий здесь не нужно, потому что весь текст ниже рассматриваемой строки относится к другой ветви (D ≥ 0). А мы знаем, что в условном операторе выполняется только одна ветвь, после чего выполняется оператор, следующий за условным. У нас в программе больше операторов нет, поэтому она и заканчивается.
Задача. С клавиатуры вводится число X. Найти значение выражения: вычислителе квадратный корень из разности X2 –15, в знаменателе — сумма tgX + 2ctgX. Если при введенном X выражение не существует, сообщить об этом.
Запишем выражение и хорошенько его рассмотрим. Конечно, вычислить его значение можно не при всех значениях X. Какова область допустимых значений (ОДЗ) этой переменной? Конечно, подкоренное выражение должно быть неотрицательным и выражение в знаменателе не должно равняться нулю. Но, увы, написать в программе только эти условия — недостаточно. Ведь чтобы проверить, что выражение не равно нулю, компьютер должен подсчитать его значение для заданного X, но выражение tg X + 2 ctg X само существует не при всех значениях X, значит, мы можем заставлять компьютер подсчитывать его значение только в том случае, когда уверены, что это значение существует. То есть нам надо проверить, не равны ли 0 синус и косинус X (напомним tg(x) = sin(x)/cos(x); ctg(x) = cos(x)/sin(x)). Таким образом получается, что надо сделать не две, а целых четыре проверки. И вот здесь порядок проверок очень важен!
Обратите внимание, подобные действия мы делаем, когда, выполняя задания по алгебре, определяем ОДЗ функции. И там, выписывая условия, которым должны удовлетворять аргументы, мы об их порядке не задумываемся. Почему же здесь, в аналогичной задаче, мы говорим, что соблюдение порядка проверок имеет решающее значение? Дело в том, что, решая задачу по алгебре, мы в большинстве случаев лишь указываем, какие условия нужно проверить, и, возможно даже не проверяем их целиком, а лишь подставляем ответ (определяем, удовлетворяет он ОДЗ или нет). Здесь же мы не просто выписываем условия существования функции, а пишем команды, в процессе выполнения которых компьютер должен будет произвести необходимые вычисления, и мы должны позаботиться о том, чтобы эти вычисления можно было сделать.
С порядком проверок определились, можно писать программу. Но хорошо бы еще иметь в виду вот что: для того чтобы произвести проверки, нам (точнее, компьютеру) придется выполнять достаточно сложные вычисления (например, подсчитывать значения тригонометрических функций). При подсчете значения конечного выражения понадобятся результаты этих вычислений. Давайте не будем заставлять компьютер вычислять одно и то же несколько раз, запомним вычисленные значения. Получим следующую блок-схему (рис. 25).
В блок-схеме у нас несколько одинаковых блоков — печать сообщения о том, что выражение не имеет смысла. Объединять все эти блоки в один не стоит — в этом случае программа, соответствующая блок-схеме, получится «не структурная», в ней придется использовать оператор перехода. Чтобы в программе не писать несколько раз одно и то же, удобно ввести строковую константу (мы так уже делали).
И еще одно замечание перед тем, как мы приступим к написанию программы. Мы говорили, что вещественные числа не принято сравнивать на точное равенство, а у нас присутствуют сравнения с нулем для переменных Y и S, которые являются вещественными. В блок-схеме для наглядности удобна именно такая запись, в программе не будем сравнивать число на равенство с нулем, а напишем, что оно должно отличаться от нуля на некоторое небольшое значение (назовем его Eps), то есть по модулю должно превосходить это Eps.
Рисунок 25 –Блок-схема программы
Program Func;
Const Eps=1E-8;
Net:=’Выражения не существует’;
Var X,Y,Z,S:real;
Begin
Writeln(‘X=’);
Readln (X);
Y:=cos(X);
If Abs (Y)>Eps then
Begin
S:=sin(X);
If abs(S)>eps then
Begin Z:=sqr(X)-15;
If Z>=0 then
Begin Y:=S/Y+2*Y/S;
If abs (Y)>eps then
Writeln (sqrt(Z)/Y:10:4)
Else writeln (net);
End
Else writeln (net);
end
Else writeln (net);
End
Else writeln (net);
End.
Рисунок 26-Текст программы
Обратите внимание на структуру получившейся программы. На ее верхнем уровне всего 4 оператора: вся «лесенка» — это один большой условный оператор. В программе, как и в блок-схеме, 4 веточки с текстом «Else WriteLn(Net)», и убрать ни одну из них никак нельзя: если это сделать, то при каких-то значениях X программа не будет печатать никаких сообщений.
В отношении в условном операторе могут сравниваться не только числа, но и символы.
Задача а. С клавиатуры вводятся два числа и знак операции между ними: «+» или «–». Выполнить над числами соответствующее действие и напечатать результат.
Var A,B,C : Real;
Z : Char;
Begin Write('Введите первое число '); Readln(A); Write('Введите втоpое число '); Readln(B); Write ('Введите знак опеpации (+ или -) ');
Readln(Z);
If Z='+' Then C:=A+B
Else C:=A-B; Writeln(A:4:1,Z,B:4:1,'=',C:6:2)
End.
Рисунок 27-Текст программы
Посмотрите, как будет вести себя наша программа, если человек введет не «+», не «–», а какой-то другой символ? Неправильно! Как с этим бороться, мы узнаем чуть позже, а сейчас немного усложним задачу. Пусть операций будет теперь не две, а четыре.
Задача б*. С клавиатуры вводятся два числа и знак операции между ними: «+», «–», «*» или «/». Выполнить над числами соответствующее действие и напечатать результат.
Var A,B,C : Real;
Z : Char;
Begin Write('Введите первое число '); Readln(A); Write('Введите втоpое число '); Readln(B); Write ('Введите знак опеpации (+,-,* или /) '); Readln(Z);
If Z='+' Then C:=A+B
Else If Z='-' Then C:=A-B
Else If Z='*' Then C:=A*B
Else C:=A/B;
Writeln(A:4:1,Z,B:4:1,'=',C:6:2)
End.
Рисунок 28-Текст программы
Как хорошо, что у нас всего четыре арифметических действия! Как бы выросла наша программа, какую большую «лестницу» из Then–Else пришлось бы писать, если бы их было, скажем, 10! Оказывается, не пришлось бы. В Паскале такие ситуации предусмотрены.
Оператор выбора
Этот оператор создан как раз для реализации таких «широких» разветвлений, когда вычислительный процесс разделяется не на две, а на большее количество ветвей.
Запишем, как будет выглядеть оператор выбора в нашей программе, если поставить его вместо условного оператора.
Case Z of
'+' : C:=A+B;
'-' : C:=A-B;
'*' : C:=A*B;
'/' : C:=A/B
End;
Как видите, программа становится гораздо короче и нагляднее! Как же выглядит оператор выбора в общем виде?
Case и of — это служебные слова, они присутствуют в любом операторе выбора. Заканчивается оператор словом End (как видим, End может «закрывать» не только Begin, но еще и Case). Между Case и of должно быть выражение, от значения которого зависит, какую ветвь следует выбирать. В нашем случае выражение простейшего вида — переменная. Это выражение должно быть строго ординального типа! Вспомним, пока мы знаем два таких типа — Integer и Char.
Далее перечисляются «метки выбора» — все значения, которые может принять данное выражение, и для каждого значения через двоеточие записывается оператор, который надо выполнить в этом случае. Обратите внимание — один оператор! Как быть, если для решения задачи одного не хватает? Мы это уже знаем — любое количество операторов превращается в один, если их поместить в операторные скобки Begin–End. Пары «значение: оператор» (альтернативы) отделяются друг от друга точкой с запятой. Порядок, в котором перечисляются эти пары, значения не имеет.
Выше было сказано, что должны быть перечислены все возможные значения выражения, которое используется в операторе выбора. А что будет, если «забыть» какое-то значение? В разных версиях языка эта часть оператора «устроена» по-разному. В «стандартном» языке, описанном его создателем (Н. Виртом), определено, что, если в операторе выбора выражение приняло значение, для которого не написан оператор, — это ошибка, программа прекращает работу. В большинстве реализаций такого не происходит, просто не выполняется ни один из операторов, составляющих ветви оператора выбора. А в некоторых реализациях даже есть специальная ветвь Else. Она записывается в качестве последней ветви, после всех значений (но перед End). Интересно, что здесь перед Else ставится точка с запятой (в отличие от условного оператора).
Далее приведен фрагмент программы, которая по номеру дня в месяце (n-целое, от 1 до 31) печатает, на какой день недели он приходится (считаем, что 1-е число этого месяца пришлось на понедельник).
Case N mod 7 of
1: writeln(‘Понедельник’);
2: writeln(‘Понедельник’);
3: writeln(‘Понедельник’);
4: writeln(‘Понедельник’);
5: writeln(‘Понедельник’);
6: writeln(‘Понедельник’);
0: writeln(‘Понедельник’);
End;
Записанное в этом операторе арифметическое выражение N mod 7 может принимать одно из семи значений, мы их все описали.
Иногда бывает, что для нескольких разных значений выражения надо выполнить одни и те же действия, тогда можно действия дважды не выписывать, а соответствующие метки варианта записать через запятую.
С днями недели можно написать такой фрагмент:
Case N mod 7 of
1,2,3,4,5 : Writeln('Рабочий день');
6,0: Writeln('Выходной день');
End;
В некоторых реализациях допускается даже не перечислять все значения через запятую, а записать целый диапазон, если для всех значений из этого диапазона требуется выполнить одинаковые действия. Тогда следующий фрагмент будет тоже правильным (Ch — типа Char, любой символ):
Case Ch of
'A'..'Z', 'a'..'z': WriteLn('Латинская буква');
'0'..'9': WriteLn('Цифра');
'+', '-', '*', '/': WriteLn('Знак арифметической операции');
Else WriteLn('Специальный символ');
End;
Вспомним, мы уже говорили, что латинские буквы, большие и маленькие, пронумерованы подряд (имеют коды, идущие друг за другом). Запись 'A'..'Z' означает диапазон (отрезок) всех значений от 'A' до 'Z', включая концы. Цифры тоже идут подряд, а вот про арифметические знаки мы ничего такого не знаем, поэтому их пришлось перечислить.
А напоследок напомним, что в любой версии Паскаля, как бы широки возможности оператора Case в ней ни были, оператор выбора работает только с ординальными типами. Например, при решении квадратного уравнения у нас имеется три веточки-альтернативы (для D = 0, D < 0, D > 0), но оформить эту часть программы с помощью оператора выбора не удастся, так как D — вещественное. (Подумайте, если бы вдруг D стало целым, удалось бы тогда записать соответствующий оператор выбора?)
Задачи для самостоятельного решения.
Div и mod
1. Компьютер спрашивает человека, как его зовут, а потом печатает, обращаясь по имени: «Здравствуй, <Имя>!», «<Имя>, пишет программу»
2. Вводится четырехзначное число натуральное число. Найти произведение его цифр.
3. Вводится трехзначное натуральное число. Составить число из его цифр в обратном порядке (не напечатать цифры рядом, а именно напечатать получившееся число).
4. Вводится четырехзначное натуральное число. Выписать, сколько в нем тысяч, сотен, десятков и единиц.
5. Вводится слово из четырех букв. Составить «слово» из символов, каждый из которых является следующим по порядку для букв введенного слова.
6. С дерева собрали некоторое количество яблок. Их разделили поровну между детьми, гулявшими в саду (яблоки не резали), а оставшиеся отдали, чтобы сварить компот. Сколько яблок досталось каждому ребенку? Сколько пошло на компот?
7. Известно, сколько этажей в доме и сколько квартир на каждой площадке в подъезде (значения вводятся с клавиатуре). Определить, в каком подъезде и на коком этаже находится заданная квартира.
8. Определить является ли год, введенный с клавиатуры, високосным. Год считается високосным, если число этого года не кратно 100 и кратно 4 либо кратно 400.
Оператор выбора.
9. С клавиатуры вводится, сколько сейчас времени (в часах, от 0 до 23) и через сколько часов должен зазвонить будильник. В какое время будильник зазвонит? (Не забыть рассмотреть ситуацию, когда время вечернее, а будильник зазвонит утром следующего дня или когда будильник зазвонит через несколько дней — такой он у нас «долгоиграющий».)
10. Функция задана в виде дроби . Вводится значение x, на выходе-значение функции, если его можно вычислить, или сообщение о том, что x не входит в область определения.
11. Известно время начала и конца некоторого мероприятия (в часах и минутах, часы задаются в диапазоне от 0 до 23). Мероприятие длилось не более 12 часов, но могло начаться вечером, а закончиться на следующий день. Подсчитать, сколько времени длилось мероприятие (в часах и минутах).
12. Вспомним, что координатная плоскость делится на 4 четверти, и известно, какие знаки имеют X и Y в этих четвертях. Написать программу, в которой с клавиатуры вводятся координаты некоторой точки и печатается, в какой четверти она находится.
13. Вводятся 3 числа. Можно ли построить треугольник с такими длинами сторон? Если можно, то определить, является ли он равносторонним, равнобедренным, прямоугольным.
14. Известны длины сторон и углы выпуклого четырехугольника (надо ли вводить все углы?). Является ли он квадратом, ромбом, прямоугольником, параллелограммом? Причем, если четырехугольник является квадратом, не надо писать, что он к тому же ромб, прямоугольник и параллелограмм (то же для прямоугольника — не надо писать, что он параллелограмм).
15. Прямую можно задать уравнением Y = kX + b. С клавиатуры вводятся коэффициенты k и b двух прямых. Определить их взаимное расположение (совпадают, параллельны, пересекаются, а, может быть, и вовсе не существуют).
16. Решить уравнение kX + B = 0. (Учесть случай k = 0, в том числе одновременно с B = 0.) Коэффициенты вводятся с клавиатуры. Выписать получившееся уравнение (вместо коэффициентов k и B подставить введенные числа). Найти X.
17. Задано трехзначное положительное целое число. Есть ли среди его цифр 3? Если есть, на каком месте стоит?
18. Заданы 3 числа. Сколько из них одинаковых?
19. Заданы 4 числа. Сколько среди них одинаковых? (Не забыть рассмотреть случай, когда заданы 2 пары одинаковых чисел, например: 1, 1, 2, 2.)
20. Вводится слово из 4 букв. Есть ли в нем одинаковые буквы?
21. С клавиатуры вводится символ. Если это маленькая латинская буква, напечатать ее, если это большая латинская буква — напечатать соответствующую ей маленькую. В остальных случаях напечатать сообщение об ошибке.
22. Человеку задается некоторый вопрос, на который возможен ответ «да» или «нет». В качестве ответа он вводит одну букву. Понять и напечатать ответ человека, учитывая, что, имея в виду «да» («yes»), он может ввести большую или маленькую, русскую или латинскую букву «д» («y»), а вместо «нет», соответственно, те же «вариации» буквы «н» («n»). Человек может и ошибиться — об этом надо напечатать сообщение.
23. Вводится номер месяца. Напечатать его название.(case of)
24. Вводится номер месяца. Напечатать название следующего и предыдущего месяцев (аккуратнее с январем и декабрем!).
25. Вводится номер месяца. Напечатать, какое это время года. .(case of)
26. С клавиатуры вводится символ. Напечатать, является ли он цифрой, маленькой или большой латинской буквой. .(case of)
27. Составить программу, которая грамотно печатает фразу «У меня K друзей». K вводится с клавиатуры. Например, для K = 1 должно напечататься «У меня 1 друг», для K = 24 — «У меня 24 друга», для K = 100 —«У меня 100 друзей».
28. В зависимости от того, в каких единицах измерения вводится значение, перевести его в другие единицы измерения. В данном случае переводится объем информации (байты, килобайты, мегабайты и гигабайты).
ВАРИАНТЫ ЗАДАНИЙ Б21-021-1
ФИО
Задания
Аргандеева Дарья Владимировна
1,9,23
Бушмакин Семен Алексеевич
2,10,22
Горбушин Михаил Денисович
3,11,20
Дулесов Антон Сергеевич
4,12,19
Замараева Анастасия Дмитриевна
5,13,24
Кузьмина Софья Игоревна
6,14,25
Ложкина Диана Валерьевна
7,15,27
Лукьянова Екатерина Сергеевна
8,16,26
Мартюшев Артём Александрович
1,17,28
Панфилова Дарья Валерьевна
218,21
Парамонов Кирилл Олегович
3,11,19
Сакерина Алиса Владиславовна
4,,13,20
Сивков Роман Алексеевич
5,15,21
Соловьева Анна Алексеевна
6,17,22
Чибирев Сергей Алексеевич
7,12,23
Шляпин Тимофей Андреевич
1,10,24
Коротков Илья Сергеевич
2,19,25
Бабушкин Егор Львович
3,10,22
Новенький 2 (Извиняюсь, пока нет списков)
4,16,27
ВАРИАНТЫ ЗАДАНИЙ Б21-021-2
ФИО
Задания
Гарбузов Евгений Русланович
9,16,28
Горбушин Максим Александрович
8,17,27
Дюкин Михаил Алексеевич
7,18,26
Ефремов Дмитрий Александрович
6,19,25
Ефремова Вероника Владимировна
5,20,24,
Журавлев Александр Олегович
4,21,23
Зеленин Михаил Алексеевич
3,10,22
Калабаев Павел Николаевич
2,11,21
Князев Алексей Игоревич
1,12,20
Матвеев Георгий Игоревич
9,13,19
Мысева Софья Андреевна
8,14,18
Николаев Егор Леонидович
6,15,17
Нищенков Никита Александрович
7,16,25
Устюжанин Андрей Денисович
4,15,26
Шляпникова Дарья Александровна
5,14,27
Шмелёв Максим Сергеевич
3,13,28
ВАРИАНТЫ ЗАДАНИЙ Б21-791-1
ФИО
Задания
Ахсанов Булат Зиннурович
5,15,22
Баранов Егор Сергеевич
4,16,25
Борисов Никита Алексеевич
3,17,27
Бусаргин Анатолий Алексеевич
2,18,23
Васильева Валерия Александровна
1,19,21
Воронцов Сергей Евгеньевич
6,20,28
Кукаева Анастасия Сергеевна
7,21,26
Ложкин Данил Александрович
8,11,22
Попов Евгений Андреевич
9,12,23
Рустамхонов Абдумуминхон Абдусаломхон угли
1,13,24
Серегин Эдуард Владимирович
2,14,25
Снаговский Никита Александрович
3,10,26
Стяжкин Фёдор Алексеевич
4,16,27
Ушаков Иван Константинович
5,17,28
Фомин Максим Игоревич
6,12,19,
Шабалин Иван Викторович
7,18,26
Шестакова Екатерина Валерьевна
8,19,28