рефераты конспекты курсовые дипломные лекции шпоры

Реферат Курсовая Конспект

Часть I. Необходимые сведения о компьютере и программе

Часть I. Необходимые сведения о компьютере и программе - раздел Компьютеры, Глава 0.      ...

Глава 0.

                   
   
С,Н.Лукин
 
 
 
   
 
   
для школьников, студентов и начинающих
 
   


Оглавление

 

 

Предисловие............................................................................................................................................. 5

0.1. Кому нужна эта книга?.................................................................................................................................................................. 5

0.2. Почему Паскаль?............................................................................................................................................................................. 5

0.3. Какой из Паскалей?........................................................................................................................................................................ 6

0.4. Краткое содержание с рекомендациями................................................................................................................................... 6

Часть I. Необходимые сведения о компьютере и программе..................... 8

Глава 1. Первое представление о компьютере и программе............................................................. 9

1.1. Что умеет делать компьютер........................................................................................................................................................ 9

1.2. Что такое компьютер. Первое представление о программе............................................................................................... 9

1.3. Как человек общается с компьютером.................................................................................................................................... 11

Глава 2. Программа и программирование......................................................................................... 12

2.1. Список команд. Командный и программный режимы........................................................................................................ 12

2.2. Что важно знать о программе.................................................................................................................................................... 13

2.3. Понятие о процедуре. Может ли робот поумнеть?............................................................................................................. 13

2.4. Программа для компьютера на машинном языке................................................................................................................ 14

2.5. Языки программирования........................................................................................................................................................... 15

2.6. Пример настоящей программы для компьютера на языке Лого...................................................................................... 16

2.7. Последовательность работы программиста на компьютере........................................................................................... 17

2.8. Основные приемы программирования.................................................................................................................................... 18

Глава 3. Устройство и работа компьютера........................................................................................ 21

3.1. Как устроен и работает компьютер......................................................................................................................................... 21

3.2. Устройство и размеры оперативной памяти......................................................................................................................... 23

3.3. Взаимодействие программ в памяти........................................................................................................................................ 23

3.4. Внешние устройства компьютера............................................................................................................................................ 24

3.5. Кодирование информации в компьютере............................................................................................................................... 27

Часть II. Программирование на Паскале – первый уровень..................... 29

Глава 4. Простые (линейные) программы. Операторы ввода-вывода. Переменные величины 30

4.1. Процедура вывода Write............................................................................................................................................................. 30

4.2. Первая программа на Паскале.................................................................................................................................................. 31

4.3. Выполняем первую программу на компьютере................................................................................................................... 32

4.4. Процедура вывода WriteLn. Курсор........................................................................................................................................ 33

4.5. Переменные величины. Оператор присваивания................................................................................................................. 34

4.6. Описания переменных (VAR)..................................................................................................................................................... 35

4.7. Что делает оператор присваивания с памятью.................................................................................................................... 36

4.8. Имена переменных........................................................................................................................................................................ 37

4.9. Математика. Запись арифметических выражений.............................................................................................................. 38

4.10. Вещественные числа в Паскале.............................................................................................................................................. 39

4.11. Порядок составления простой программы.......................................................................................................................... 40

4.12. Операторы ввода данных ReadLn и Read......................................................................................................................... 42

4.13. Интерфейс пользователя........................................................................................................................................................... 43

4.14. Строковые переменные............................................................................................................................................................. 44

4.15. Диалог с компьютером.............................................................................................................................................................. 45

4.16. Константы..................................................................................................................................................................................... 45

Глава 5. Разветвляющиеся программы.............................................................................................. 46

5.1. Условный оператор IF или как компьютер делает выбор............................................................................................... 46

5.2. Правила записи оператора IF................................................................................................................................................... 48

5.3. Составной оператор..................................................................................................................................................................... 49

5.4. Ступенчатая запись программы............................................................................................................................................... 50

5.5. Вложенные операторы if. Сложное условие в операторе if. Логические операции.................................................. 50

5.6. Символьный тип данных Char.................................................................................................................................................. 53

5.7. Оператор варианта case.............................................................................................................................................................. 53

Глава 6. Циклические программы...................................................................................................... 56

6.1. Оператор перехода GOTO. Цикл. Метки................................................................................................................................ 56

6.2. Выход из цикла с помощью if.................................................................................................................................................... 58

6.3. Оператор цикла repeat................................................................................................................................................................. 59

6.4. Оператор цикла while................................................................................................................................................................... 60

6.5. Отличия операторов repeat и while........................................................................................................................................... 61

6.6. Оператор цикла for....................................................................................................................................................................... 61

Глава 7. Типичные маленькие программы....................................................................................... 64

7.1. Вычислительная циклическая программа............................................................................................................................. 64

7.2. Роль ошибок.................................................................................................................................................................................... 65

7.3. Счетчики.......................................................................................................................................................................................... 65

7.4. Сумматоры...................................................................................................................................................................................... 67

7.5. Вложение циклов в разветвления и наоборот....................................................................................................................... 68

7.6. Вложенные циклы......................................................................................................................................................................... 68

7.7. Поиск максимального из чисел................................................................................................................................................. 69

Глава 8. Процедуры.............................................................................................................................. 71

8.1. Компьютер звучит......................................................................................................................................................................... 71

8.2. Простейшие процедуры.............................................................................................................................................................. 72

8.3. Процедуры и операторы............................................................................................................................................................. 75

8.4. Стандартные процедуры Halt и Exit....................................................................................................................................... 75

Глава 9. Графика................................................................................................................................... 77

9.1. Стандартные модули................................................................................................................................................................... 77

9.2. Стандартный модуль Graph, текстовый и графический режимы.................................................................................... 77

9.3. Рисуем простейшие фигуры....................................................................................................................................................... 78

9.4. Работа с цветом. Заливка. Стиль линий и заливки.............................................................................................................. 81

9.5. Используем в рисовании переменные величины.................................................................................................................. 83

9.6. Использование случайных величин при рисовании........................................................................................................... 84

9.7. Движение картинок по экрану................................................................................................................................................... 85

Глава 10. Создаем первую большую программу.............................................................................. 87

10.1. Постановка задачи..................................................................................................................................................................... 87

10.2. Программирование по методу “сверху-вниз”..................................................................................................................... 87

10.3. Сначала – работа над структурой программы................................................................................................................. 89

10.4. Зачем переменные вместо чисел............................................................................................................................................ 91

10.5. Записываем программу целиком............................................................................................................................................ 92

10.6. Порядок описания переменных, процедур и других конструкций Паскаля.............................................................. 95

10.7. Управление компьютером с клавиатуры. Функции ReadKey и KeyPressed............................................................... 96

10.8. Буфер клавиатуры...................................................................................................................................................................... 97

10.9. Гетерархия. Задание на игру “Торпедная атака”.......................................................................................................... 100

Часть III. Программирование на Паскале – второй уровень................. 103

Глава 11. Алфавит и ключевые слова Паскаля.............................................................................. 104

11.1. Алфавит....................................................................................................................................................................................... 104

11.2. Ключевые слова........................................................................................................................................................................ 104

11.3. Использование пробела.......................................................................................................................................................... 105

Глава 12. Работа с разными типами данных Паскаля.................................................................. 106

12.1. Список типов.............................................................................................................................................................................. 106

12.2. Числовые типы.......................................................................................................................................................................... 107

12.3. Массивы...................................................................................................................................................................................... 108

12.4. Определения констант............................................................................................................................................................ 111

12.5. Типизированные константы.................................................................................................................................................. 112

12.6. Придумываем типы данных.................................................................................................................................................. 112

12.7. Логический тип Boolean......................................................................................................................................................... 113

12.8. Перечислимые типы................................................................................................................................................................. 113

12.9. Ограниченный тип (диапазон).............................................................................................................................................. 114

12.10. Действия над порядковыми типами.................................................................................................................................. 115

12.11. Символьный тип Char. Работа с символами................................................................................................................... 116

12.12. Строковый тип String. Работа со строками..................................................................................................................... 117

12.13. Записи........................................................................................................................................................................................ 118

12.14. Множества............................................................................................................................................................................... 120

12.15. Расположение информации в оперативной памяти. Адреса..................................................................................... 122

12.16. Ссылки....................................................................................................................................................................................... 123

Глава 13. Процедуры и функции с параметрами........................................................................... 125

13.1. Процедуры с параметрами.................................................................................................................................................... 125

13.2. Функции....................................................................................................................................................................................... 127

13.3. Подпрограммы. Локальные и глобальные переменные................................................................................................ 128

13.4. Массивы как параметры........................................................................................................................................................ 129

13.5. Параметры-значения и параметры-переменные............................................................................................................. 130

13.6. Индукция. Рекурсия. Стек....................................................................................................................................................... 131

13.7. Сортировка................................................................................................................................................................................. 133

Глава 14. Строгости Паскаля............................................................................................................ 135

14.1. Структура программы............................................................................................................................................................ 135

14.2. Структура процедур и функций........................................................................................................................................... 136

14.3. Выражения................................................................................................................................................................................. 137

14.4. Совместимость типов.............................................................................................................................................................. 137

14.5. Форматы вывода данных....................................................................................................................................................... 138

14.6. Переполнение ячеек памяти.................................................................................................................................................. 139

14.7. Дерево типов.............................................................................................................................................................................. 139

14.8. Синтаксисические диаграммы Паскаля............................................................................................................................. 140

Глава 15. Другие возможности Паскаля.......................................................................................... 147

15.1. Работа с файлами данных..................................................................................................................................................... 147

15.2. Вставка в программу фрагментов из других программных файлов.......................................................................... 149

15.3. Модули программиста............................................................................................................................................................ 150

15.4. Дополнительные процедуры и функции модуля Graph................................................................................................. 152

15.5. Копирование и движение областей экрана...................................................................................................................... 152

15.6. Вывод текста в графическом режиме.................................................................................................................................. 154

15.7. Управление цветом в текстовом режиме (модуль CRT)................................................................................................ 154

15.8. Работа с датами и временем (модуль DOS)....................................................................................................................... 155

15.9. Нерассмотренные возможности Паскаля.......................................................................................................................... 156

15.10. Миг между прошлым и будущим....................................................................................................................................... 157

Часть IV. Работа в Паскале на компьютере............................................. 159

Что нужно знать и уметь к моменту выполнения первой программы?............................................................................... 159

Порядок работы в Паскале.............................................................................................................................................................. 159

(1) Запуск Паскаля............................................................................................................................................................................. 159

(2) Начало работы. Ввод программы. Выход из Паскаля...................................................................................................... 161

(3) Сохранение программы на диске. Загрузка программы с диска.................................................................................... 162

(4) Выполнение программы............................................................................................................................................................. 163

(5) Исправление ошибок. Отладка программы.......................................................................................................................... 164

Работа с несколькими окнами......................................................................................................................................................... 168

Копирование и перемещение фрагментов текста...................................................................................................................... 169

Обзор популярных команд меню................................................................................................................................................... 169

Создание исполнимых файлов (exe)............................................................................................................................................. 170

Приложения. Справочный материал.......................................................... 171

П1. Как вводить программу в компьютер или работа с текстом в текстовом редакторе.............................................. 171

П2. Файловая система магнитного диска.................................................................................................................................... 174

П3. Список некоторых операций, процедур и функций Паскаля......................................................................................... 176

П4. Произношение английских слов............................................................................................................................................. 177

П5. Решения заданий......................................................................................................................................................................... 180

П6. Список литературы.................................................................................................................................................................... 207

П7. Предметный указатель.............................................................................................................................................................. 208

 

 

От автора

 

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

Также хочу поблагодарить Алексея Яковлевича Архангельского, просмотревшего рукопись и сделавшего существенные предложения по направленности ее содержания.

 

Предисловие

 

Сначала о терминологии. Везде в дальнейшем я буду:

· для краткости вместо термина «Турбо-Паскаль» употреблять термин «Паскаль».

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

· пользоваться термином «объект» в его общечеловеческом смысле, несмотря на то, что в языках программирования он имеет специальное значение.

0.1. Кому нужна эта книга?

Это самоучитель. То есть написана книга с расчетом на то, что, изучив ее без посторонней помощи, вы сможете без посторонней помощи писать программы на Паскале и выполнять их на компьютере тоже без посторонней помощи. Материал книги я в течение трех лет проверял на учениках-энтузиастах 6-11 классов 345 московской школы. Проверка, как мне кажется, закончилась нормально - вопросов в процессе изучения ребята задавали немного, а программировать научились. Ответы же на их вопросы я включил в книгу.

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

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

Если вы опытный программист, но хотите изучить еще и Паскаль, вам эта книга не нужна - изложение рассчитано на начинающих.

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

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

Книга учит не только писать программы на листе бумаги, но и выполнять программы на компьютере. Все, что вам нужно знать заранее, это как включать компьютер и как запускать Паскаль. Все остальное в книге объяснено.

0.2. Почему Паскаль?

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

Прежде всего, для полезного, занимательного и веселого изучения основных идей программирования существуют специальные учебные языки, рассчитанные на детей и новичков. Это «Кенгуренок», «Пылесосик», Лого. Кстати, Лого - язык достаточно богатый, чтобы программировать на нем и несложные игры. Но, к сожалению, эти языки мало распространены в России и по ним почти нет литературы. Так что вопрос о них отпадает. Перейдем к рассмотрению профессиональных взрослых языков. Сейчас наиболее известны Бэйсик, Паскаль, Си, Ява в их самых разных версиях.

Но Ява применяется в основном только в сети.

Си – высокопрофессиональный язык, в среде программистов он распространен очень широко, но слишком сложен для восприятия новичком и с него лучше не начинать. Если вам очень хочется программировать на Си, рекомендую начать с Бэйсика или Паскаля. После них освоение Си пойдет гораздо легче.

В качестве языков для обучения студентов и школьников наиболее широко используются Паскаль и Бэйсик. Причина в том, что их современные версии (Borland Pascal for Windows, Delphi, Visual Basic и др.) достаточно широко распространены во всем мире для разработки профессиональных программ, а сами языки, тем не менее, весьма просты и понятны.

При сравнении Паскаля и Бэйсика нужно помнить, что паскалей и бэйсиков на самом деле много (Pascal, TurboPascal, Borland Pascal, Borland Pascal for Windows, Basic, QBasic, Quick Basic, Visual Basic, Visual Basic .NET и пр.). Оба языка постоянно развиваются и каждой версии присущи свои преимущества и недостатки. Нельзя сказать, что вообще Бэйсик лучше Паскаля, или наоборот, иначе бы на свете остался только один из этих языков. Нельзя с уверенностью предсказать, что кто-то из них в будущем победит. Можно только сказать, что пока каждый силен в своей области и более поздняя версия языка всегда богаче и мощнее более ранней версии.

Исходя из этого, я сравню не Паскаль вообще и Бэйсик вообще, а их версии, наиболее распространенные в российских школах и институтах, а именно TurboPascal 7.0 и QBasic. Если сравнивать их, то на Бэйсике хорошо писать маленькие программы (до 25-50 строк). Они получаются короче и проще, чем на Паскале. Но большие программы на таком Бэйсике из-за плохой структурированности языка получаются труднообозримыми. К тому же Паскаль гораздо богаче, быстрее и мощнее (это естественно, так как он по размеру в десятки раз больше, чем Бэйсик). Паскаль строг и придирчив, изящен и красив.

0.3. Какой из Паскалей?

Любая программа, которую вы встретите в этой книге, является правильной программой в версиях Паскаля TurboPascal 5.5, TurboPascal 6.0, TurboPascal 7.0 и Borland Pascal для DOS, а абсолютное большинство программ - и в более ранних версиях. Это естественно, так как основа языка едина для всех версий. Таким образом, вы можете считать эту книгу учебником по программированию на любой из версий Паскаля. Лично я при написании этой книги использовал TurboPascal 7.0.

Теперь – о работе на компьютере. Каждая версия Паскаля предлагает свой способ работы на компьютере (каждая следующая версия - все более удобный и мощный). В широком смысле этот способ называется средой программирования. Как я уже говорил, среды программирования версий TurboPascal 6.0, TurboPascal 7.0 и Borland Pascal для DOS очень близки между собой в тех рамках, которыми я ограничиваюсь в книге. Я буду учить работать именно в этих средах. Все, что я буду говорить, относится к любой из них. Редкие случаи различий я буду полностью оговаривать. Если же на вашем компьютере установлена другая версия, не очень огорчайтесь, так как основные приемы работы в среде Паскаля одинаковы во всех версиях, а большинство остальных приемов - похожи. Различаются лишь подробности, которые нужны не часто.

Краткое содержание с рекомендациями

Книга состоит из четырех частей и приложения:

 

Часть I. Необходимые сведения о компьютере и программе.В этой части Паскалю мы не учимся. Она - для начинающих и для тех более опытных, кто имеет пробелы в знаниях основ компьютера и программирования. В этой части вы узнаете следующее:

 

· что такое компьютер, программа, цикл, ветвление, процедура, и какая от них выгода;

· что такое языки программирования;

· принцип действия компьютера и его устройств: оперативной памяти, принтера, винчестера и других;

· взаимодействие устройств во время работы компьютера;

· принципы кодирования информации в разных устройствах компьютера.

Часть II. Программирование на Паскале – первый уровень.Цель этой части – провести вас от создания самых простых программ до сложных. Здесь вы учитесь программировать на Паскале самым простым способом - на примерах, то есть по принципу “делай, как я”. Вы научитесь создавать небольшие программы, включающие циклы, ветвления, процедуры и использующие графику и звук. Заканчивается часть созданием и заданием на создание солидной программы. Предполагается, что после выполнения этого задания у вас должно возникнуть ощущение всесильности, то есть вы должны почувствовать, что теперь вам по плечу программа любого размера, и что вам может понадобиться в будущем, так это сведения о работе с теми или иными данными.

 

Часть III. Программирование на Паскале – второй уровень.Цели этой части:

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

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

 

Часть IV. Работа в Паскале на компьютере. Она описывает работу в среде программирования TurboPascal 7.0. Вы научитесь вводить программу в компьютер, запускать ее на выполнение, отлаживать с использованием отладчика, сохранять и загружать с диска. В полном объеме среда программирования рассмотрена не будет, но все ее средства, необходимые для уверенной работе на компьютере, будут изложены исчерпывающе.

 

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

 

Часть I. Необходимые сведения о компьютере и программе

· Что такое программа, цикл, ветвление, процедура, и какая от них выгода. · Принцип действия компьютера и его устройств: оперативной памяти, принтера,… · Взаимодействие устройств во время работы компьютера.

Глава 1. Первое представление о компьютере и программе

Что умеет делать компьютер

  Что же умеет делать компьютер:  

Что такое компьютер. Первое представление о программе.

  1.Выйти из квартиры 2.Подойти к двери лифта

Как человек общается с компьютером

Если же, наоборот, компьютер хочет сообщить человеку какую-то информацию, то он обычно показывает ее на экране монитора. Такой информацией могут…   Что же обычно делает человек, сидя за компьютером? Все зависит от того, что ему от компьютера нужно. А нужно ему в…

Глава 2. Программа и программирование

Список команд. Командный и программный режимы

  Список команд робота: ШАГ ВПЕРЕД

Последовательность работы человека с роботом

2.Подходите к роботу, стоящему в исходном положении, и отдаете ему команду СЛУШАЙ ПРОГРАММУ 3.Сообщаете ему программу 4.Отдаете роботу команду ВЫПОЛНЯЙ ПРОГРАММУ

Что важно знать о программе

Спрашивается, можно ли написать программу для гораздо более сложной задачи, например для перестановки всей мебели на этаже? Разумеется, можно,… Что требует от нас программа? Она требует абсолютной точности при ее… Запомните, что после того, как вы отдали роботу команду ВЫПОЛНЯЙ ПРОГРАММУ и робот начал ее выполнять, вы не можете…

Программадля компьютера на машинном языке

Взглянем на список команд новенького компьютера, только что покинувшего заводские стены. Внутри него нет почти никаких программ, поэтому умеет он…   Примеры задач, выполняемых командами машинного языка:

Языки программирования

Поскольку этот недостаток машинного языка был давным-давно понятен всем программистам, то они составили из команд машинного языка процедуры[2]для… · Нарисовать кружочек заданного размера в заданном месте экрана · Нарисовать прямоугольник заданного размера и формы в заданном месте экрана

Пример настоящей программы для компьютера на языке Лого

Давайте напишем настоящую программу на настоящем языке программирования. Для этого выберем язык Лого. Он предназначен в основном для рисования. Напишем программу для рисования домика, вот такого:

 

Начнем с того, что у нас в руках находится дискета с языком Лого. Вставим ее в компьютер. После нескольких нажатий на клавиши посредине экрана возникает вот такая маленькая черепашка:

С этого момента компьютер готов принимать нашу программу и выполнять ее. Занимательность и простота работы с Лого заключается в том, что многие его команды являются командами для черепашки нарисовать на экране те или иные разноцветные линии, что-нибудь покрасить и т.п. Передвигается черепашка по экрану маленькими шагами. Размер экрана по горизонтали и вертикали - несколько сотен шагов.

Из всего длинного списка команд Лого нам для рисования домика понадобятся только две. Приведем примеры их записи с пояснением:

 

ВПЕРЕД 28 По этой команде черепашка продвинется вперед на 28 шагов, оставляя за собой тонкий след, то есть фактически она нарисует отрезок прямой длиной в 28 шагов.
НАЛЕВО 60 По этой команде черепашка повернется на месте налево на 60 градусов.

 

А теперь напишем программу:

Программа Пояснения
ВПЕРЕД 40 Черепашка идет вверх и рисует правую стенку дома
НАЛЕВО 90 Собираемся рисовать не крышу, а потолок
ВПЕРЕД 50 Черепашка рисует потолок
НАЛЕВО 90 Собираемся рисовать левую стенку дома
ВПЕРЕД 40 Черепашка рисует левую стенку дома
НАЛЕВО 90 Собираемся рисовать пол
ВПЕРЕД 50 Черепашка рисует пол
НАЛЕВО 90 Готовимся добраться до крыши по правой стене
ВПЕРЕД 40 Черепашка забирается на крышу по правой стене
НАЛЕВО 45 Собираемся рисовать правый скат крыши
ВПЕРЕД 36 Черепашка рисует правый скат крыши
НАЛЕВО 90 Собираемся рисовать левый скат крыши
ВПЕРЕД 36 Черепашка рисует левый скат крыши

 

Как и программа для нашего воображаемого робота, любая программа для компьютера требует абсолютной точности записи. Нельзя допускать орфографических ошибок - НАЛЕВА, нельзя записывать команды по-другому - ВЛЕВО. Компьютер в этом случае просто откажется выполнять программу. Но если мы, соблюдая эти формальные правила, все же по невнимательности допустим ошибку в программе, компьютер программу выполнять не откажется и, выполнив ее, получит неправильный результат. Например, если в программе пятую сверху команду (для рисования левой стены) мы запишем так - ВПЕРЕД 60 (а не ВПЕРЕД 40), то домик будет выглядеть так:

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

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

Может ли черепашка поумнеть? Да. Объясните черепашке, что составленная программа есть процедура с именем ДОМИК – и отныне вам достаточно будет отдать команду ДОМИК – и черепашка его нарисует.

Последовательность работы программиста на компьютере

  0.Сначала программист получает задачу для компьютера, например, нарисовать… 1.Затем он думает, как из команд (операторов), которые ему предоставляет в распоряжение язык программирования,…

Основные приемы программирования

На все эти вопросы ответ один: если вы хорошо разбираетесь в поставленной задаче, то вы обязательно сможете разложить ее на много маленьких задач,… Возьмем воздушный бой. Здесь нужно задаться вопросом - а что такое движение?…  

Глава 3. Устройство и работа компьютера

 

Как устроен и работает компьютер

Компьютеры бывают разные. Вам почти наверняка придется работать на так называемом персональном компьютере. Именно про него я сказал в 1.1, что он…  

Порядок обмена информацией между устройствами компьютера

1.Ввести число с дискеты 2.Ввести число с клавиатуры 3.Перемножить эти числа

Устройство и размеры оперативной памяти

Оперативная памятькомпьютера устроена аналогично этому листу. Только размер ее гораздо меньше, чем у тетрадного листа, а клеточек гораздо больше, и… Оперативная память компьютера электронная. Информация хранится в ней в виде…

Взаимодействие программ в памяти

Важно помнить, что компьютер работает по программе не только тогда, когда выполняет нашу программу умножения из 3.1, но и до и после этого. Так уж… Внутри компьютера в специальном постоянном запоминающем устройственаходится… Важно понимать, что запуск на выполнение целой программы - Бэйсика явился результатом выполнения очередной команды…

Внешние устройства компьютера

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

Кодирование информации в компьютере

Прежде всего заметим, что информация в компьютере - это программы или данные, с которыми эти программы работают. Из чего состоит программа? Программа на языке программирования состоит из… Из чего состоят данные? Если это числовые или текстовые данные, то они тоже состоят из символов[5]. О графических…

Глава 4. Простые (линейные) программы. Операторы ввода-вывода. Переменные величины

Процедура вывода Write

Говорят, что процедура Write выводитна экран число 1999, или (по традиции), что процедура Write печатает число 1999, хотя, конечно, печатать на… А теперь поучимся на примерах:  

Write( -500) -500

Пояснения: Можно печатать не только числа, но и результаты вычисления арифметических выражений Write(3 * 2) 6 Знак * обозначает умножение

Первая программа на Паскале

Конечно, кроме оператора Write в Паскале есть еще много операторов. Но для начального понимания того, как устроена программа на Паскале, достаточно и его. Вот пример программы:

BEGIN
Write('Начали!');
Write(8+1);
Write(5-2)

END.

Вы видите, что программа состоит из трех операторов Write, записанных друг за другом. Кроме них, программы на Паскале содержат "знаки препинания" - в нашем случае это служебные словаBEGINи END, точка с запятой и точка. Слова BEGIN и END в нашей программе не являются, в отличие от Write, приказами на выполнение каких-либо действий по выполнению задания.

Пока примем такие правила расстановки "знаков препинания":

1. BEGIN будем ставить в начале программы, чтобы компьютеру было видно, откуда она начинается. (Это правило мы очень скоро уточним). BEGIN переводится НАЧАЛО, читается "би'гин".

2. END с точкойставится в конце программы, чтобы компьютеру было видно, где она кончается. END переводится КОНЕЦ, читается "энд".

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

Итак, программа на Паскале, как и на многих языках, состоит из последовательности операторов, выполняемых компьютером в порядке записи. Так, выполняя нашу программу, компьютер сначала выведет на экран слово Начали! , затем число 9, затем число 3. На этом работа программы завершится. На экране мы увидим Начали!93

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

BEGIN Write( 'Начали!') ;
Write( 8 +1 ) ;Write( 5

-2) END.

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

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

bEgin WriTe( 'Начали!') ; write( 8+1) ;WRITE( 5-2) enD.

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

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

BEGIN

Write('Начали!'); {Это приказ напечатать слово «Начали!»}
Write( 8+1) ;
Write( 5-2) {А здесь компьютер из 5 вычтет 2 и напечатает результат}
END. {Не забыть бы точку}

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

Выполняем первую программу на компьютере

Торопыжкам все равно придется изучать часть IV, но, возможно, попозже. Основательным же скажу, что пока при последовательном изучении части IV вам…   Итак, вот последовательность действий для опытных по выполнению первой программы на компьютере:

Процедура вывода WriteLn. Курсор

Все вышесказанное можно более точно описать с помощью понятия курсора. Если вы когда-нибудь вводили текст в компьютер с клавиатуры, то знаете, что… после нажатия на клавишу B на экране вы увидите B_ после нажатия на клавишу E на экране вы увидите BE_

Переменные величины. Оператор присваивания

Понятие переменной величинывам известно из школьной математики. Пусть несколько лет назад ваш рост равнялся 130 см. Обозначим этот факт так: r=130. Теперь он равен 140 см, то есть r=140. Получается, что величина r изменилась.Поэтому она называется переменной величиной. Числа 130 и 140 называются значениями переменной величиныr.

Любой язык программирования умеет обращаться с переменными величинами. Без них он был бы очень слаб и смог бы извлечь из компьютера только возможности карманного калькулятора. Точно так же алгебра без переменной величины превратилась бы в арифметику. Однако, преимущества применения переменных величин нам откроются позже, а пока наша задача - к ним привыкнуть.

Что же мы можем делать с переменными величинами, программируя на Паскале? Прежде всего, мы можем задавать компьютеру значение той или иной переменной величины. Это мы можем сделать при помощи нового оператора, который называется оператором присваивания. Так, если мы хотим сказать, что а имеет значение 6, то должны записать а := 6 . Как видите, вместо значка = употребляется значок :=. Он называется знаком присваивания, а сама запись а:=6 называется оператором присваивания. Говорят, что величине а присваивается значение 6. С момента выполнения оператора а:=6 компьютер будет помнить, что а равно шести.

Справа от значка := в операторе присваивания можно писать не только числа, но и переменные величины, и выражения. Выражение пока будем понимать так, как его понимает школьная математика. Например, после выполнения следующего фрагмента программы: . . . . a:=2*3+4; b:=a; y:=a+b+1. . . . компьютер будет знать, что a равно 10, b равно 10, y равно 21. Еще несколько примеров:

ФРАГМЕНТ ПРОГРАММЫ ЧТО ЗАПОМНИТ КОМПЬЮТЕР
v := -2+10; h := 10*v; s := v+h v=8 h=80 s=88
t := 0; n := 2*t+40; z := -n t=0 n=40 z= -40

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

ФРАГМЕНТ ПРОГРАММЫ ЧТО ВИДИМ НА ЭКРАНЕ
v := -2+10; h := 10*v; s := v+h; WriteLn (s)
v := -2+10; h := 10*v; s := v+h; WriteLn ( 's' ) s
v := -2+10; h := 10*v; WriteLn (v+h)
v := -2+10; WriteLn (v+10*v)
v := -2+10; h := 10*v; s := v+h; WriteLn (v, ' ' ,h, ' ' ,s) 8 80 88
v := -2+10; h := 10*v; s := v+h; WriteLn(v+1000, ' ' ,10*h, ' ' ,s) 1008 800 88

Нужно иметь в виду, что слева от знака := может стоять только переменная величина, но не число и не выражение. Можно писать с:=34, но нельзя писать 34:=с. Можно писать z:=f-v+990 , но нельзя писать f-v+990:=z. Правило это принято потому, что оператор присваивания сначала смотрит или вычисляет, какое значение имеет правая часть, а затем присваивает это значение переменной, стоящей в левой части. Нет смысла присваивать значение числу или выражению.

Обратите внимание на один важный момент. Когда школьник видит выражение (например, d+2d), он не обязательно его вычисляет. Он может его преобразовать или, скажем, упростить (получив 3d). Компьютер же, видя выражение, сначала его, может быть, и упростит, но затем обязательно вычислит. А для этого он должен знать численные значения входящих в него величин (в нашем случае это величина d). Таким образом, вычисляя правую часть оператора присваивания (например, y:=a+b+1), компьютер должен обязательно заранее знать, чему равны переменные, из которых эта правая часть состоит (в нашем случае это a и b). Ответственность за это знание лежит полностью на программисте. Пусть забывчивый программист записал такой фрагмент: . . . а:=10; y:=a+b+1 . . . , нигде в программе не придав b никакого значения. Естественно, при вычислении выражения a+b+1 компьютер не будет знать, чему равно b. В такой ситуации разные языки программирования поступают по-разному. Некоторые просто отказываются вычислять выражения, некоторые подставляют вместо b нуль, Паскаль же иногда может поступить довольно вредно: вместо b он подставит, что бог на душу положит, и получит сногсшибательный результат, например, игрек становится равным -8904 .

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

Оператор присваивания состоит из знака присваивания := , слева от которого пишется переменная, а справа - число, переменная или выражение. При выполнении оператора присваивания компьютер "в уме" (то есть ничего не показывая на мониторе) вычисляет правую часть и присваивает вычисленное значение переменной, стоящей в левой части.

Задание 4: Какое значение будет присвоено переменной t после выполнения фрагмента: k:=1+2; s:=2*k; t:=6-s ?

Описания переменных(VAR)

VAR a,b : Integer; BEGIN a:=100; b:=20; WriteLn (a + b) END. Очевидно, эта программа напечатает число 120. В программе новостью для нас… Зачем нужно описание? Для понимания этого сначала нужно вспомнить, для чего нужна компьютеру память и как она устроена…

Что делает оператор присваиванияс памятью

Рассмотрим пример программы:

VAR a,b,y : Integer;
BEGIN
a:= 10;
b:= 6;
y:= a+b+1;
WriteLn (y+200)
END.

В программе между BEGIN и END встречаются три переменные, поэтому все они перечислены в описании VAR a,b,y : Integer . Компьютер отведет для них в памяти три двухбайтовые ячейки.

В 4.5 я рассказывал о работе оператора присваивания, используя такие выражения, как "компьютер знает", "компьютер помнит". Но нам необходимо более строгое понимание работы этого оператора, понимание "ближе к железу":

Выполняя оператор присваивания (например, y:=a+b+1), компьютер сначала смотрит на его правую часть (a+b+1). Если в ней встречаются переменные (в нашем случае это a и b ), то компьютер перед вычислением ищет их значения в отведенных под них ячейках памяти (и находит там 10 и 6), подставляет эти значения в правую часть и вычисляет ее. Затем вычисленное значение (17) компьютер записывает в ячейку памяти, отведенную под переменную, поставленную в левой части (y).

Таким образом, когда мы говорим "Компьютер запомнил, что а равно 2", мы подразумеваем "Компьютер записал в ячейку памяти, предназначенную для а, число 2".

А теперь рассмотрим, как будут заполняться информацией ячейкиa,b,y в процессе выполнения нашей программы. В самом начале выполнения паскалевской программы в них находится неизвестно что. Первым выполняется оператор a:=10. Согласно только что приведенному определению оператора присваивания в ячейку a будет записано число 10. Затем выполняется оператор b:= 6 и в ячейке b появляется шестерка. Затем выполняется оператор y:= a+b+1. Компьютер смотрит, что находится в ячейках a и b, видит там 10 и 6, подставляет их в выражение a+b+1, получает 17 и записывает в ячейку y. Наконец выполняется оператор WriteLn (y+200). Компьютер заглядывает в ячейку y, видит там 17, вычисляет 17+200 и выводит 217 на экран.

Схематически этот процесс можно изобразить так:

ПОРЯДОК ИСПОЛНЕНИЯ ОПЕРАТОРОВ ЧТО НАХОДИТСЯ В ЯЧЕЙКАХ ПАМЯТИ ЧТО ВИДИМ НА ЭКРАНЕ
a b y
a:= 10 ? ?  
b:= 6 ?  
y:= a+b+1  
WriteLn (y+200)

Теперь мы можем также уточнить работу оператора WriteLn:

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

Задание 7: Поменяйте местами операторы b:= 6 и y:= a+b+1. Что произойдет?

 

Оператор присваивания меняет значение переменной величины

Пока я не рассматривал программы, в которых переменныеменяют свою величину. Теперь настало время такую программу рассмотреть:

VAR k : Integer;
BEGIN
k:=10; WriteLn (k); k:=25; WriteLn (k); k:=4; WriteLn (k)
END.

 

Запишем схематически процесс изменения информации в ячейке k:

ПОРЯДОК ИСПОЛНЕНИЯ ОПЕРАТОРОВ ЧТО НАХОДИТСЯ В ЯЧЕЙКЕ ПАМЯТИ k ЧТО ВИДИМ НА ЭКРАНЕ
k:=10  
WriteLn (k)
k:=25  
WriteLn (k)
k:=4  
WriteLn (k)

Как видите, в процессе работы программы содержимое ячейки k меняется. Так, при выполнении оператора k:=25 там вместо значения 10 появляется 25. А куда же девается десятка? Она стирается, то есть компьютер забывает ее безвозвратно. Здесь действует общий принцип работы всех компьютеров:

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

Раз теперь вместо 10 в ячейке k находится 25, то оператор WriteLn (k) печатает уже 25. Следующий оператор k:=4 запишет на место 25 четверку, а WriteLn (k) ее напечатает.

А что напечатает следующая программа?

VAR f : Integer;
BEGIN
f:=30;
f:=f+4;
WriteLn (f)
END.

Оператор f:=30 запишет в ячейку f число 30. А что сделает странный оператор f:=f+4? По определению оператора присваивания он сначала вычислит правую часть f+4 , подставив туда вместо f его значение, взятое из ячейки, и получит 34. Затем число 34 будет записано в ячейку, отведенную под переменную, обозначенную в левой части, то есть опять в ячейку f. При этом старое значение 30 будет стерто.

Таким образом, оператор f:=f+4 просто увеличивает число в ячейке f на четверку или, другими словами, увеличивает f на 4.

Задания 8-10:

Определите без компьютера, что будет напечатано при выполнении следующих фрагментов программ:

8) a:=100; a:=10*a+1; WriteLn (a)

9) a:=100; a:=-a; WriteLn (a)

10) a:=10; b:=25; a:=b-a; b:=a-b; WriteLn (a,' ',b)

Имена переменных

В том и другом случае будут напечатаны числа 3 и 51. Очевидно, компьютеру все равно, как мы обозначаем переменные величины, в смысл имен он не… Будем называть обозначение переменной именем или идентификатором этой… Правило:

Velichina

Zzz

Polnaja_summa

Tri_plus_dva

S25

K1

_k1

___

A1b88qq

Oshibka

Примеры неправильной записи имен:

ж - буква не латинского алфавита
polnaja summa - содержится символ (пробел), не являющийся буквой, цифрой или знаком подчеркивания
2as - начинается с цифры

Domby&Son - содержится символ & , не являющийся буквой, цифрой или знаком подчеркивания

Математика. Запись арифметических выражений

В правой части оператора присваивания и в операторе WriteLn мы записывали выражения, имеющие численное значение (например, a+b-8). Такие выражения… Четыре действия арифметики (и еще два) обозначаются в Паскале следующим… На уроках математики мы привыкли писать ab+cd , подразумевая: a умножить на b плюс c умножить на d. В Паскале это…

Вещественные числав Паскале

VAR a,b,y : Integer; BEGIN a:=10; b:=6; y:= a / b; WriteLn (y) END. Паскаль откажется выполнять эту программу, так как знает, что при делении… Что же делать? Конечно же, Паскаль предлагает простой выход. Программист имеет право любую переменную описать не как…

BEGIN

a:=10; b:=6;

y:=a / b;

WriteLn (y)

END.

По-английски Real читается " 'риэл", переводится "вещественный". Под переменную типа Real Паскаль отводит в памяти ячейку размером в 6 байтов.

Что мы увидим на экране в результате выполния оператора WriteLn (y)? Если вы думаете, что 1.666666 , то ошибаетесь. Переменные, описанные как Real, Паскаль выводит на экран в так называемом экспоненциальном формате(виде), с первого взгляда непонятном. Более подробно об этом и других форматах мы поговорим в 14.5, а пока, чтобы заставить Паскаль выводить вещественные числа в обычном, понятном виде, допишем кое-что в оператор вывода - WriteLn (y :8:3). Это значит, что мы хотим численное значение переменной y типа Real видеть на экране в привычном виде с 3 знаками после десятичной точки, а всё изображение числа не должно занимать больше 8 символов, включая целую часть, дробную часть, знак и десятичную точку. Этот оператор напечатает на экране 1.667. Здесь напечатано действительно 8 символов (три пробела, предшествующие единице, видны вам, как пустое место). Вместо 8 и 3 в операторе программист может писать любые имеющие смысл числа.

Поэкспериментируйте: (y :38:3), (y :20:10), (‘Результат равен’, y :8:3).

 

 

Три совета

1. Программы, которые вы видите в книге, вводите в компьютер и выполняйте их, даже если они кажутся вам почти понятными. В ряде случаев вы получите… 2. В каждой из этих программ экспериментируйте, то есть разными способами… 3. Выполняйте и сверяйте с ответом все задания. Это, конечно, главный совет из трех. Учтите, что сверенная с ответом…

Порядок составления простой программы

Известны размеры спичечной коробки: высота - 12.41 см., ширина - 8 см., толщина - 5 см. Вычислить площадь основания коробки и ее объем .   Порядок составления программы:

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

V := pl * visota; 6. После получения результата его нужно напечатать. Действительно, все… WriteLn (pl,' ', V :10:3)

BEGIN

shirina:=8; tol:=5; visota:=12.41;

pl := shirina * tol;

V := pl * visota;

WriteLn (pl,' ', V :10:3)

END.

Программа напечатает два числа: 40 и 496.400 .

Эту задачу можно было бы решить и гораздо более короткой программой:

BEGIN WriteLn (8 * 5, ' ' , 8 * 5 * 12.41 :10:3) END.

 

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

 

Задания 12-14:

Написать программы для решения следующих задач:

12) В углу прямоугольного двора размером 50х30 стоит прямоугольный дом размером 20х10. Подсчитать площадь дома, свободную площадь двора и длину забора. Примечание: в углу, где дом, забора нет.

13) Радиус окружности равен 800. Вычислить длину окружности и площадь круга. Результаты печатать с 5 знаками после десятичной точки.

14) Автомобиль 3 часа ехал со скоростью 80 км/час и 2 часа со скоростью 90 км/час. Вычислить среднюю скорость автомобиля (она равна суммарному пути, деленному на суммарное время).

Операторы ввода данныхReadLnи Read.

Задача: Сложить два числа - 20 и 16.

Сравним две программы решения этой задачи:

VAR a,b : Integer; BEGIN a:=20; b:=16; WriteLn (a+b) END. VAR a,b : Integer; BEGIN ReadLn (a,b); WriteLn (a+b) END.

Программы отличаются только одной строкой. Первая программа не требует пояснений - она печатает число 36. Во второй программе нигде не сказано, чему равны a и b, а вместо этого включен оператор ReadLn. Поговорим о нем.

ReadLn читается "рид'лайн", переводится "читай строку". Он приказывает компьютеру остановиться и ждать, когда человек введет с клавиатуры определенную информацию, после чего продолжить работу. В частности, ReadLn (a,b) будет ждать ввода двух целых чисел.

Таким образом, если первая программа после запуска будет работать без остановки до самого конца и без хлопот выдаст результат, то вторая программа на операторе ReadLn остановится и будет ждать. Во время этого ожидания человек должен на клавиатуре набрать число 20 (так как первым в списке оператора ReadLn стоит a), затем нажать клавишу пробела, затем набрать 16 и нажать клавишу Enter. Паскаль воспринимает нажатие пробела, как сигнал человека о том, что закончен набор на клавиатуре одного числа и сейчас начнется набор другого. После набора на клавиатуре последнего числа необходимо нажать клавишу Enter в знак того, что ввод чисел для данного оператора ReadLn закончен и компьютер может продолжать работу. В соответствии с этим компьютер сразу же после нажатия Enter прекращает ожидание и прежде всего направляет число 20 в память, в ячейку a, число же 16 - в ячейку b. На этом он считает выполнение оператора ReadLn законченным и переходит к следующему оператору - WriteLn. В результате будет напечатано число 36.

Таким образом, обе программы делают одно и то же. Зачем же тогда применять ReadLn вместо оператора присваивания? Ведь первая программа понятней, да и работает без остановки. Одна из причин в том, что программа с ReadLn гораздо универсальнее, "свободнее": если первая программа решает задачу сложения только двух конкретных чисел, то вторая программа складывает два любых числа. Вторая причина в том, что программа с ReadLn позволяет программисту во время написания программы не задумываться над конкретными значениями исходных данных, оставляя эту головную боль на момент выполнения программы. Но самая главная причина в том, что ReadLn позволяет человеку общаться с компьютером, вести с ним диалог во время выполнения программы.

 

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

Придумаем имена переменным величинам:

kol_krol - количество кроликов в зоопарке

kol_slon - количество слонов в зоопарке

norma_krol - сколько морковок в день положено кролику

norma_slon - сколько морковок в день положено слону

vsego - сколько всего требуется морковок

 

А теперь напишем программу:

VAR kol_krol,kol_slon,norma_krol,norma_slon,vsego :Integer;

BEGIN

norma_krol:=2;

norma_slon:=100;

ReadLn (kol_krol);

kol_slon:=3;

vsego := norma_krol * kol_krol + norma_slon * kol_slon;

WriteLn (vsego)

END.

Написав программу, программист вводит ее в компьютер, отлаживает и записывает на диск. На этом его миссия закончена. Утром служитель, пересчитав кроликов и найдя, что их 60 штук, подходит к компьютеру и запускает программу на выполнение.

Компьютер, выполнив автоматически первые два оператора (norma_krol:=2 и norma_slon:=100), останавливается на операторе ReadLn. Служитель вводит число 60, после чего компьютер посылает это число в ячейку kol_krol и переходит к выполнению следующего оператора ( kol_slon:=3 ). В конце концов на мониторе появится ответ: 420.

Вот схематическое изображение процесса выполнения программы:

ПОРЯДОК ИСПОЛНЕНИЯ ОПЕРАТОРОВ ЧТО НАХОДИТСЯ В ЯЧЕЙКАХ ПАМЯТИ
kol_krol kol_slon norma_krol norma_slon vsego
norma_krol:=2 ? ? ? ?
norma_slon:=100 ? ? ?
ReadLn (kol_krol) ? ?
kol_slon:=3 ?
vsego:=norma_krol
WriteLn (vsego)

На следующее утро, обнаружив, что 5 кроликов продано другому зоопарку, служитель запускает ту же самую программу, вводит число 55 и получает ответ - 410.

На этом несколько фантастичном примере я хотел показать, что применение ReadLn позволяет создавать программы, которые, оставаясь приятно неизменными, позволяют легко решать задачу в любое время для любых значений исходных данных. Можно было бы пойти по другому пути - вместо ReadLn использовать оператор присваивания, например kol_krol:=60. Но в этом случае программист каждое утро должен был бы бежать в зоопарк, чтобы исправлять в программе этот оператор присваивания.

Оператор ReadLn можно писать и без скобок, просто так: ReadLn . Выполняя оператор в такой записи, компьютер остановится и будет ждать, но не ввода какой-то информации, а просто нажатия на клавишу Enter. Таким образом, это просто оператор создания паузы в процессе выполнения программы. О том, зачем нужны паузы, поговорим чуть ниже.

Кроме оператора ReadLn для ввода данных применяется также оператор Read. Для начинающего программиста различия в их применении несущественны. Мы будем пока употреблять только ReadLn. Оператор Read без скобок паузу не создает.

Интерфейс пользователя

Это же касается и выдачи результатов. На пустом экране появляется сухое число 420. Посторонний человек ни за что не поймет, какой оно имеет смысл:… Дополним чуть-чуть нашу программу, чтобы интерфейс стал более удобным: VAR kol_krol,kol_slon,norma_krol,norma_slon,vsego : Integer;

BEGIN

norma_krol:=2;

norma_slon:=100;

WriteLn ( 'Введите, пожалуйста, количество кроликов' );

ReadLn ( kol_krol);

kol_slon:=3;

vsego := norma_krol * kol_krol + norma_slon * kol_slon;

WriteLn( 'Вам всего понадобится ' ,vsego, ' морковок' );

ReadLn

END.

Эта программа будет работать точно так же, как и предыдущая, с тем отличием, что во время паузы, вызванной оператором ReadLn ( kol_krol), на экране будет гореть удобная надпись -

Введите, пожалуйста, количество кроликов

а результат будет выведен на экран в виде -

Вам всего понадобится 420 морковок

Часто, впрочем, можно обойтись и без ReadLn. Нажав пару клавиш на клавиатуре (Alt-F5), мы можем снова зажечь погасший экран с результатами. В… Задания 15-16: Написать с использованием интерфейса программы решения задач:

Строковые переменные

В первой программе описание VAR a : Integer говорит о том, что переменная a обязана иметь числовое значение, а оператор a:=98 записывает в ячейку a… Во второй программе описание VAR a : String говорит о том, что переменная a… Обратите внимание, что в программе текст должен браться в кавычки, а в памяти он хранится без кавычек и на экран…

BEGIN

WriteLn ('Введите какое-нибудь слово');

ReadLn (a);

WriteLn ('Вы ввели слово ' ,a)

END.

Во время паузы, вызванной оператором ReadLn, вы должны ввести какой-нибудь набор символов, например Изнакурнож , и затем нажать клавишу Enter в знак того, что ввод закончен. В результате на экране будет напечатан текст:

Вы ввели слово Изнакурнож

Диалог с компьютером

КОМПЬЮТЕР ВЫВОДИТ НА ЭКРАН:Здравствуй, я компьютер, а тебя как зовут? ЧЕЛОВЕК ВВОДИТ С КЛАВИАТУРЫ: Коля КОМПЬЮТЕР ВЫВОДИТ НА ЭКРАН:Очень приятно, Коля. .Сколько тебе лет?

Константы

Кроме переменных величин в тексте программы мы встречаем константы. Это те значения, которые или присванваются переменным, или встречаются в выражениях, или сравниваются с выражениями. Например:

x:=25 здесь числовая константа - 25

slovo:=’Волга’ здесь строковая константа - Волга

simvol:=’!’ здесь символьная константа - !

y:=(x+1) / (200*x - 0.3) здесь числовые константы - 1 и 200 и 0.3

Глава 5. Разветвляющиеся программы

Условный операторIF или как компьютер делает выбор

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

Теперь посмотрим, как писать разветвляющиеся программы на Паскале.

Выучим сначала три английских слова:

if читается "иф" переводится "если"
then читается "зэн" переводится "то"
else читается "элз" переводится "иначе"

Теперь приведем пример нового для вас оператора:

IF a=28 THEN WriteLn (f) ELSE k:=44

Переводится он так:

ЕСЛИ a=28 ТО печатай f ИНАЧЕ присвой переменной k значение 44.

Другими словами, мы предлагаем компьютеру сначала подумать, правда ли, что a=28 , и если правда, то выполнить оператор WriteLn (f), в противном случае выполнить оператор k:=44 . Таким образом, мы с вами впервые написали оператор, при выполнении которого компьютер не просто выполняет, что приказано, а сначала думает и делает выбор (пока одного из двух).

Мы видим, что оператор if включает в себя другие операторы, которые выполняются или не выполняются в зависимости от какого-то условия. Чтобы понять, зачем может пригодиться оператор if, рассмотрим следующую задачу.

Задача 1. Компьютер должен перемножить два числа - 167 и 121. Если их произведение превышает 2000, то компьютер должен напечатать текст ПРОИЗВЕДЕНИЕ БОЛЬШОЕ, иначе текст ПРОИЗВЕДЕНИЕ МАЛЕНЬКОЕ. После этого компьютер в любом случае должен напечатать само произведение.

Программа:

VAR a,b,y :Integer;

BEGIN
a:=167;

b:=121;

y:=a*b;

if y>20000 then WriteLn ('ПРОИЗВЕДЕНИЕ БОЛЬШОЕ')

else WriteLn ('ПРОИЗВЕДЕНИЕ МАЛЕНЬКОЕ');

WriteLn (y)

END.

Пояснение: В программе 5 операторов, последний – WriteLn (y). Поскольку эти 5 операторов выполняются по порядку, то он выполнится обязательно.

 

Задача 2. В компьютер вводятся два произвольных положительных числа - длины сторон двух кубиков. Компьютер должен подсчитать объем одного кубика - большего по размеру .

Обозначим a1 - сторону одного кубика, a2 - сторону другого, bol - сторону большего кубика, V - объем кубика. Приведем три варианта программы:

 

ВАРИАНТ 1   VAR a1,a2 : Real; BEGIN ReadLn (a1,a2); ifa1>a2 then WriteLn (a1*a1*a1 : 15:5) else WriteLn (a2*a2*a2 : 15:5) END.
ВАРИАНТ 2   VAR a1,a2,V : Real; BEGIN ReadLn (a1,a2); if a1>a2 thenV:=a1*a1*a1 else V:=a2*a2*a2; WriteLn (V : 15:5) END.
ВАРИАНТ 3   VAR a1,a2,bol,V : Real; BEGIN ReadLn (a1,a2); if a1>a2 then bol:=a1 else bol:=a2; V:=bol*bol*bol; WriteLn (V : 15:5) END.

 

Поясним последний вариант. Программа состоит из четырех операторов, которые выполняются в порядке записи. Первым после запуска выполняется оператор ReadLn (a1,a2), который ждет от нас ввода двух чисел. Пусть мы сегодня ввели числа 3 и 2. Компьютер понимает, что a1 равно 3, a2 равно 2, и переходит к выполнению оператора if. Он видит, что 3>2, и поэтому выполняет оператор bol:=a1, а оператор bol:=a2 не выполняет. В результате в ячейке bol оказывается число 3. Затем компьютер переходит к следующему оператору - V:=bol*bol*bol и вычисляет V=3*3*3=27. Следующий оператор WriteLn (V : 15:5) печатает число 27.00000 .

Если завтра мы запустим эту же программу и введем числа 6 и 10, то компьютер увидит, что утверждение 6>10 ложно, и поэтому выполнит оператор bol:=a2, а оператор bol:=a1 выполнять не станет. В результате в ячейке bol окажется число 10 и будет напечатано число 1000.00000 .

 

А теперь, дорогой читатель, вам пришла пора освоить пошаговый режим выполнения программы на компьютере. В обычном режиме компьютер выполняет программу настолько быстро, что вы не успеваете заметить, в каком порядке он выполняет отдельные операторы программы, а без этого часто невозможно понять ее логику. Пошаговый режим заставляет компьютер при выполнении программы задерживаться на каждой строке программы столько, сколько нужно человеку. Сейчас вам необходимо проделать то, что сказано в части IV в пункте «Пошаговый режим» параграфа «Исправление ошибок. Отладка программы».

 

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

Оператор if можно записывать и без части else. Например, if s<t then w:=a+1. Это означает, что если s<t, то нужно выполнить оператор w:=a+1, в противном случае ничего не делать, а просто перейти к следующему оператору.

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

Вот как будет выглядеть наша программа-"цензор":

VAR Slovo : String;
BEGIN
ReadLn (Slovo); { переменная Slovo будет иметь значением строку символов, введенных с клавиатуры }
if Slovo = 'колхозник' then Slovo := 'фермер';
WriteLn (Slovo)
END.

Правила записи оператора IF

 

 

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

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

IFусловие THEN оператор ELSE оператор

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

оператор любой оператор Паскаля
условие пока под условием будем понимать два арифметических выражения, соединенных знаком сравнения, или условие равенства или неравенства строк, как это показано на примере в 5.1
выражение что такое выражение, было пояснено в 4.9
знак сравнения знаков сравнения шесть: > больше >= больше или равно = равно < меньше <= меньше или равно <> не равно

 

Пример: if5*a+4 <= a*b then WriteLn (b) else a:=b+5 Здесь

 

WriteLn (b) - один оператор,

a:=b+5 - другой оператор,

5*a+4 <= a*b - условие,

5*a+4 - одно выражение,

a*b - другое выражение,

<= - знак сравнения.

 

Вспомним правило расстановки точек с запятыми. Они применяются для того, чтобы отделять друг от друга операторы, выполняющиеся друг за другом. Поэтому и после оператора if мы тоже ставили точку с запятой, если после него шел какой-нибудь оператор. Распространенная привычка начинающих программистов - автоматически ставить точку с запятой после любого оператора, независимо от того, что после него стоит - другой оператор или же служебное слово, например else или end. Так вот, перед end точку с запятой ставить не возбраняется, а

перед ELSE точку с запятой ставить запрещено.

В п.5.1 вы уже видели, что оператор if можно записывать в краткой форме:

IFусловиеTHENоператор

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

IF условие THEN оператор [ ELSE оператор ]

Квадратные скобки здесь означают, что их содержимое можно писать, а можно и не писать в операторе.

Полезное замечание: Вычисляя выражения, стоящие в условии оператора if, Паскаль не записывает их значения в память. Например, после выполнения фрагмента - b:=6; if b+1>0 then s:=20 - в ячейке b будет храниться 6, а не 7. То же относится и к выражениям из оператора WriteLn. Например: b:=6; WriteLn (b+1) . И здесь тоже в ячейке b останется храниться 6, а не 7. И вообще, информация в ячейках памяти не меняется при вычислении выражений.

Примеры работы оператора if:

ФРАГМЕНТ ПРОГРАММЫ ЧТО НА ЭКРАНЕ
a:=10; if a>2 then WriteLn ('!!!') else WriteLn ('!') !!!
a:=4; if a>5 then a:=a+10 else a:=a-1; WriteLn (a)
s:=6; if s-8<0 then s:=s+10; WriteLn (s)
s:=6; if s<0 then s:=s+10; s:=s+1; WriteLn (s)

Пояснение: Обратите внимание, что в последнем примере оператор if кончается оператором s:=s+10, а не s:=s+1. Поэтому оператор s:=s+1 будет выполняться всегда, независимо от величины s.

Задания 18-20:

Определить без компьютера, что будет напечатано при выполнении следующих фрагментов программ:

18. k:=20; k:=k+10; if k+10<>30 then k:=8 elsek:=k-1; WriteLn (k)

19. k:=20; k:=k+10; if k+10 = 30 thenk:=8 else k:=k-1; WriteLn (k)

20. p:=1; if p>0 then p:=p+5; Write (p); if p>10 then p:=p+1; Write (p)

Задания 21-23:

21. В компьютер вводятся два числа. Если первое больше второго, то вычислить их сумму, иначе - произведение. После этого компьютер должен напечатать текст ЗАДАЧА РЕШЕНА.

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

Указание: Для этого его длина должна быть меньше суммы длин двух других отрезков. Замечание: Пока не думайте о том, что слишком длинными могут быть второй или третий отрезки. Об этом – задание из 5.5.

23. Дракон каждый год отращивает по три головы, но после того, как ему исполнится 100 лет - только по две. Сколько голов и глаз у дракона, которому N лет?

Составной оператор

Вот фрагмент программы, которая складывает два числа:

WriteLn ('Введите два числа');
ReadLn (a,b);
WriteLn ('Сумма равна ' ,a+b)

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

WriteLn ('Введите число');
ReadLn (a);
WriteLn ('Квадрат числа равен ' ,a*a)

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

Начинаться наша программа могла бы примерно так:

VAR Otvet : String; . . . . .

BEGIN

WriteLn ('Чем займемся – сложением или возведением в квадрат?');

ReadLn (Otvet);

if Otvet = 'сложением' then . . . . else . . . .

Здесь после then мы должны бы вставить первый фрагмент, а после else второй. Однако, тут возникает проблема. Каждый из фрагментов состоит из нескольких операторов, а синтаксис оператора if разрешает ставить после then и else только по одному оператору. Чтобы преодолеть эту трудность, в Паскале есть средство превратить последовательность записанных друг за другом операторов формально в один оператор. Для этого последовательность заключается между словами begin и end и получившаяся конструкция называется составным оператором.

Вот первый фрагмент в виде составного оператора:

begin
WriteLn ('Введите два числа');
ReadLn (a,b);
WriteLn ('Сумма равна ' ,a+b)
end

Компьютер выполняет составной оператор неотличимо от последова­тельности опера­торов, из которых он состоит, однако титул составного оператора позволяет ему считаться одним оператором и поэтому быть вхожим в те места программы, в которые разрешен вход только единичным операторам, а не их после­до­вательностям, как, например, имеет место в нашем случае с оператором if.

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

VAR Otvet :String;

a,b :Integer;

BEGIN

WriteLn ('Чем займемся - сложением или возведением в квадрат?');

ReadLn (Otvet);

if Otvet = 'сложением'

Then

begin WriteLn ('Введите два числа');

ReadLn (a,b);

WriteLn ('Сумма равна ' ,a+b)

End

Else

begin WriteLn ('Введите число');

ReadLn (a);

WriteLn ('Квадрат числа равен ' ,a*a)

end;

WriteLn ('Счет завершен')

END.

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

Задание 24: Видоизменить диалог с компьютером, начатый в 4.15. Пусть компьютер, узнав возраст человека, дальнейшую беседу ведет по двум вариантам. Если возраст больше 17, то компьютер должен задать вопрос: "В каком институте ты учишься?" и получив ответ, глубокомысленно заметить "Хороший институт". Если же возраст меньше или равен 17, то соответственно - "В какой школе ты учишься?" и "Неплохая школа". После этого, каков бы ни был вариант, компьютер должен попрощаться: "До следующей встречи!".

Ступенчатая запись программы

Сделано все это для удобства чтения программы, для того, чтобы глаз мог сразу же уловить структуру программы, а именно, из каких частей состоит как… Конечно, допустимы и некоторые отклонения от ступенчатого стиля. Например,… a:=0; b:=0; c:=0; f:=4;

Вложенные операторы if. Сложное условие в операторе if. Логические операции

Согласно синтаксической схеме оператора if, после then и else может стоять любой оператор Паскаля, в том числе и if.

Решим задачу: В компьютер вводится число (пусть для конкретности это будет дальность какого-нибудь выстрела). Если оно находится в интервале от 28 до 30, то напечатать текст ПОПАЛ, иначе - НЕ ПОПАЛ.

Сначала составим алгоритм: Введи число. Если оно больше 28, то надо еще подумать, в противном случае печатай НЕ ПОПАЛ. А о чем же думать? А вот о чем: Если число меньше 30, то печатай ПОПАЛ, иначе печатай НЕ ПОПАЛ.

А теперь по составленному алгоритму напишем программу:

VAR a : Real;
BEGIN
ReadLn (a);
if a>28 then if a<30 then WriteLn ('ПОПАЛ')
else WriteLn ('НЕ ПОПАЛ')
else WriteLn ('НЕ ПОПАЛ')
END.

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

d:=3; v:=10; if v<6 then if v<20 then d:=1 else d:=2

Чему будет равняться d после выполнения этого фрагмента - 1, 2 или 3? Ответ зависит от того, какому if принадлежит else - if v<6 или if v<20 ? Чтобы ответить на этот вопрос, пойдем по тексту программы от интересующего нас else к началу и если по пути нам не встретится еще один else. то первый же if, на который мы наткнемся - наш. Если по пути нам встретится еще один else, забудем пока про наш else и найдем сначала if для нового else, а со старым разберемся потом.

Испытайте-ка этот способ в нашем фрагменте и в предыдущей программе. Получается, что else в нашем примере принадлежит if v<20 и значит, d будет равняться 3.

Задание 25: Усложним задание из 5.2: В компьютер вводятся длины трех отрезков. Компьютер должен ответить на вопрос, правда ли, что эти отрезки могут образовать треугольник.

Указание: Для этого каждый отрезок должен быть меньше суммы длин двух других отрезков.

 

_____________ _ _____________

 

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

В Паскале, тем не менее, есть возможность записывать многие программы со вложенными друг в друга if короче и понятнее, используя только один if. Для этого используются логические операции.

 

Задача "Разборчивая принцесса". В прихожей у принцессы - длинная очередь женихов. Принцессе нравятся только голубоглазые маленького роста. Устав принимать женихов и отбирать из них подходящих, принцесса вместо себя поставила компьютер, написав для него программу, которая говорит ВЫ МНЕ ПОДОЙДЕТЕ тем, у кого цвет глаз голубой и рост меньше 140 см. Остальным программа говорит ДО СВИДАНИЯ.

Вот эта программа:

VAR Tsvet :String; {Цвет}

Rost :Integer; {Рост}

BEGIN

WriteLn ('Каков цвет ваших глаз?');

ReadLn (Tsvet);

WriteLn ('Введите ваш рост в сантиметрах');

ReadLn (Rost);

if (Tsvet ='Голубой') AND (Rost<140) {Если цвет голубой И рост<140}

then WriteLn ('ВЫ МНЕ ПОДОЙДЕТЕ')

else WriteLn ('ДО СВИДАНИЯ')

END.

Мы видим, что условие в операторе if уже не такое простое, как мы описывали раньше, а сложное, то есть состоящее из двух взятых в скобки условий[6], соединенных знаком логической операции AND (читается "энд", переводится "и"). Весь оператор if можно прочесть так - если цвет глаз голубой И рост меньше 140 сантиметров, то печатай ВЫ МНЕ ПОДОЙДЕТЕ, иначе печатай ДО СВИДАНИЯ.

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

Поэтому наш оператор if ответит ДО СВИДАНИЯ и высоким голубоглазым и высоким неголубоглазым и маленьким неголубоглазым. И лишь маленьким голубоглазым он ответит ВЫ МНЕ ПОДОЙДЕТЕ.

 

Программа для задачи ПОПАЛ - НЕ ПОПАЛ при использовании логических операций значительно упростится:

VAR a :Real;
BEGIN
ReadLn (a);
if (a>28) AND (a<30) then WriteLn ('ПОПАЛ')
else WriteLn ('НЕ ПОПАЛ')
END.

Задача "Неразборчивая принцесса". Неразборчивой принцессе нравятся все маленькие независимо от цвета глаз и все голубоглазые независимо от роста. Программа неразборчивой принцессы будет отличаться от программы разборчивой одним единственным знаком логической операции:

if (Tsvet ='Голубой') OR(Rost<140) {Если цвет голубой ИЛИрост<140}

Знак логической операции OR читается "о", переводится "или".

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

Поэтому теперь оператор if ответит ВЫ МНЕ ПОДОЙДЕТЕ и высоким голубоглазым и маленьким голубоглазым и маленьким неголубоглазым. И лишь высоким неголубоглазым он ответит ДО СВИДАНИЯ.

Знаками AND и OR можно объединять сколько угодно условий. Например:

if (a>2) OR (x=b) OR (c<>1) then k:=99 else k:=33

Здесь выполнится оператор k:=99, если верно хотя бы одно из трех условий, и лишь когда все три неверны, будет выполняться оператор k:=33.

Кроме логических операций AND и OR применяется еще логическая операция NOT(читается "нот", переводится "не"). Запись if NOT(a>b) then... переводится так - ЕСЛИ НЕПРАВДА, ЧТО a больше b, ТО.... Вот фрагмент:

a:=2; b:=3; if NOT(a>b) then k:=1 else k:=0

Здесь выполнится оператор k:=1, так как неправда, что 2>3.

 

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

Внутри скобок можно писать не только простые, но и сложные условия. Например, фрагмент if NOT ((a>2) AND (b>3)) AND (s>8)) then... можно перевести так - если неправда, что одновременно верны три условия - a>2, b>3, s>8, то...

Примеры:

ФРАГМЕНТ РЕЗУЛЬТАТ
a:=8; b:=6; if (a>b) AND (b>7) then k:=1 else k:=0 k=0
a:=8; b:=6; if (a>b) OR (b>7) then k:=1 else k:=0 k=1
a:=8; b:=6; if (a<b) OR (b>7) then k:=1 else k:=0 k=0
a:=8; b:=6; if NOT (a=8) then k:=1 else k:=0 k=0

Задание 26: "Замысловатая принцесса". Определите, кто нравится принцессе, по фрагменту из ее программы:

if (Tsvet ='Черный') AND ((Rost<180) OR (Rost>184))

then WriteLn ('ВЫ МНЕ ПОДОЙДЕТЕ')

else WriteLn ('ДО СВИДАНИЯ')

 

До сих пор мы применяли оператор if для выбора одной из двух возможностей. Покажем, как применять его для выбора одной из нескольких. Усложним нашу задачу про ПОПАЛ - НЕ ПОПАЛ:

Человек вводит в компьютер число. Если оно находится в интервале от 28 до 30, то нужно напечатать текст ПОПАЛ, если оно больше или равно 30 - то ПЕРЕЛЕТ, если оно находится на отрезке от 0 до 28, то НЕДОЛЕТ, если число меньше нуля - НЕ БЕЙ ПО СВОИМ.

Вот программа:

VAR a : Real;

BEGIN

ReadLn (a);

if (a>28) AND (a<30) then WriteLn ('ПОПАЛ');

if a>=30 then WriteLn ('ПЕРЕЛЕТ');

if (a>=0) AND (a<=28) then WriteLn ('НЕДОЛЕТ');

if a<0 then WriteLn ('НЕ БЕЙ ПО СВОИМ')

END.

Необходимо обращать внимание на аккуратную расстановку знаков сравнения и числовых границ диапазонов. Если во втором if вместо a>=30 мы напишем a>=20, то при вводе числа 25 компьютер даст нам двусмыс­ленный ответ:

ПЕРЕЛЕТ
НЕДОЛЕТ

Если же мы вместо a>=30 напишем a>30, то при вводе числа 30 мы вообще не получим от компьютера никакого ответа.

Задание 27:

Человек вводит с клавиатуры строку, смысл которой - приветствие при встрече. Компьютер тоже должен ответить приветствием. Отвечать нужно в соответствии со следующей таблицей:

ПРИВЕТСТВИЕ ЧЕЛОВЕКА ОТВЕТ КОМПЬЮТЕРА
Привет Привет
Здравствуйте Здравствуйте
Здорово Здравствуйте
Добрый день Салют
Приветик Салют
Салют Салют
Здравия желаю Вольно

 

Символьный тип данныхChar

Описание VAR a,b: Char означает, что переменные a иbимеют право принимать значения любых символов, с которыми может работать компьютер. (О символах… Вот программа, переворачивающая любое трехбуквенное слово, введенное человеком… VAR c1,c2,c3: Char; BEGIN ReadLn (c1,c2,c3); WriteLn (c3,c2,c1) END.

Оператор вариантаcase

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

VAR Otmetka: Integer;

Begin

WriteLn ('Какую отметку ты получил по чистописанию?');

ReadLn (Otmetka);

CASE otmetka OF {Перевод: В СЛУЧАЕ ЕСЛИ отметка РАВНА...}

1,2 :WriteLn('Кошмар!');
3 :WriteLn('Неважно');

4 :WriteLn('Неплохо');
5 :WriteLn('Молодец!');

ELSE WriteLn('Таких отметок не бывает')

END {Конец оператора CASE}

End.

Основой программы является оператор варианта CASE (читается "кэйс", переводится "случай"). Предлог OF читается "эв". Весь оператор CASE нужно понимать так:

В СЛУЧАЕ ЕСЛИ отметка РАВНА

1 или 2 печатай 'Кошмар!'

3 печатай 'Неважно'

4 печатай 'Неплохо'

5 печатай 'Молодец!'

ИНАЧЕ печатай 'Таких отметок не бывает'

КОНЕЦ оператора case

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

Если вы еще недостаточно хорошо поняли логику оператора case, то обратите внимание на то, что в нашей программе он работает так же, как следующий оператор if:

if (Otmetka=1) OR (Otmetka=2)
then WriteLn('Кошмар!')
else if Otmetka=3
then WriteLn('Неважно')
else if Otmetka=4
then WriteLn('Неплохо')
else if Otmetka=5
then WriteLn('Молодец!')
else WriteLn('Таких отметок не бывает')

У оператора case есть существенное ограничение - переменная, стоящая после слова case, должна быть так называемого порядкового типа. Подробно о порядковых типах мы поговорим в Глава 12, пока же мы знаем три типа, относящиеся к порядковым - это Integer, LongInt и Char. Порядковыми они называются потому, что все их возможные значения можно выстроить по порядку и перечислить с начала до конца: -32768, ....4,5,6,7,8... 32767 для Integer, .....'д','е','ж','з','и'.... для Char. Получается, что значения типов Real и String применять в операторе case нельзя, так как совершенно непонятно, как их перечислять по порядку.

Таким образом, задачу про ПОПАЛ-НЕ ПОПАЛ в принципе невозможно решить при помощи case. И этому две причины: 1)переменная имеет тип Real, 2)перед двоеточием в операторе case нельзя писать условия со знаками >, < и т.п.

Вот еще пример программы с оператором case:

VAR a,k : Integer;

Begin

a:=3;

case a*a+1 of {В СЛУЧАЕ ЕСЛИ a*a+1 РАВНО...}

8,3,20 :k:=0;

7,10 :begin k:=1; WriteLn(k) end;

12 ..18 :k:=3

end {Конец оператора CASE}

End.

Эта программа напечатает 1. Здесь мы видим несколько новых для нас элементов:

Во-первых, после слова case стоит не переменная, а выражение, поэтому с перечисленными перед двоеточиями значениями будет сравниваться число 10, полученное как 3*3+1. Кстати, выражение тоже обязано быть порядкового типа (о том, что такое тип выражения, мы строго поговорим в 14.4, а сейчас скажем только, что это выражение, имеющее значения порядкового типа).

Во-вторых, один из операторов, стоящих после двоеточий, составной. Это begin k:=1; WriteLn(k) end

В-третьих - конструкция 12 ..18 . Она обозначает то же, что и 12,13,14,15,16,17,18. Она служит в нашем случае для сокращения записи и называется диапазоном.

В-четвертых, здесь отсутствует конструкция else. Это значит, что если бы в нашей программе мы вместо a:=3 написали a:=0, то оператор case, не найдя совпадения, не выбрал бы ни один из трех своих вариантов и, не найдя также else, завершил бы свою работу, так ничего и не сделав.

Задание 28:

Ученик вводит с клавиатуры букву русского алфавита. Компьютер должен сказать, какая это буква - гласная, согласная звонкая, согласная глухая или другая какая-нибудь (можно и НЕ ЗНАЮ).

Задание 29: «Калькулятор». Ученик вводит с клавиатуры число, символ арифметического действия (+, -, *, /) и еще одно число. Компьютер должен напечатать результат. Указание: Используйте три оператора ReadLn.

Глава 6. Циклические программы

Оператор переходаGOTO. Цикл. Метки

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

Write ('Это ');
Write ('тело ');
Write ('цикла');
Write (' ')

в результате чего на мониторе мы бы увидели:

Это тело цикла Это тело цикла Это тело цикла Это тело цикла . . . .

Большинство языков программирования (в том числе и Паскаль) устроены так, что операторы выполняются в том порядке, в котором они записаны. Это значит, что после оператора Write ('Это ') обязательно выполнится оператор Write ('тело '), а после него - Write ('цикла'), а после него - Write (' '). Все это хорошо. Но нам нужно, чтобы после выполнения оператора Write (' ') Паскаль нарушал этот свой принцип последовательного выполнения операторов и выполнял бы оператор Write ('Это '). Если мы этого добьемся, то дальше все пойдет само собой, так как после Write ('Это ') Паскаль автоматически выполнит Write ('тело ') и так далее до бесконечности.

Если бы операторы Паскаля можно было писать по-русски, то для достижения нашей цели было бы естественно воспользоваться такой конструкцией:

метка m1: Write ('Это ');
Write ('тело ');
Write ('цикла');
Write (' ');
иди к оператору, помеченному меткой m1

Здесь мы видим новый для нас "оператор" ИДИ, который выполняется после Write (' ') и единственная работа которого заключается в том, чтобы заставить компьютер перескочить к выполнению оператора Write ('Это '), помеченного меткой m1.

А вот как этот фрагмент выглядит реально на Паскале:

m1: Write ('Это ');
Write ('тело ');
Write ('цикла');
Write (' ');
GOTO m1

Здесь GOTO- оператор перехода, читается " 'гоуту", переводится "иди к", m1 - метка.

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

Мы пока знаем, что переменная, встречающаяся в программе, должна быть описана выше BEGIN после слова VAR. Метки, встречающиеся в программе, тоже должны быть описаны выше BEGIN после слова LABEL(читается "лэйбл", переводится "метка").

Вот наша программа полностью:

LABEL m1;
BEGIN
m1: Write ('Это ');
Write ('тело ');
Write ('цикла');
Write (' ');
goto m1
END.

Если вы уже запустили эту программу, то через некоторое время перед вами должен встать жизненно важный вопрос – как же ее остановить? Для этого достаточно прочесть параграф «Выполнение программы» из части IV. Вот вкратце, что вам нужно оттуда знать:

Для прерывания работы программы (в том числе и зациклившейся) существует комбинация клавиш Ctrl-Break (имеется в виду, что, удерживая нажатой клавишу Ctrl, вы должны щелкнуть по клавише Break). На экран возвращается окно редактора. Строка программы, на которой она была прервана, выделяется полосой белого цвета. Если вы снова запустите программу, она продолжит работу с прерванного места. Чтобы начать сначала, уберите полосу с экрана клавишами Ctrl-F2.

Группа операторов, выполняющихся многократно, называется телом цикла. У нас это все операторы, начиная с Write ('Это ') и кончая GOTO m1.

Пример программы:

LABEL 8;
VAR a,k : Integer;
BEGIN
k:=6;

a:=100;

goto 8;

a:=a+k;

k:=2*k;

WriteLn(a);

8: a:=a+1;

k:=k+10;

WriteLn(k,' ' ,a);

END.

Эта программа напечатает 16 101. Операторы выполняются в такой последовательности:

k:=6;

a:=100;

goto 8;

a:=a+1;

k:=k+10;

WriteLn(k,' ' ,a);

А операторы a:=a+k; k:=2*k; WriteLn(a) выполнены не будут вообще, несмотря на то, что написаны.

Задание 30: Определить без компьютера, что будет печатать программа:

LABEL m1,met5;
VAR n,k : Integer;
BEGIN
n:=10;

k:=0;

WriteLn('Считаем зайцев' );

met5: Write(n);

n:=n+k;

goto m1;

n:=n+1;

m1: Write(' зайцев ');

ReadLn;

k:=k+1;

goto met5;

WriteLn('Посчитали зайцев')

END.

 

А теперь, уважаемый читатель, нам с вами пришла пора снова отвлечься от программирования и расширить свои знания о работе на компьютере. Сейчас вам необходимо проделать то, что сказано в части IV в параграфе «Работа с несколькими окнами» и пункте «Работа с окнами пользователя и отладчика» параграфа «Исправление ошибок. Отладка программы».

 

 

Задания 31-33:

Написать программы для выполнения следующих заданий:

31) Бесконечно печатать букву А: ААААААААААА.....

32) Бесконечно печатать 1000 999 998 997 996 ......

33) Бесконечно печатать 100 50 25 12.5.... с 8 десятичными знаками.

Примечание: Во всех программах используйте ReadLn для создания паузы на каждом цикле. Чтобы программа шла все-таки довольно быстро, нажмите клавишу ввода и не отпускайте.

Выход из цикла с помощью if

Задача: При помощи цикла напечатать на экране: Начало счета 3 5 7 9 Конец счета  

Оператор цикла repeat

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

В Паскале - три оператора цикла: repeat, while и for. Первым изучим оператор repeat.

Конструкция repeat. . . . . untila+2>3*b читается "ри'пит.....ан'тил...", а переводится "повторяй......до тех пор, пока a+2 не станет больше 3*b".

Составим с использованием оператора repeat программу решения задачи о печати чисел 3 5 7 9 из предыдущего параграфа. Для того, чтобы точно определить работу оператора repeat, приведем ее параллельно со вторым вариантом программы решения этой задачи из того же параграфа:

 

2 ВАРИАНТ ВАРИАНТ С REPEAT
LABEL m1,m2; VAR f : Integer; BEGIN Write('Начало счета '); f:=3; m1: Write(f,' '); f:=f+2; if f>9 then goto m2 else goto m1; m2: Write(' Конец счета') END. VAR f : Integer; BEGIN Write('Начало счета '); f:=3; repeat Write(f,' '); f:=f+2; until f>9; Write(' Конец счета') END.

Порядок работы обеих программ совершенно одинаков, так что можно считать слово repeat заменой метки m1, а конструкцию until f>9 считать заменой оператора if f>9 then goto m2 else goto m1.

Синтаксис оператора repeat:

Repeat оператор ; оператор ;. . . ; оператор until условие

Вкратце работу оператора repeat можно описать так: Повторяй выполнение операторов, стоящих между словами repeat и until, до тех пор, пока не станет истинным условие.

Более подробно работа оператора repeat описывается так:

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

Задача: Компьютер предлагает человеку ввести слово, после чего распечатывает это слово, снабдив его восклицательным знаком. Затем снова предлагает ввести слово и так до тех пор, пока человек не введет слово "Хватит". Распечатав его с восклицательным знаком, компьютер отвечает "Хватит так хватит" и заканчивает работу.

Придумаем строковую переменную, в которую человек будет с клавиатуры вводить слово. Назовем ее Slovo.

VAR Slovo : String;
BEGIN
repeat
WriteLn('Введите слово');
ReadLn(Slovo);
WriteLn(Slovo, '!')
until Slovo='Хватит';
WriteLn('Хватит так хватит')
END.

Задание 37: Усложним эту задачу. Пусть компьютер перед распечаткой каждого слова ставит его порядковый номер.

Задание 38-39: Выполнить с применением оператора repeat последние два задания из предыдущего параграфа.

Задание 40: Если камень бросить горизонтально со 100-метровой башни со скоростью v=20м/с, то его расстояние от башни по горизонтали (s) будет выражаться формулой s=vt, где t – время полета камня в секундах. Высота над землей h будет выражаться формулой h=100 – 9.81t2/2. Вычислять и печатать t, s и h для t=0, 0.2, 0.4, 0.6 и так далее до тех пор, пока камень не упадет на землю.

Оператор цикла while

Синтаксис оператора while:

WHILE условие DO оператор

Словоwhileчитается "вайл", слово do- "ду", вся конструкция переводится так - Покаусловие истинно, делайоператор. Например, while a>b do b:=b+1.

Работает оператор while так:

Сначала компьютер проверяет истинность условия, стоящего после слова while. Если условие истинно, то выполняется оператор, стоящий после do. Затем снова проверяется истинность условия и в случае истинности снова выполняется этот оператор. И т.д. Если условие ложно, то оператор while прекращает свою работу и компьютер переходит к выполнению следующего оператора.

Оператор, стоящий после while, вполне может быть составным, поэтому тело цикла у оператора while, так же как и у оператора repeat, может состоять из многих операторов.

Решим при помощи while ту же задачу о печати чисел 3 5 7 9, что в предыдущем параграфе решили с помощью repeat. Для того, чтобы точно определить работу оператора while, приведем программу ее решения параллельно с третьим вариантом программы из 6.2:

3 ВАРИАНТ ВАРИАНТ С WHILE
LABELm1,m2,m3; VAR f : Integer; BEGIN Write('Начало счета '); f:=3; m1: if f<=9 then goto m3 else goto m2; m3: Write(f,' '); f:=f+2; goto m1; m2: Write(' Конец счета') END. VAR f : Integer; BEGIN Write('Начало счета '); f:=3; while f<=9 do begin Write(f,' '); f:=f+2; end; Write(' Конец счета') END.

Как видите, здесь после do стоит составной оператор begin Write(f,' '); f:=f+2; end. Последовательность исполнения операторов и проверки условий в обеих программах совершенно аналогичны.

 

Типичная ошибка начинающих – небрежное обращение со знаками сравнения. Многие не видят большой разницы в том, как записать – while f<=9 или while f<9 , а затем, «недополучив» результат, удивляются, почему. И здесь лучшим средством для понимания является отладочный режим. Попробуйте ошибочный вариант последней программы (с while f<9) выполнить в пошаговом режиме с использованием окон пользователя и отладчика. Для этого введите в окно отладчика две вещи: переменную f и выражение f<9 (оно может иметь только два значения: true - истина и false - ложь, другими словами – «условие выполнено» и «условие не выполнено»).

 

Задание 41: Вычислять с использованием while квадратные корни из чисел 900, 893, 886, 879 и т.д. до тех пор, пока это можно делать.

Отличия операторов repeat и while

Отличий три:

· Компьютер выходит из цикла оператора repeat тогда, когда условие истинно, а из цикла оператора while - когда условие ложно.

· while может ни разу не выполнить оператор, стоящий после do. repeat же хотя бы раз операторы, стоящие между repeat и until, выполнит.

Так, фрагмент k:=8; repeat k:=1 until 3>2; WriteLn(k) напечатает 1.

А фрагмент k:=8; while 2>3 do k:=1; WriteLn(k) напечатает 8.

· При компиляции оператор while дает несколько более эффективную программу, чем оператор repeat.

 

Часто эти отличия для начинающих малосущественны, поэтому выбирайте оператор по вкусу. Мне, например, надоели паскалевские begin и end, поэтому я охотнее пользуюсь оператором repeat.

Оператор цикла for

Выполняя программу печати чисел 3 5 7 9, оператор repeat выполнил цикл 4 раза. То же самое сделал и оператор while. Однако, обычно, когда мы пишем операторы repeat и while, нам совсем неважно знать, сколько раз они выполнят цикл. Тем не менее, существует много задач, для решения которых цикл нужно выполнить именно определенное количество раз. В этом случае удобно использовать оператор цикла for.

Задача: 200 раз напечатать слово ФУТБОЛ.

Попробуем сначала решить задачу при помощи оператора goto. Начнем с такого фрагмента:

metka: WriteLn('ФУТБОЛ');
goto metka

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

i:=1;
metka: WriteLn('ФУТБОЛ');
i:=i+1; {увеличение i на 1}
if i<=200 then goto metka

END.

Здесь i вначале равно 1, но к каждому следующему выполнению цикла оно увеличивается на 1. В первый раз выполняя оператор if, компьютер проверяет условие 2<=200 и найдя его истинным, выполняет оператор goto metka. Во второй раз проверяется условие 3<=200 и т.д. В 199-й раз компьютер проверяет условие 200<=200 и найдя его истинным, выполняет оператор goto metka. В 200-й раз компьютер проверяет условие 201<=200 и найдя его ложным, выходит из цикла.

В нашем фрагменте "полезную" работу выполняет только одна строка из четырех - WriteLn('ФУТБОЛ'). Остальные три строки заняты тем, что обеспечивают выполнение "полезной" строки ровно 200 раз. Нам пришлось организовать специальную переменную, значение которой в каждый момент выполнения программы говорит о том, в какой раз выполняется цикл. Переменная с таким свойством называется счетчиком циклов.

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

LABEL m1,m2; VAR i : Integer; BEGIN i:=1; m1: if i>200 then goto m2; WriteLn('ФУТБОЛ'); i:=i+1; goto m1; m2: END. VAR i : Integer; BEGIN for i:=1 to 200 do WriteLn('ФУТБОЛ') END.

Слово forчитается "фо", переводится "для". Слово to читается "ту", переводится "до". Слово doчитается "ду", переводится "делай". Конструкция for i:=1 to 200 do по-русски читается так: Для i, изменяющегося от 1 до 200, делай оператор, стоящий после слова do. Смысл повторения здесь такой же, как и в операторе while. Оператор, стоящий после do, тоже, конечно, может быть составным.

Синтаксис оператора for:

FOR имя := выражение1 TO выражение2 DO оператор

Пример записи: for j:=a+b to2*s dok:=k+1.

Пояснения к синтаксической схеме:

имя - это имя произвольной переменной порядкового типа (см. 5.7 и 12.8), в частности целочисленной, называемой переменной цикла,

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

Работа оператора for:

Прежде всего вычисляется выражение1, и переменной цикла (пусть это будет i) присваивается его значение. Затем вычисляется выражение2 и сравнивается с i. Если i > выражения2, то оператор for завершает свою работу, так ничего и не сделав. В противном случае выполняется оператор, стоящий после do. После выполнения этого оператора значение i увеличивается на 1 и снова сравнивается с выражением2. Если i > выражения2, то оператор for завершает свою работу, иначе снова выполняется оператор, стоящий после do, снова i увеличивается на 1 и т.д.

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

10 ФУТБОЛ 11 ФУТБОЛ 12 ФУТБОЛ . . . . . 200 ФУТБОЛ

Вот программа:

VAR i : Integer;
BEGIN
for i:=10 to 200 do
begin Write(i);
Write(' ФУТБОЛ ')
end
END.

Здесь после do стоит уже составной оператор.

Можно ли удобно использовать оператор for для печати такой информации?:

100 ФУТБОЛ 99 ФУТБОЛ 98 ФУТБОЛ . . . . . 40 ФУТБОЛ

Вполне, так как оператор for позволяет не только увеличивать, но и уменьшать переменную цикла. Однако, для этого нельзя писать for i:=100 to 40, а нужно писать for i:=100 downto 40. Читается downto - "'даунту", переводится буквально "вниз до". Соответственно, для выхода из цикла должно быть истинным не условие i > выражения2, а условие i < выражения2.

Вот объединенный синтаксис оператора for:

FOR имя := выражение1 TO DOWNTO выражение2 DO оператор

 

Вертикальная черта между двумя элементами конструкции «TOиDOWNTO» говорит о том, что в конструкции должен присутствовать один из этих элементов.

Задание 42: Напечатать с помощью оператора for:

Прямой счет: -5 -4 -3 -2 -1 0 1 2 3 4 5 Обратный счет: 5 4 3 2 1 0 -1 -2 -3 -4 -5 Конец счета

 

Глава 7. Типичные маленькие программы

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

Вычислительная циклическая программа

Сначала напишем фрагмент для одного зала: ReadLn (dlina, shirina, visota); S:=dlina*shirina; {Площадь пола}

Роль ошибок

Площадь пола=300 Объем зала=304 Площадь пола=600 Объем зала=605 Площадь пола=50 Объем зала=53

Счетчики

Фрагмент, решающий задачу: c:=0; {Обнуляем счетчик} m: ReadLn(a); {Вводим очередное число}

BEGIN

c:=0; {Обнуляем счетчик}

for i:=1 to 200 do begin

ReadLn(a);

if a>0 then c:=c+1

end {for};

WriteLn('Из них положительных - ' ,c)

END.

Пояснения:Путь рассуждений здесь тот же, что и в первой задаче. В результате применения оператора for фрагмент ReadLn(a);if a>0 then c:=c+1 выполняется ровно 200 раз, благодаря чему счетчик с накапливает нужное значение. Оператор WriteLn выполняется только один раз и печатает это значение.

Совет: Если вы запускаете эту программу в компьютере, то с числом 200 возиться крайне долго. Поменяйте его на 3 или 4. Смысл программы от этого не изменится.

 

Задание 46: Что будет, если

1) Вместо c:=0 написать c:=10.

2) Вместо c:=c+1 написать c:=c+2.

3) Строки end {for} и WriteLn поменять местами.

4) Строки c:=0 и for поменять местами.

5) Строки for и ReadLn поменять местами.

Задача 3:В компьютер один за другим вводятся произвольные символы. Ввод заканчивается символом "/". Подсчитать, какой процент от общего числа введенных символов составляют символ "W" и символ ":" по отдельности.

Здесь мы организуем три счетчика одновременно: сW и сDv - для подсчета букв W и двоеточий соответственно, а также i - счетчик циклов, то есть общего числа введенных символов.

Программа:

VAR i,cW,cDv, procent_W, procent_Dv : Integer;

simvol :Char;

Begin

i:=0; cW:=0; cDv:=0; {Обнуляем все три счетчика}

repeat {Повторяй цикл}

ReadLn (simvol); {Введи символ}

i:=i+1; {«Посчитай» его}

case simvol of

'W' :cW:=cW+1; {Если это W, увеличь счетчик символов W}

':' :cDv:=cDv+1 {Если это :, увеличь счетчик символов :}

End

until simvol = '/'; {пока не наткнешься на символ /}

procent_W :=Round(100*cW/i); {Вычисляй процент символов W}

procent_Dv :=Round(100*cDv/i); {Вычисляй процент символов :}

WriteLn(procent_W,' ',procent_Dv)

End.

Задание 47: В компьютер вводится N чисел. Подсчитать по отдельности количество отрицательных, положительных и тех, что превышают число 10.

Задание 48: В компьютер вводятся пары целых чисел. Подсчитать, сколько среди них пар, дающих в сумме число 13. Подсчет закончить после ввода пары нулей.

Напомню, что пару чисел можно ввести оператором ReadLn(a,b).

Сумматоры

s:=0; {Обнуляем сумматор. Это не менее важно, чем обнулить счетчик} m: ReadLn(a); s:=s+a; {Увеличиваем сумматор}

BEGIN

ReadLn(N);

s:=0;

for i:=1 to N do begin

ReadLn(a);

s:=s+a

end {for};

WriteLn(‘Сумма равна ' ,s:20:10)

END.

Задание 49: Пусть N=2, a=5 и 3. Тогда по этой программе Паскаль напечатает 8. Что он напечатает, если:

1) Вместо s:=0 написать s:=10.

2) Вместо s:=s+a написать s:=s+a+1.

3) Строки end {for} и WriteLn поменять местами.

4) Строки s:=0 и for поменять местами.

5) Строки for и ReadLn поменять местами.

6) Строки s:=s+a и end {for} поменять местами.

7) Вместо for i:=1 to N написать for i:=2 to N.

Задания 50-52: Написать программы для следующих задач:

50) Во дворце 40 залов. Известны длина и ширина каждого зала. Вычислить площадь пола всего дворца.

51) Вычислить средний балл учеников вашего класса по физике.

52) Вычислить произведение N произвольных чисел.

Вложение циклов в разветвления и наоборот

Для тренировки определите, что напечатает следующий фрагмент: for i:=1 to 5 do begin a:=9;

Вложенные циклы

  1*1= 1*2= 1*3= 1*4= 1*5= 1*6= 1*7= …   Начнем с малого - пусть нужно напечатать

Поиск максимального из чисел

Задача рыбаку: Принести домой самую большую из выловленных рыб. Решение рыбака: Рыбак приготовил для самой большой рыбы пустое ведро. Первую… Решение программиста: Программист приготовил для самого большого числа ячейку и придумал ей название, скажем, max.…

BEGIN

ReadLn(max); {первую рыбу - в ведро}

for i:=2 to 10 do begin {ловим остальных рыб:}

ReadLn(chislo); {поймали очередную рыбу}

if chislo>max then max:=chislo {и если она больше той, что в ведре, бросаем ее в ведро }

end {for};

WriteLn(max) {несем самую большую рыбу домой}

END.

 

Задание 57: Найти из N чисел минимальное. Каким по порядку было введено минимальное число? Указание: для номера минимального числа тоже нужно отвести специальную ячейку.

Задание 58: У вас есть данные о росте ваших одноклассников. Правда ли, что рост самого высокого отличается от роста самого низкого больше, чем на 40 см.?

 

Глава 8. Процедуры

Смысл и выгода процедур вам известны из 2.8. Напомню, что процедурынужны для того, чтобы программа была короче, и чтобы ее было легче прочесть. Ни одна профессиональная программа не обходится без процедур или без их старших братьев - объектов, рассмотрение которых выходит за рамки начального курса.

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

Компьютер звучит

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

USES CRT;
BEGIN

Sound(300)

END.

Пояснения:

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

Единственный оператор программы Sound(300) приказывает компьютеру включить ровный однообразный звук частотой 300 колебаний в секунду (герц). Слово Sound звучит “‘саунд”, переводится “звук”. Для тех, кто не знает, поясню, что частота определяет высоту звука. Sound(300) - это звук средней высоты . Sound(6000) - это звук высокий, тонкий, как комариный писк. Sound(40) - звук низкий, толстый.

Итак, все действие нашей программы заключается в том, что включается звук. А что дальше? Когда он выключается? А никогда! Программа, выполнившись мгновенно, прекращает свою работу, и мы остаемся один на один со звуком. Через две-три минуты он начинает нам надоедать. Пытаясь его прекратить, мы выходим из среды Паскаля - не помогает. В общем, звук продолжается все то время, пока компьютер включен. В остальном он никак не мешает компьютеру правильно работать. Мы можем запустить другую программу - звук будет сопровождать нас. Самый простой способ избавиться от звука - перезапустить компьютер. Другой способ - выполнить программу, в которой есть оператор NoSound:

USES CRT;
BEGIN

NoSound

END.

Оператор NoSound(звучит “ноу ‘саунд”, переводится “нет звука”), выключает звук. Совет: Работая с любой звуковой программой, откройте еще одно окно и введите туда эту программу с NoSound. Не пожалеете!

Теперь рассмотрим такую программу:

USES CRT;
BEGIN

Sound (300); Delay (2000); NoSound

END.

Здесь мы видим новый для нас оператор Delay (2000). Он читается “ди’лэй”, переводится “отсрочка” или “пауза”. Его действие в том, что он приостанавливает работу программы на 2000 миллисекунд или, что то же самое, на 2 секунды. Delay (1000) приостанавливает работу программы на 1 секунду, Delay (500) - на полсекунды и т.д. (Должен сказать, что на самом деле продолжительность паузы сильно зависит от быстродействия компьютера).

Итак, оператор Sound (300) включает звук. Сразу после этого оператор Delay (2000) приостанавливает работу программы на 2 сек. Но звук этот оператор не может выключить, компьютер продолжает звучать. Через 2 сек программа снова оживает и выполняется оператор NoSound. Звук выключается. Таким образом, результатом выполнения этих трех операторов будет звук частотой 300 гц продолжительностью 2 сек.

Рассмотрим работу программы:

USES CRT;
BEGIN

Sound(900);Delay(1000);Sound(200);Delay(3000);NoSound

END.

Начинается она со звука частотой 900 гц и продолжительностью 1 с, а затем оператор Sound(200) включает вместо звука в 900 гц звук частотой 200 гц, который длится 3 с.

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

USES CRT;

VAR hz: Integer;

BEGIN

hz:=60;

while hz<800 do begin

Sound(hz);

Delay(1000);

hz:=hz+40

end;

NoSound

END.

Если вас интересуют музыкальные ноты, то вот вам операторы Sound, задающие все ноты третьей октавы:

Нота до Sound(523)
Нота до диез Sound(554)
Нота ре Sound(587)
Нота ре диез Sound(622)
Нота ми Sound(659)
Нота фа Sound(698)
Нота фа диез Sound(740)
Нота соль Sound(784)
Нота соль диез Sound(831)
Нота ля Sound(880)
Нота ля диез Sound(932)
Нота си Sound(988)

 

Задания 59-63:

59) Уменьшив как следует числа в операторах Delay(1000) и hz:=hz+40 можно добиться впечатления одного непрерывного постепенно повышающегося звука (сирена). Попробуйте сделать это.

60) Если вам это удалось, попробуйте смоделировать сирену милицейской машины: звук вверх - звук вниз - звук вверх - звук вниз - … и так несколько раз.

61) Быстро чередуя короткие звуки двух разных частот и короткие паузы, можно добиться разных звуковых эффектов и шумов, например звука телефонного звонка или моторчика авиамодели.

62) Сделайте “датчик чувствительности уха к высоким частотам”. Извстно, что человеческое ухо не может слышать звуки, частота которых превышает 10000-20000 гц. У разных людей порог чувствительности разный. Напишите программу, которая выдает звуки все более высокой частоты и печатает на экране значения этой частоты, так что человек успевает увидеть, при какой частоте он перестает слышать звук. Вы сможете определить, у кого порог чувствительности выше – у вас или у вашего друга. Удобно внутри цикла использовать команду ReadLn.

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

Простейшие процедуры

Вот таблица кодирования русских и латинских букв (латинские буквы показаны строчными, а русские - заглавными): Аa .- Бb …   Закодируем азбукой Морзе текст PIPING и заставим компьютер воспроизвести соответствующий набор звуков. Пусть…

END.

Недостатки программы:

· Довольно большой объем, что обидно, так как в программе много одинаковых фрагментов.

· Если бы не комментарии, было бы совершенно непонятно, о чем эта программа.

 

А теперь я напишу ту же программу, но с использованием процедур:

Программа 2

USES CRT;

 

PROCEDURE tochka;

BEGIN Sound(900); Delay(100); NoSound; Delay(80) END;

 

PROCEDURE tire;

BEGIN Sound(900); Delay(200); NoSound; Delay(80) END;

 

BEGIN

{буква P:}tochka; tire; tire; tochka; Delay(300);

{буква I:} tochka; tochka; Delay(300);

{буква P:}tochka; tire; tire; tochka; Delay(300);

{буква I:} tochka; tochka; Delay(300);

{буква N:}tire; tochka; Delay(300);

{буква G:}tire; tire; tochka; Delay(300);

END.

Программа 2 гораздо короче и даже без комментариев понятнее программы 1. Поясним, как мы получили ее из предыдущей.

Сначала мы обнаружили в программе 1 часто повторяющиеся фрагменты. Их было два:

Sound(900); Delay(100); NoSound; Delay(80); {точка}

Sound(900); Delay(200); NoSound; Delay(80); {тире}

Затем мы придумали имена каждому фрагменту: tochka и tire. После этого можно было писать программу 2. Каждый фрагмент мы записали один раз в начале программы выше главного BEGIN, оформив его в виде так называемого описания процедуры:

PROCEDURE tochka;

BEGIN Sound(900); Delay(100); NoSound; Delay(80) END;

PROCEDURE tire;

BEGIN Sound(900); Delay(200); NoSound; Delay(80) END;

В результате программа “узнала”, что такое tochka и tire. С этого момента имена процедурtochka и tire можно употреблять, как обыкновенные операторы, ниже главного BEGIN. Паскаль выполняет программу, начиная с главного BEGIN, и когда он натыкается на имя процедуры, он подставляет вместо него соответствующий фрагмент, взятый из описания процедуры. Это событие называется вызовомпроцедурыилиобращениемк процедуре.

Синтаксис описания простейшей процедуры таков:

PROCEDURE имя ; BEGIN оператор ; оператор ; ... END

Слово PROCEDUREчитается “про’сидже”, переводится “процедура”. Имя процедуры создается по тем же правилам, что и имя переменной. Все, что идет после имени, будем называть телом процедуры.

Задание 64: Составьте программу с процедурами, которая исполнит мелодию “Чижик-пыжик” (ми-до-ми-до-фа-ми-ре-соль-соль-ля-си-до-до-до).

 

А теперь попробуем еще больше упростить нашу программу. Замечаем, что и в программе 2 тоже имеются одинаковые фрагменты:

{буква P:} tochka; tire; tire; tochka; Delay(300);

{буква I:} tochka; tochka; Delay(300);

Для экономии места их тоже выгодно оформить в виде процедур:

PROCEDURE P;

BEGIN tochka; tire; tire; tochka; Delay(300) END;

PROCEDURE I;

BEGIN tochka; tochka; Delay(300) END;

Остальные буквы тоже выгодно оформить в виде процедур, но уже не для экономии места, а для удобочитаемости программы. Вот окончательный вариант программы:

Программа 3

USES CRT;

 

PROCEDURE tochka;

BEGIN Sound(900); Delay(100); NoSound; Delay(80) END;

 

PROCEDURE tire;

BEGIN Sound(900); Delay(200); NoSound; Delay(80) END;

 

PROCEDURE P;

BEGIN tochka; tire; tire; tochka; Delay(300) END;

 

PROCEDURE I;

BEGIN tochka; tochka; Delay(300) END;

 

PROCEDURE N;

BEGIN tire; tochka; Delay(300) END;

 

PROCEDURE G;

BEGIN tire; tire; tochka; Delay(300) END;

 

 

BEGIN

P;I;P;I;N;G

END.

Эта программа понятна и без комментариев. От предыдущей она отличается тем, что процедуры вызываются не только из тела программы, но и из тел других процедур. Действительно, посмотрим на самое начало выполнения программы. Первое, на что натыкается Паскаль ниже главного BEGIN, это P. Заглянув выше главного BEGIN, Паскаль обнаруживает, что P - это имя процедуры, и начинает ее выполнять (вызывает на выполнение). При этом, первое, на что он натыкается, это tochka. Заглянув выше, Паскаль обнаруживает, что tochka - это имя процедуры, и тоже начинает ее выполнять (вызывает на выполнение). Обратите внимание, что

вызываемая процедура должна быть описана выше вызывающей.

Такая уж особенность у Паскаля. О том, что делать, если это требование выполнить невозможно, написано в 10.6. Закончив выполнять процедуру tochka, Паскаль возвращается в процедуру P (возвращает управление процедуре P). Там он идет к следующему оператору. Это оказывается tire. И т.д.

Задание 65: Компьютер печатает текст Песня «Чижик-пыжик». 1 куплет. После этого исполняется мелодия чижика-пыжика (см. выше). Затем компьютер печатает текст 2 куплет и мелодия чижика-пыжика исполняется еще раз.

Процедуры и операторы

Разберемся немного с терминологией. Прежде всего уточним структуру программына Паскале. Любая программа на Паскале состоит из двух разделов:

 

{Раздел описаний}

BEGIN

{Раздел операторов}

END.

 

Раздел описаний может и отсутствовать, если же он присутствует, то может содержать разделы VAR, LABEL, USES, PROCEDURE и другие, нами еще не изученные.

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

В самом начале части II я упомянул, что многие операторы на Паскале являются обращениями к процедурам. Для простоты мы договорились не различать поначалу обращения к процедурам и другие операторы. Сейчас нам пора этому научиться. Кроме процедур, написанных нами (таких как tochka, tire и др.), существуют еще так называемые стандартные процедурыПаскаля. Мы уже изучили следующие стандартные процедуры: Write, WriteLn, Read, ReadLn, Sound, Delay, NoSound. Они называются стандартными, потому что определены “внутри Паскаля”[7] и ими можно пользоваться, не описывая их, как мы описывали созданные нами “пользовательские” процедуры. Природа пользовательских и стандартных процедур едина, поэтому мы будем называть и те и другие просто процедурами. Операторами же мы будем продолжать называть операторы goto, if, case, for, while, repeat, оператор присваивания, составной оператор и еще незнакомые нам оператор with и пустой оператор.

Стандартные процедуры Halt и Exit

Exitчитается “ ‘экзит”, переводится с английского “выход”. До сих пор мы составляли программы, которые заканчивали свою работу на END с… BEGIN Write(1); Write(2); Halt; Write(3) END.

BEGIN

WriteLn ('Я, король Франции, спрашиваю вас - кто вы такие? Вот ты - кто такой?');

Atos;

WriteLn ('А ты, толстяк, кто такой?');

Portos;

WriteLn ('А ты что отмалчиваешься, усатый?');

dArtanian;

WriteLn ('Анна! Иди-ка сюда!!!');

Halt;

WriteLn ('Аудиенция закончена, прощайте!');

END.

Выполнив задание, скопируйте программу в редактор Паскаля и запустите ее. Если ответ не сходится, запустите ее в отладочном пошаговом режиме.

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

 

Глава 9. Графика

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

Стандартные модули

Реально так и сделано. В Паскале определен целый ряд необязательных его кусков, которые называются стандартными модулями. Упрощенно говоря,… Если программист специально не попросил, то в памяти оказывается только… А как же попросить? Очень просто. Если вам нужно работать со звуком, вы пишете первой строкой своей программы - USES…

Стандартный модуль Graph, текстовый и графический режимы

А в этой главе я опишу работу самых популярных с моей точки зрения процедур модуля Graph.

Текстовый и графический режимы

Текстовый режимиспользуется для вывода на экран текстовой и числовой информации. Работая в текстовом режиме, компьютер считает экран разбитым на 25… Работая в графическом режимекомпьютер считает экран разбитым на множество… Получается, что графический режим лучше текстового? В общем, да, конечно. Но у графического режима есть один…

Переключение между текстовым и графическим режимами

(Начиная с этого момента я не буду приводить переводы и произношение английских слов. Многие из них приведены в приложении П3 и П4.) Вот пример программы, которая сначала в текстовом режиме пишет на экране текст… USES Graph;

BEGIN

WriteLn(‘Это текстовый режим’);

{Инициализируем графический режим:}

ReadLn;

Device:=0;

InitGraph(Device, Mode, ’<путь к графическим драйверам>’);

Circle(100,80,50); {Обращение к процедуре рисования окружности. Пока без пояснений}

ReadLn;

{Закрываем графический режим, что рекомендую:}

CloseGraph;

WriteLn(‘Это снова текстовый режим’);

ReadLn

END.

Пояснения: Перед использованием процедуры InitGraph необходимо создать две переменные величины типа Integer с произвольными именами (я использовал имена Device и Mode). Обе эти переменные при обращении к процедуре InitGraph должны быть записаны внутри круглых скобок. Вам на первых порах совершенно не обязательно это знать, но поясню, что Device означает тип вашего видеоадаптера (CGA, EGA, VGA или другой), а Mode означает номер графического режима. Если вы ничего не знаете ни о том, ни о другом, смело пишите Device := 0 и Паскаль сам определит тип вашего видеоадаптера и установит самый мощный из допустимых графический режим.

Третий элемент - не что иное, как путь к графическим драйверам Паскаля. Я использовал угловые скобки <>, чтобы подчеркнуть, что в вашей программе нужно писать не те четыре русских слова, что внутри угловых скобок, а то, на что они указывают. Почти наверняка для вас графический драйвер представлен файлом egavga.bgi, расположенном в каталоге BGI. Если сам Паскаль расположен в каталоге TP диска c, то строка вашей программы будет выглядеть так:

InitGraph(Device, Mode, ‘c:TPBGI’)

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

Если Паскаль при запуске графического режима жалуется (File not found (GRAPH.TPU)), то прочтите «Обзор популярных команд меню» из части IV. Там сказано, что делать.

 

Учтите, что при переключении режимов все содержимое экрана стирается.

Рисуем простейшие фигуры

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

BEGIN

Device:=0;

InitGraph(Device, Mode, ’<путь к графическим драйверам>’);

PutPixel(50,100,White);

Rectangle(150,150,50,200); {правый верхний и левый нижний углы}

Circle(200,100,50); {окружность}

Line(100,50,250,150); {отрезок прямой}

ReadLn;

CloseGraph

END.

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

Окружность можно построить, если известно положение центра и радиус. Окружность рисуется процедурой Circle, первые два параметра которой - координаты центра, третий - радиус.

 
 

Попробуем теперь нарисовать эллипсс центром в точке х=200, у=150, вот такой:

 

 

Это выполнит процедура Ellipse. Вот ее вызов - Ellipse(200,150,0,360,100,40).Если вы хотите нарисовать не полный эллипс, а только часть его, вместо 0 укажите начальный угол дуги эллипса, скажем 90, а вместо 360 - конечный угол, скажем 180.

Процедура ClearDeviceстирает все с экрана в графическом режиме.

Задание 67: Нарисуйте снеговика:

 
 

Работа с цветом. Заливка. Стиль линийи заливки

Первый параметр процедуры SetLineStyle управляет стилем прямых отрезков (штриховые, пунктирные и др.). Попробуйте вместо 0 написать 1, 2 или 3 и… Второго параметра касаться не будем.  

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

Как заставить Паскаль короткой программой рисовать множество элементов? Ответ: применять циклы, используя в обращениях к графическим процедурам… Задача: Нарисовать горизонтальный ряд окружностей радиусом 10 на расстоянии… Как видим, центры соседних окружностей отстоят друг от друга на 30. Вот примитивный фрагмент, решающий эту задачу: …

END.

Задание 69:. Попробуйте уменьшить расстояние между центрами окружностей, не изменяя их радиуса, нарисовав их плотнее, чтобы они пересекались, еще плотнее, пока они не образуют “трубу”.

Задание 70:. Удлините трубу налево и направо до краев экрана.

Задание 71:. Увеличьте толщину трубы.

 

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

USES Graph;

VAR x, y, Device, Mode : Integer;

BEGIN
Device:=0;

InitGraph(Device, Mode, ’<путь к графическим драйверам>’);

x:=50;

y:=20;

repeat
Circle(x,y,10);

x:=x+30;

y:=y+20;

until x>290;
ReadLn;

CloseGraph

END.

Если мы захотим менять радиус, то организуем переменную R, тоже типа Integer.

 

Задание 72:. Нарисуйте ряд точек по направлению из левого нижнего угла в правый верхний.

Задание 73:. “Круги на воде”. Нарисуйте пару десятков концентрических окружностей, то есть окружностей разного радиуса, но имеющих общий центр.

Задание 74:. “Компакт-диск”. Если радиус самого маленького “круга на воде” будет порядка 50, а самого большого - во весь экран, и если радиусы соседних окружностей будут различаться на 2-3 пиксела, то на экране вы увидете привлекательный “компакт-диск”. Сделайте его золотым (Yellow).

Задание 75:. Не трогая x, а меняя только yи R, вы получите коническую башню.

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

Задание 77:. Разлинуйте экран в линейку.

Задание 78:. А теперь в клетку.

Задание 79:. А теперь в косую линейку.

Задание 80:. Начертите ряд квадратов.

 

 

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

Задание 81:. Нарисуйте шахматную доску.

Задание 82:. “Ковер”. В задании 69 вы рисовали горизонтальный ряд пересекающихся окружностей. Теперь нарисуйте один под другим много таких рядов.

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

Задание 83:. Пусть у этого ковра будет вырезан левый нижний угол.

Задание 84:. ¼ и вдобавок вырезан квадрат посередине.

Использование случайных величинпри рисовании

Попробуем нарисовать “звездное небо”. Для этого достаточно в случайных местах экрана нарисовать некоторое количество разноцветных точек (скажем,… PutPixel (Random(640), Random(480), Random(16)) Число 16 взято по той причине, что все цвета в Паскале имеют номера от 0 до 15.

Движение картинок по экрану

USES Graph; VAR x, Device, Mode : Integer; BEGIN Device:=0;

END.

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

 

Задание 88:. Измените скорость движения. Если окружность движется небыстро, увеличьте скорость (x:=x+2), если слишком быстро – уменьшите процедурой Delay.

Задание 89:. Пусть одновременно движутся две окружности.

Задание 90:. Одна вниз, другая направо.

Задание 91:. Заставьте окружность отскочить от правого края экрана.

Задание 92:. Заставьте окружность бесконечно двигаться, отскакивая от правого и левого краев экрана.

 

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

 

Задание 93:. “Биллиардный шар”. Нарисуйте «биллиардный стол» – большой прямоугольник. Окружность под углом летает по столу, отскакивая от его краев по закону отражения. Попав “в лузу” (любой из четырех углов стола), останавливается.

 

Задание 94: Изобразите полет камня, брошенного с башни, для задания из 6.3. Напоминаю условие задания. Камень бросили горизонтально со 100-метровой башни со скоростью v=20м/с. Его расстояние от башни по горизонтали (s) выражается формулой s=v*t, где t – время полета камня в секундах. Высота над землей h выражается формулой h=100 – 9.81*t2/2. Нарисуйте башню, землю, камень (маленькая окружность). Затем камень летит. Добейтесь, чтобы время полета камня на экране примерно соответствовало реальному времени, полученному в 6.3. Нарисуйте траекторию полета камня. Для этого достаточно, чтобы камень оставлял за собой следы в виде точек.

Указание: В задаче говорится о метрах, а на экране расстояние измеряется в пикселах. Поэтому вам придется задать масштаб, то есть вообразить, что один пиксел равен, скажем, одному метру. Тогда высота башни будет равна 100 пикселам, а скорость камня – 20 пикселов в секунду Правда, картинка на экране в этом случае может показаться вам маловатой. Тогда можете задать другой масштаб – один метр, скажем, - четыре пиксела. Тогда высота башни будет равна 400 пикселам, скорость камня – 80 пикселов в секунду, а формула изменится - h=4*(100 – 9.81*t2/2).

 

Задание 95 (сложное): Сделайте игру: Пушка на экране стреляет в цель ядрами. С какого выстрела она поразит противника? Между пушкой и целью расположена небольшая гора. Перед началом игры случайно задается горизонтальная координата цели. Затем рисуется картинка.

 
 

 

 


Перед каждым выстрелом компьютер отображает на экране номер выстрела и запрашивает у человека стартовую скорость ядра v и угол a наклона ствола пушки к земле. Затем летит ядро. Полет ядра подчиняется двум уравнениям: s=v*t*cosa и h=v*t*sina – 9.81*t2/2 (см. предыдущее задание). Считается, что цель поражена, если ядро «отгрызло» от нее хоть маленький кусочек.

 

Я рассмотрел основные простые возможности модуля Graph. Некоторые другие средства модуля будут рассмотрены в Глава 15.

 

Глава 10. Создаем первую большую программу

В этой главе я вместе с вами напишу первую реальную программу. Достаточно большую для начинающих (строк на сто).

Прежде, чем приступить к большой программе, прочтите и изучите все, что вы еще не успели изучить в части IV, особенно “Отладку больших программ”.

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

Постановка задачи

Задача: Создать мультфильм следующего содержания: 1) На экране возникает ночной пейзаж и секунды три ничего не происходит: 2)     Затем звучит “космическая” музыка (секунд на 5).

BEGIN

Device:=0;

InitGraph(Device, Mode, ’<путь к гр.др.>’);

DirectVideo:=false;

Landscape; { рисование пейзажа }

WriteLn(‘Работает пауза 3 секунды’); { пауза три секунды }

Music; { музыка }

Flying_Saucer; { движение тарелки }

Music; { музыка }

WriteLn(‘Работает свет в окне’); { свет в окне }

ReadLn;

CloseGraph

END.

Пояснение. В нашей программе мы используем и модуль Graph и модуль CRT, так как нам понадобятся и графика и музыка. В этом случае оператор WriteLn просто так не работает. Чтобы он все-таки заработал, необходимо предварительно выполнить оператор DirectVideo:=false. Смысл его рассматривать не будем.

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

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

Работает процедура Пейзаж

Работает пауза 3 секунды

Работает процедура Музыка

Работает процедура Летающая тарелка

Работает процедура Музыка

Работает свет в окне

 

Теперь составим “пустую” программу полностью, с разбивкой пейзажа.

USES Graph,CRT;

VAR Device, Mode :Integer;

 

PROCEDURE Tree;

BEGIN WriteLn(‘Работает процедура Дерево’) END;

PROCEDURE House;

BEGIN WriteLn(‘Работает процедура Дом’) END;

PROCEDURE Landscape;

BEGIN

WriteLn(‘Работает процедура Пейзаж’);

WriteLn(‘Работает Горизонт процедуры Пейзаж’); { горизонт }

WriteLn(‘Работает Синева процедуры Пейзаж’); { синева }

WriteLn(‘Работает Луна процедуры Пейзаж’); { луна }

WriteLn(‘Работают Звезды процедуры Пейзаж’); { звезды }

Tree; { дерево }

Tree; { дерево }

Tree; { дерево }

House; { дом }

House; { дом }

WriteLn(‘Работает Трава процедуры Пейзаж’); { трава }

END;

PROCEDURE Music;

BEGIN WriteLn(‘Работает процедура Музыка’) END;

PROCEDURE Flying_Saucer;

BEGIN WriteLn(‘Работает процедура Летающая тарелка’) END;

 

BEGIN

Device:=0;

InitGraph(Device, Mode, ’<путь к гр.др.>’);

DirectVideo:=false;

Landscape; { рисование пейзажа }

WriteLn(‘Работает пауза 3 секунды’); { пауза три секунды }

Music; { музыка }

Flying_Saucer; { движение тарелки }

Music; { музыка }

WriteLn(‘Работает свет в окне’); { свет в окне }

ReadLn;

CloseGraph

END.

Пояснения: То новое, что появилось по сравнению с укороченным вариантом программы, я выделил жирным шрифтом. Обратите внимание, что раздел операторов совершенно не изменился. Изменилось только содержание процедуры Landscape и выше нее появились описания новых процедур, каждая из которых о себе рапортует. (Они описаны именно выше, согласно требованию из 8.2.) Порядок записи операторов внутри процедуры Landscape строго соответствует порядку рисования, который я выбрал ранее.

Если наша “пустая” программа верна, то результатом ее работы будет такая последовательность сообщений (новые сообщения я выделил жирным шрифтом):

Работает процедура Пейзаж

Работает Горизонт процедуры Пейзаж

Работает Синева процедуры Пейзаж

Работает Луна процедуры Пейзаж

Работают Звезды процедуры Пейзаж

Работает процедура Дерево

Работает процедура Дерево

Работает процедура Дерево

Работает процедура Дом

Работает процедура Дом

Работает Трава процедуры Пейзаж

Работает пауза 3 секунды

Работает процедура Музыка

Работает процедура Летающая тарелка

Работает процедура Музыка

Работает свет в окне

Скелет нашей программы готов. Теперь можно наращивать его мышцами операторов. Однако, сначала нужно в программе правильно использовать переменные величины.

Зачем переменные вместо чисел

Вот программа для задания 3 из 9.7 выше для бесконечного движения окружности влево-вправо. В ней этот принцип пока не соблюдается. USES Graph; VAR x, Device, Mode :Integer;

Записываем программу целиком

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

BEGIN

SetColor(White);

{Рисуем крону:}

Ellipse (100,400,0,360,15,30);

SetFillStyle(1,LightGreen);

FloodFill(100,400,White);

{Рисуем ствол:}

Rectangle (97,430,103,460);

SetFillStyle(1,Brown);

FloodFill(100,440,White);

END;

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

PROCEDURE Tree;

BEGIN

SetColor(White);

{Рисуем крону:}

Ellipse ( x_tree, y_tree, 0, 360,15,30);

SetFillStyle(1,LightGreen);

FloodFill(x_tree, y_tree, White);

{Рисуем ствол:}

Rectangle (x_tree - 3, y_tree + 30, x_tree + 3, y_tree + 60);

SetFillStyle(1,Brown);

FloodFill (x_tree, y_tree + 40, White);

END;

Теперь для того, чтобы дерево было нарисовано в нужном месте, нужно перед выполнением процедуры Tree присвоить координатам дерева нужные значения: x_tree := 100, y_tree:= 400. В программе процедура выполняется три раза, причем каждый раз перед ее выполнением координатам дерева присваиваются разные значения.

Аналогично составляем процедуру Дом. Сначала напишем ее без переменных:

PROCEDURE House;

BEGIN

SetColor(White);

{Рисуем стену:}

Rectangle (300,400,340,440);

SetFillStyle(1,LightBlue);

FloodFill (301,401,White);

{Рисуем окно:}

Rectangle (315,410,325,420);

SetFillStyle(1,DarkGray);

FloodFill (320,415, White);

{Рисуем крышу:}

Line(295,400,345,400);

Line(295,400,320,370);

Line(345,400,320,370);

SetFillStyle(1,Red);

FloodFill (320,399, White);

END;

Выберем левый верхний угол стены точкой начала отсчета. Ее координаты x_house:=300; y_house:=400. Окончательный вид процедуры House вы можете видеть в программе.

Вот полный текст программы:

USES Graph,CRT;

VARDevice, Mode, i : Integer;

y_goriz, x_tree, y_tree, x_house, y_house,

x_tar, y_tar, shirina_tar, visota_tar : Integer;

 

PROCEDURE Tree;

BEGIN

SetColor(White);

{Рисуем крону:}

Ellipse ( x_tree, y_tree, 0, 360, 15, 30);

SetFillStyle(1,LightGreen);

FloodFill(x_tree, y_tree, White);

{Рисуем ствол:}

Rectangle (x_tree - 3, y_tree + 30, x_tree + 3, y_tree + 60);

SetFillStyle(1,Brown);

FloodFill (x_tree, y_tree + 40, White);

END;

 

PROCEDURE House;

BEGIN

SetColor(White);

{Рисуем стену:}

Rectangle (x_house, y_house, x_house+40, y_house+40);

SetFillStyle(1,LightBlue);

FloodFill (x_house+1, y_house+1, White);

{Рисуем окно:}

Rectangle (x_house+15, y_house+10, x_house+25, y_house+20);

SetFillStyle(1,DarkGray);

FloodFill (x_house+20, y_house+15, White);

{Рисуем крышу:}

Line(x_house-5, y_house, x_house+45, y_house);

Line(x_house-5, y_house, x_house+20, y_house-30);

Line(x_house+45, y_house, x_house+20, y_house-30);

SetFillStyle(1,Red);

FloodFill (x_house+20, y_house-1, White);

END;

 

PROCEDURE Landscape;

BEGIN

{ горизонт: }

Line(0, y_goriz, 640, y_goriz);

{ синева: }

SetFillStyle(1,Blue);

FloodFill(10,10,White);

{ луна: }

SetColor(Yellow);

Circle(500,100,30);

SetFillStyle(1,Yellow);

FloodFill(500,100,Yellow);

{ звезды: }

for i:=1 to 100 do PutPixel (Random(640),Random(y_goriz),Random(16));

{Три дерева: }

x_tree:=100; y_tree:=400; Tree;

x_tree:=300; y_tree:=300; Tree;

x_tree:=550; y_tree:=380; Tree;

{Два дома: }

x_house:=300; y_house:=400; House;

x_house:=470; y_house:=300; House;

{ трава: }

SetFillStyle(1,Green);

FloodFill(10,470,White);

END;

 

PROCEDURE Music;

BEGIN

Sound(200);Delay(1000);

Sound(500);Delay(1000);

Sound(300);Delay(1000);

NoSound

END;

 

PROCEDURE Flying_Saucer;

BEGIN

{Задаем начальные координаты летающей тарелки и ее размеры.

Их не обязательно задавать в начале раздела операторов, так как они

больше никакой процедуре не нужны}

x_tar:=100; y_tar:=40; shirina_tar:=30; visota_tar:=15;

repeat {Цикл движения тарелки }

SetColor(White);

Ellipse (x_tar, y_tar, 0, 360, shirina_tar, visota_tar);

Delay(20); {Чтобы замедлить движение }

SetColor(Blue);

Ellipse (x_tar, y_tar, 0, 360, shirina_tar, visota_tar);

y_tar:=y_tar+1

until y_tar > y_goriz;

{Прорисовываем последний раз тарелку на горизонте: }

SetColor(White);

Ellipse (x_tar, y_tar, 0, 360, shirina_tar, visota_tar);

END;

 

BEGIN

Device:=0;

InitGraph(Device, Mode, '<путь к граф.драйверам>’);

y_goriz:=240;

Landscape; { рисуем пейзаж }

Delay(3000); { пауза три секунды }

Music; { музыка }

Flying_Saucer; { движение тарелки }

Music; { музыка }

SetFillStyle(1,Yellow); { свет в окне }

FloodFill (x_house+20, y_house+15, White); { свет в окне }

ReadLn;

CloseGraph

END.

Порядок описания переменных, процедур и других конструкций Паскаля

У нас переменные описаны в разделе VAR. А под применением переменной будем пока понимать ее упоминание в разделе операторов основной программы или… Посмотрим на нашу программу. Мы мудро поместили раздел VAR на самый верх… Те же рассуждения применимы и к процедурам и другим конструкциям. Так, описание процедуры Tree ни в коем случае нельзя…

Управление компьютером с клавиатуры. Функции ReadKey и KeyPressed

BEGIN repeat WriteLn(‘А нам все равно!’) until 2>3 END. Вы сидите перед компьютером и ждете, когда он закончит печатать свой текст. А… Только когда вы, удерживая нажатой клавише Ctrl, щелкнете по клавише Break, программа прервет свою работу.

BEGIN

Repeat

if KeyPressed then WriteLn(‘Хозяин нажал клавишу!’)

else WriteLn(‘А нам все равно!’)

until 2>3

END.

Выражение “if KeyPressed then” можно перевести как “если нажата клавиша, то”. Наткнувшись на это выражение, Паскаль проверяет, была ли нажата клавиша на клавиатуре. Когда вы запустите эту программу, она будет бесконечно печатать А нам все равно! Но как только вы щелкнете по какой-нибудь клавише, программа станет бесконечно печатать Хозяин нажал клавишу!

Если функция KeyPressed просто реагирует на то, была ли нажата какая-нибудь клавиша, то функция ReadKey сообщает, какая именно клавиша была нажата.

Вот программа, которая бесконечно печатает текст А нам все равно! и одновременно непрерывно ждет нажатия на клавиши, и как только клавиша нажата, однократно докладывает, была ли нажата клавиша “w” или другая клавиша, после чего продолжает печатать А нам все равно! Если мы захотим, чтобы программа закончила работу, мы должны нажать на клавишу “q”.

USES CRT;

VAR klavisha : Char;

BEGIN

Repeat

Delay (1000); {иначе программа печатает слишком быстро}

WriteLn(‘А нам все равно!’);

if KeyPressed then begin

klavisha:= ReadKey;

if klavisha=’w’ then WriteLn(‘Нажата клавиша w’)

else WriteLn(‘Нажата другая клавиша’)

end{if}

until klavisha=’q’

END.

Программа доберется до строки klavisha:= ReadKey только в случае, если будет нажата какая-нибудь клавиша. Функция ReadKey определяет, какой символ был на нажатой клавише, и присваивает его значение переменной, которую мы придумали - klavisha. С этого момента вы можете как хотите анализировать эту переменную и в зависимости от ее значения управлять работой компьютера.

Наша программа будет бесконечно печатать А нам все равно!, а при каждом нажатии на клавишу будет однократно сообщать Нажата клавиша w или Нажата другая клавиша. Почему однократно, а не бесконечно? Грубо это можно объяснить тем, что после выполнения функции ReadKey Паскаль “забывает”, что на клавиатуре была нажата клавиша.

Вы спросите, а зачем здесь вообще нужна строка if KeyPressed then? Дело в том, что если перед выполнением функции ReadKey клавишу на клавиатуре не нажать, то функция ReadKey останавливает программу и заставляет ее ждать нажатия на клавишу, а после нажатия программа продолжает работу. Если вам в вашей программе паузы не нужны, то вам придется использовать KeyPressed.

Функция ReadKey напоминает процедуру ReadLn. Однако у нее есть интересное отличие: при вводе символов по процедуре ReadLn они появляются на экране, а при вводе символа по функции ReadKey - нет. Благодаря этому свойству, с помощью ReadKey можно организовать “секретный ввод” информации в компьютер - человек, стоящий у вас за спиной и видящий экран монитора, но не видящий ваших пальцев, никогда не догадается, на какие клавиши вы нажимаете.

Подробнее о механизме действия ReadKey и KeyPressed см. в следующем параграфе.

Задача “Пароль на программу”.

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

Пусть ваш пароль -typ. Тогда для решения задачи вам достаточно вставить в начало вашей программы следующий фрагмент:

WriteLn(‘Введите, пожалуйста, пароль’);

Simvol1:= ReadKey;

Simvol2:= ReadKey;

Simvol3:= ReadKey;

if NOT ((Simvol1=’t’) AND (Simvol2=’y’) AND (Simvol3=’p’)) then Halt;

{Продолжение программы}

Вы скажете: Кто угодно перед запуском моей программы посмотрит в ее текст и сразу же увидит пароль. Совершенно верно. Чтобы текст программы не был виден, преобразуйте ее в исполнимый файл с расширением exe (см. часть IV).

Задание 96 “Светофор”: Нарисуйте светофор: прямоугольник и три окружности. При нажатии нужной клавиши светофор должен загораться нужным светом.

Задание 97 “Зенитка”: Вверху справа налево медленно движется вражеский самолет (эллипс). В подходящий момент вы нажатием любой клавиши запускаете снизу вверх зенитный снаряд (другой эллипс).

Буфер клавиатуры

Компьютер работает с клавиатурой сложнее, чем нам кажется. Причина сложности вот в чем. Предположим, вы играете в игру, где с клавиатуры управляете… Чтобы исправить ситуацию, нужно дать компьютеру возможность в случае занятости… На клавиши пока не нажимали:

Begin

инициализация графического режима;

DirectVideo:=false; {Чтобы работал WriteLn }

NACHALO {Вот такой короткий раздел операторов.}

End.

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

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

 

Улучшение. Если у всех кораблей будет одинаковая скорость, то попадать будет слишком просто, а значит и играть неинтересно. Сделайте скорость кораблей случайной. Конечно, не совсем уж (скажем, в условных единицах скорости диапазон от 0 до 10 – это слишком), а в пределах разумного (скажем, от 4 до 8 – это нормально). Причем не нужно менять скорость одного и того же корабля в процессе движения. Пусть она остается постоянной, а то все будет зависеть не от мастерства, а от везения. Различаются скорости только разных кораблей.

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

 

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

 

Мы с вами закончили первый из двух циклов знакомства с Паскалем. Если вам удались «Торпедная атака» или «Графический редактор» и они у вас работают не хуже, чем указано в задании, то у вас должна появиться уверенность, что теперь, умело разбивая программы на небольшие процедуры, вы можете создавать программы любой сложности, а значит цель этого цикла достигнута. Я вас поздравляю - вам присваивается звание “Программист-любитель III ранга”!

 

 

Часть III. Программирование на Паскале – второй уровень

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

Эта часть посвящена тому, чтобы

· Расширить ваши знания о возможностях Паскаля

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

 

Начнем с наведения порядка в наших знаниях о Паскале.

 

 

Глава 11. Алфавит и ключевые слова Паскаля

Алфавит

В Паскале тоже есть свой алфавит - четкий набор символов, которые вы имеете право употреблять в программе. Ни одного другого символа употреблять…   Вот алфавит Паскаля:

Ключевые слова

absolute AND array

Использование пробела

· Пробелызапрещены внутри имен и ключевых слов.

· Пробелы обязательны между именами и ключевыми словами (если они находятся в одной строке).

· В остальных случаях пробелы несущественны и могут ставиться произвольно.

· Там, где допускается один пробел, допускается и сколько угодно.

· Вместо нажатия на клавишу пробела можно нажимать на клавишу ввода.

 

Глава 12. Работа с разными типами данных Паскаля

Список типов

Каждая переменная величина в Паскале должна принадлежать какому-нибудь типу: Integer, Char, String и т.п. Вот список практически всех типов, многие из которых нам еще предстоит пройти. Здесь не учтены только так называемые процедурные типы, которые в этой книге освещаться не будут.

 

Простые типы

Числовые типы

Целочисленные типы

Byte

ShortInt

Word

Integer

LongInt

Вещественные типы

Real

Single (при наличии или эмуляции матем. сопроцессора)

Double (при наличии или эмуляции матем. сопроцессора)

Extended (при наличии или эмуляции матем. сопроцессора)

Comp (при наличии или эмуляции матем. сопроцессора)

Символьный тип

Char

Логический тип

Boolean

Перечислимый тип

Ограниченный тип (диапазон)

 

Сложные (структурированные) типы(строятся из простых):

Массивы array

Записи record

Множества set

Строки String

Файлы

Текстовые файлы

Text

Типизированные файлы

File of …

Бестиповые файлы

File

ОбъектыObject

Ссылки:

Ссылки

Адресный тип

    Комментарии к списку типов

Числовые типы

Зачем нужны Byte и ShortInt, если есть Integer? Они занимают меньше места в памяти. Если, например, ваша переменная по смыслу задачи обозначает…   Вещественные типыпозволяют переменной принимать значения вещественных чисел согласно следующей таблице: …

BEGIN

a:=55555555555.1; b:=55555555555.0;

y:=a-b;

WriteLn (y :30:3)

END.

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

Массивы

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

Переменные с индексами

x1 x2 b8 yi yi-6 zij zi+1j а читаются так: икс первое, икс второе, бэ восьмое, игрек итое, игрек и минус… X[1] X[2] B[8] Y[i] Y[i-6] Z[i,j] Z[i+1,j]

Одномерные массивы

Рассмотрим на простом примере, как Паскаль управляется с массивами. Предположим, в зоопарке живут три удава. Известна длина каждого удава в… Обозначим длину первого удава - dlina[1], второго - dlina[2], третьего -… VAR dlina : array [1..3] ofInteger

BEGIN

dlina[1]:=500;

dlina[2]:=400;

dlina[3]:=600;

{В этот момент в трех ячейках памяти уже находятся числа

и с ними можно выполнять арифметические действия}

summa:= dlina[1]+dlina[2]+dlina[3];

WriteLn(summa)

END.

Если смысл написанного выше вам неясен, запустите отладочный пошаговый режим выполнения программы, заставив Паскаль показывать вам текущие значения dlina[1], dlina[2], dlina[3], summa.

Теперь запишем ту же программу в предположении, что длины удавов заранее неизвестны и мы их вводим при помощи ReadLn:

VAR dlina :array [1..3] of Integer;

summa :Integer;

BEGIN

ReadLn (dlina[1],dlina[2],dlina[3]);

summa:= dlina[1]+dlina[2]+dlina[3];

WriteLn(summa)

END.

Теперь решим ту же задачу в предположении, что удавов не три, а тысяча:

VAR dlina :array [1..1000] of Integer;

summa, i :Integer;

BEGIN

{Вводим длины тысячи удавов, хоть это и утомительно:}

for i:=1 to 1000 do ReadLn (dlina[i]);

{Здесь на первом выполнении цикла i=1 и поэтому компьютер выполняет ReadLn(dlina[1]),

на втором – i=2 и поэтому компьютер выполняет ReadLn(dlina[2]) и т.д.}

 

{Определяем суммарную длину тысячи удавов:}

summa:= 0;

for i:=1 to 1000 do summa:=summa+dlina[i]);

WriteLn(summa)

END.

Решим еще одну задачу. Дан ряд из 10 произвольных чисел: a[1], a[2], ... , a[10]. Подсчитать и напечатать суммы троек стоящих рядом чисел: a[1]+a[2]+a[3], a[2]+a[3]+a[4], a[3]+a[4]+a[5], ...... , a[8]+a[9]+a[10].

VAR a :array [1..10] of Integer;

i :Integer;

BEGIN

for i:=1 to 10 do ReadLn (a[i]);

for i:=1 to 8 do WriteLn ( a[i]+ a[i+1]+ a[i+2] )

END.

 

Задание 103:. Напишите программу вычисления среднегодовой температуры (Для проверки в компьютере годом можно считать неделю).

Задание 104:. Подсчитайте количество морозных дней (когда температура ниже -20 град.).

Задание 105:. Каким по порядку идет самый морозный день?

Задание 106:. Вычислить и распечатать первые тридцать чисел Фибоначчи.

12.3.3. Двумерные массивы

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

  1-й день 2-й день 3-й день 4-й день
Метеостанция 1 -8 -14 -19 -18
Метеостанция 2
Метеостанция 3

Требуется:

1) Распечатать показания термометров всех метеостанций за 2-й день

2) Определить среднюю температуру на третьей метеостанции

3) Распечатать всю таблицу

4) Распечатать, в какие дни и на каких метеостанциях температура была в диапазоне 24-26 градусов тепла

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

t[1,1] t[1,2] t[1,3] t[1,4]

t[2,1] t[2,2] t[2,3] t[2,4]

t[3,1] t[3,2] t[3,3] t[3,4]

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

Программа:

{В памяти отводим массив из 3*4=12 ячеек под значения типа Integer индексированной переменной t. Будем называть его двумерным массивом:}

 

VAR t :array [1..3, 1..4] ofInteger;

s,i,j :Integer;

BEGIN {Зададим значения элементов массива примитивным присваиванием:}

t[1,1]:=-8; t[1,2]:=-14; t[1,3]:=-19; t[1,4]:=-18;

t[2,1]:=25; t[2,2]:= 28; t[2,3]:= 26; t[2,4]:= 20;

t[3,1]:=11; t[3,2]:= 18; t[3,3]:= 20; t[3,4]:= 25;

{А теперь распечатаем второй столбец массива:}

for i:=1 to 3 do WriteLn(t[i,2]);

{Определим среднее значение элементов третьей строки:}

i:=3;

s:=0;

for j:=1 to 4 do s:=s+t[i,j];

WriteLn(s/4 :10:3);

{Распечатаем всю таблицу:}

for i:=1 to 3 do for j:=1 to 4 do WriteLn (t[i,j]);

{Распечатаем станции и дни с температурой 24-26 градусов:}

for i:=1 to 3 do for j:=1 to 4 do

if(t[i,j]>=24) AND (t[i,j]<=26) then WriteLn ('Станция ',i,' день ',j)

END.

Задание 107: Вычислить разницу между максимальной и минимальной температурой во всей таблице.

Какие бывают массивы

array [1..10] of Integer -одномерный массив 10 ячеек array [1..10, 1..5] of Integer -двумерный массив 50 ячеек array [1..10, 1..5, 1..2] of Integer -трехмерный массив 100 ячеек

Определения констант

Приведем программу вычисления среднегодовой температуры для задания 1 из 12.3.

VAR s,i:Integer; t:array [1..365] of Integer;

BEGIN

for i:=1 to 365 do ReadLn(t[i]);

s:=0;

for i:=1 to 365 do s:=s+t[i];

WriteLn(s/365)

END.

Пусть нам потребовалось переделать эту программу на вычисление средней недельной температуры. Для этого достаточно везде в тексте программы число (константу) 365 заменить на число (константу) 7. В больших программах одна и та же константа может встречаться десятки раз и подобный процесс может потребовать значительного расхода времени. В 10.4 мы уже сталкивались с такой ситуацией. Там мы нашли выход в том, что вместо константы записывали переменную величину. Но в нашем случае этого не получится, так как Паскаль запрещает задавать границу в описании массива переменной величиной. В таких случаях поступают следующим образом. Константе придумывают имя (как переменной), например k, и в специальном разделе constей задается значение. Вот наша программа с использованием константы k:

CONST k =365; {Обратите внимание, что в определении вместо := стоит = }

VAR s,i :Integer;

t :array [1..k] of Integer;

BEGIN

for i:=1 to k do ReadLn(t[i]);

s:=0;

for i:=1 to k do s:=s+t[i];

WriteLn(s/k)

END.

В приведенном виде программа стала универсальной. Теперь для ее переделки под средненедельную температуру достаточно в одном месте поменять определение k=365 на k=7.

Значению константы запрещено меняться в процессе выполнения программы, то есть запрещены операторы вида k:=30 и ReadLn(k). Паскаль присматривает за этим.

Тип константы указывать нельзя[10]. Паскаль сам догадается о типе по записи:

CONST n =800; {тип целочисленный}

e =2.7; {тип Real}

bukva =’ж’; {тип Char}

Slash =’/’; {тип Char}

slovo =’хорошо’; {тип String}

OK =true; {тип Boolean}

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

Типизированные константы

CONST n :Integer =800; e :Real =2.7; Вот как запишется программа для вычисления средней недельной температуры из 12.4, если массив t описать как…

BEGIN

s:=0;

for i:=1 to k do s:=s+t[i];

WriteLn(s/k)

END.

Здесь в круглых скобках задается список начальных значений переменной t, а именно: t[1] равно -14, t[2] равно -12 и т.д. В разделе операторов эти значения можно менять.

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

Const k =3; n=4;

t :array [1..k,1..n] of Integer = (( -8,-14,-19,-18),

( 25, 28, 26, 20),

( 11, 18, 20, 25));

.......

Обратите внимание на расстановку скобок.

Придумываем типы данных

Запись TYPE bukva = Char означает: ТИП bukva "равен" (эквивалентен) типу Char, то есть мы просто придумали типу Char еще одно название "bukva". Теперь все равно, как записать:

Логический тип Boolean

Говорят, что логическое выражение 3>2 имеет значение “истина” (по-английскиtrue- “тру”), а логическое выражение i<=0 имеет значение “ложь”… Внутренняя идеология построения языка Паскаль требует определить новый тип… Слова true и false являются логическими константамии их можно употреблять в логических выражениях или вместо них.…

Перечислимые типы

VAR Month : (january, february, march, april, may, june, july, august, september, october, november, december) Она означает, что переменная Month может принимать только одно из… Эти значения ни в коем случае не являются строками. Так, нельзя записать Month:= ‘may’. Кроме того, их нельзя вывести…

Ограниченный тип (диапазон)

Задача: Поезд отправляется в путь в 22 часа и находится в пути 10 часов. Во сколько он прибывает на место назначения?

 

Ошибочная программа:

VAR Otpravlenie, Pribitie :Byte;

BEGIN

Otpravlenie:=22;

Pribitie:=Otpravlenie+10;

WriteLn(Pribitie)

END.

Эта программа вместо ответа “8” напечатает ответ “32” и ошибки не заметит. Паскаль не знает, что имеют смысл только те значения переменной Pribitie, которые находятся в диапазоне от 0 до 24. Это должен был знать программист, но он тоже не обратил на это внимания. Хотелось бы, чтобы Паскаль вместо выдачи неправильного ответа напоминал забывчивым программистам, что переменная вышла из имеющего смысл диапазона. Для этого программист должен иметь возможность этот диапазон Паскалю указать. Такую возможность дает применение диапазонов(ограниченных типов).

Вот программа, обнаруживающая собственную ошибку:

VAR Otpravlenie, Pribitie : 0..24;

BEGIN

Otpravlenie:=22;

Pribitie:=Otpravlenie+10;

WriteLn(Pribitie)

END.

Конструкция VAR Otpravlenie, Pribitie : 0..24 означает, что переменные Otpravlenie и Pribitie имеют право принимать значения целых чисел в диапазоне от 0 до 24.

Паскаль будет обнаруживать выход за диапазон только в том случае, когда вы установите флажок (крестик) в Options®Compiler…®Compiler Options®Runtime Errors в положение Range Checking (см. часть IV – «Обзор популярных команд меню»).

Диапазон можно задавать для любого порядкового типа, например:

VAR Month :(january, february, march, april, may, june, july, august, september, october, november, december);

Spring :march..may;

Autumn :september..november;

tsifra :0..9;

Zaglavnie:’А’..’Я’

Диапазон является одним из видов порядковых типов.

Задание 108: Известны дата и время (месяц, день, час, минута) отплытия теплохода летом этого года из Москвы в Астрахань. Известно время в пути (в днях, часах и минутах). Оно не превышает 20 суток. Определить дату и время прибытия теплохода в Астрахань. Использовать диапазоны.

Вариант 1: Для простоты предположим, что путешествие начинается между 1 и 10 июня.

Вариант 2. Путешествие начинается в любой день лета. Определите еще и дни недели отправления и прибытия, если известно, какой день недели был 1 июня.

Действия над порядковыми типами

Как видите, сюда не входят вещественные типы и String. Порядковый тип - это такой тип, все значения которого можно перечислить,… Любой порядковый тип имеет внутреннюю нумерацию. Пусть мы задали тип TYPE weekday = (mon,tu,we,th,fr) . Внутри…

Символьный тип Char. Работа с символами

Для работы с символами вам достаточно кроме вышеизложенных знать еще одну функцию - Chr. Выполнив оператор c1:=Chr(69), Паскаль присваивает c1… Задание 112: Угадайте, что напечатает компьютер, выполнив оператор… Задание 113: Распечатайте часть таблицы ASCII, конкретнее - символы, соответствующие кодам 32-255. Обратите…

Строковый тип String. Работа со строками

Как можно сэкономить память, работая со строками? Если мы напишем VAR a:String, то Паскаль отведет под символы строковой переменной a 255 байтов.… Теперь разберем функции для работы над строками. Исходные данные … Процедура Str может вам понадобиться, например, вот в каком случае. Модуль Graph имеет возможность печатать на экране…

Записи

На вооружении флота 100 подводных лодок. Адмиралу часто приходится решать задачи такого типа: 1)перечислить названия лодок, имеющих скорость, превышающую скорость вражеской подводной лодки Шредер; 2)подсчитать, сколько лодок имеют на вооружении больше 10 торпед; и т.д. Чтобы ускорить решение таких задач, адмирал приказал занести в компьютер сведения обо всех лодках, включая вражеские лодки Шредер и Рокстеди, а именно: их названия, скорость и число торпед, находящихся на вооружении.

Отвести место в оперативной памяти под указанную информацию о 102 лодках можно двумя способами: 1)с помощью массивов, 2)с помощью записей.

Рассмотрим программу, использующую первый способ. В каждом массиве будет 102 элемента, причем элементы 101 и 102 отведены под лодки противника.

VAR nazvanie :array[1..102] of String; {Место под 102 названия}
skorost :array[1..102] of Real; {Место под 102 скорости}
torped :array[1..102] of Byte; {Место под 102 количества торпед}
i :Integer;
BEGIN
{Здесь каким-нибудь способом заносим в отведенное место всю информацию,
например, присвоением - nazvanie[1]:='Щука'.... или загрузкой из файла}
{А теперь решим первую из двух задач:}
for i:=1 to 100 do if skorost[i] > skorost [101] then WriteLn(nazvanie[i])
END.

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

ЯЧЕЙКИ ДЛЯ ИНФОРМАЦИИ ИНФОРМАЦИЯ
nazvanie[1] Щука
nazvanie[2] Дельфин
........... ........
nazvanie[101] Шредер
nazvanie[102] Рокстеди
skorost[1]
skorost[2]
........... ........
skorost[101]
skorost[102]
torped[1]
torped[2]
........... ........
torped[101]
torped[102]
i ?

Вы видите, что данные об одной лодке разбросаны по памяти.

Рассмотрим второй способ. Иногда бывает удобно, чтобы данные, касающиеся одной лодки, хранились в памяти рядом, вот так:

ЯЧЕЙКИ ДЛЯ ИНФОРМАЦИИ ИНФОРМАЦИЯ
lodka[1].nazvanie Щука
lodka[1].skorost
lodka[1].torped
lodka[2].nazvanie Дельфин
lodka[2].skorost
lodka[2].torped
. . . . . . . . . . . . . . . . . . . . . . .
vr .nazvanie Шредер
vr .skorost
vr .torped
prot .nazvanie Рокстеди
prot .skorost
prot .torped

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

Сами по себе массивы не позволяют хранить информацию в таком порядке, для этого нужно использовать записи. Запись- это набор данных (полей) различных типов, касающийся одного объекта. Например, запись, касающаяся нашей первой лодки, это набор трех полей: название - Щука (тип String), скорость - 26 (тип Real), количество торпед - 6 (тип Byte). Точка отделяет имя поля от обозначения записи, содержащей это поле.

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

Прежде чем отводить место в памяти под всю информацию, объясним Паскалю, из чего состоит одна запись, то есть опишем ее, задав специальный тип записиrecordи придумав ему имя, скажем, podlodka:

TYPE podlodka = record
nazvanie :String;
skorost :Real;
torped :Byte;
end;
..........

Тип определен, но место в памяти пока не отведено. Здесь нам, хочешь-не хочешь, придется воспользоваться массивом. При помощи VAR отведем место под массив из 100 записей для наших подлодок и отдельное место под две записи для вражеских. Массиву придумаем имя lodka.

VAR lodka :array[1..100] of podlodka;
vr,prot :podlodka; {Записи для двух вражеских лодок}
i :Integer;

..........................

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

Вот программа целиком:

TYPE podlodka = record
nazvanie :String;
skorost :Real;
torped :Byte;
end;
VAR lodka :array[1..100] of podlodka;
vr,prot :podlodka;
i :Integer;

BEGIN {Здесь задаем значения полям всех записей. Конечно, удобнее это делать
при помощи типизированных констант (см.следующую программу) или
файлов данных, но я использую простое присвоение:}
lodka[1].nazvanie :='Щука';
lodka[1].skorost :=26;
. . . . . . . .
prot.torped :=22;
{А теперь решаем первую задачу:}
for i:=1 to 100 do if lodka[i].skorost > vr.skorost then WriteLn (lodka[i].nazvanie)
END.

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

 

Теперь запишем нашу программу с использованием типизированных констант, для краткости ограничив наш флот тремя подводными лодками:

TYPE podlodka = record
nazvanie :String;
skorost :Real;
torped :Byte;
end;
CONST lodka : array[1..3] of podlodka =
((nazvanie:'Щука'; skorost:26; torped: 6),
(nazvanie:'Дельфин'; skorost:14; torped:10),
(nazvanie:'Леонардо'; skorost:28; torped:11));
vr : podlodka =
(nazvanie:'Шредер'; skorost:20; torped:15);
prot : podlodka =
(nazvanie:'Рокстеди'; skorost:18; torped:22);
VAR i : Integer;
BEGIN
for i:=1 to 3 do if lodka[i].skorost > vr.skorost then WriteLn(lodka[i].nazvanie);
END.

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

Задание 116: Создайте базу данных о своих родственниках. О каждом родственнике должно быть известно:

· Имя

· Год рождения

· Цвет глаз

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

 

1) Распечатать ваш возраст и цвет глаз

2) Ответить на вопрос – правда ли, что ваш дядя старше тети.

 

Задание 117: Создайте базу данных о своих однокашниках. О каждом однокашнике должно быть известно:

· Фамилия

· Имя

· Пол

· Год рождения

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

 

1) Вычислить средний возраст ваших однокашников

2) Определить, кого среди них больше – дам или кавалеров

3) Ответить на вопрос – есть ли в вашей базе тезки (это нелегко).

 

Множества

Если в множестве элемент повторяется, то считается, что он входит туда только один раз. Например, множества [2,5,2] и [2,5] эквивалентны. Порядок элементов в множестве не играет роли. Множества [2,5] и [5,2]… В описании тип множества задается словами set of. Например, конструкция

Расположение информации в оперативной памяти. Адреса

Раньше я уподоблял оперативную память тетрадному листу в клеточку. Каждая клетка - байт. Теперь я уподоблю ее многоэтажному небоскребу. Каждый этаж… Как и положено этажам, байты имеют номера. Эти номера называются адресами.… Во время выполнения вашей программы, написанной на Паскале, в памяти находится самая разная информация. То, что…

Ссылки

Пусть вы хотите использовать следующий массив:

VAR a: array[1..200, 1..200] of Integer;

Давайте подсчитаем, сколько байтов в памяти займет этот массив. Одно число типа Integer занимает 2 байта. Получаем 200*200*2 = 80000 байтов. В сегменте данных массив не умещается, значит привычным образом работать с ним нельзя. Использование ссылок позволяет разместить его в куче(по английски - heap), имеющей гораздо больший размер.

Я привел лишь один из доводов в пользу применения ссылок. А поближе познакомимся мы со ссылками на простом примере. Задача: Вычислить и напечатать y=a+b, где a и b - целые числа 2 и 3. Вот традиционная программа для решения этой задачи:

VAR a, b, y : Integer;
BEGIN
a:=2; b:=3;
y:=a+b;
WriteLn (y)
END.

А теперь потребуем, чтобы число 2 и результат 5 размещались в куче (впрочем, строго говоря, не обязательно в куче). Вот программа со ссылками:

VAR b : Integer;
a,y : ^Integer;
BEGIN
New(a); New(y);
a^ := 2; b:=3;
y^ := a^ + b;
WriteLn (y^)
END.

Пояснения: Все, что выше BEGIN, выполняется на этапе компиляции: Строка a,y:^Integer приказывает отвести в памяти в сегменте данных две ячейки, но не для будущих чисел 2 и 5, а для адресов ячеек из кучи, в которых эти самые 2 и 5 предполагается хранить. Итак, будущие значения a и y - не числа 2 и 5, а адресаячеек для этих чисел или, по-другому, ссылкина ячейки для этих чисел. Пока же адреса эти не определены.

Все, что ниже BEGIN, выполняется на этапе выполнения программы: При помощи обращений к процедуре New ( New(a) и New(y) ) мы идем дальше и придаем переменным a и y значения конкретных адресов памяти, то есть отводим для будущих чисел 2 и 5 конкретное место в памяти. Таким образом, мы сталкиваемся с новым для нас явлением - место в памяти отводится не на этапе компиляции, а на этапе выполнения программы. В Паскале имеются средства и освобождать это место на этапе выполнения программы (процедура Dispose, на которой я не буду останавливаться). Называется все это динамическим распределением памятии сулит выгоды экономным создателям программ, использующим большие объемы разных данных в разные моменты выполнения программы.

Оператор a^:= 2 идет еще дальше и посылает в ячейку, адрес которой находится в ячейке a, число 2. Обозначается такая ячейка - a^. Если бы мне вздумалось написать a:=2, это бы значило, что я хочу послать в ячейку a адрес равный двум, что вполне возможно, но синтаксически неверно, так как численные значения адресов задаются по-другому.

Смысл следующих двух операторов очевиден.

Подведем итог. Значок ^, поставленный перед типом (например, ^Integer), означает новый ссылочный тип, значения которого обязаны быть адресами переменной (или ссылками на переменную) исходного типа (в нашем случае Integer).

Значок ^, поставленный после переменной ссылочного типа (например, a^), означает переменную, на которую ссылается исходная переменная (в нашем случае исходная переменная a).

 

Вот еще некоторые возможные операции со ссылками (без особых пояснений):

TYPE D = array[1..10] of Real;
DP = ^D;
Int = ^Integer;
VAR i, j : Int; { i, j - адреса целых чисел}
m : DP; { m - адрес первой ячейки массива из 10 вещ. чисел}
BEGIN
New(i); New(j); New(m);
i^:=4;
j^:=3;
j:=i; {Теперь j и i содержат адреса одного и того же числа - 4}
WriteLn(j^); {поэтому будет напечатано число 4}
m^[9]:=300 {Девятый элемент массива становится равным числу 300}
END.

Вернемся к задаче о размещении большого массива. Поскольку Паскаль вслед за MS-DOS запрещает не только описывать, но также, естественно, и ссылаться на структуру, объемом превышающую 64К, то ссылаться сразу на весь двумерный массив не выйдет и поэтому программа получится непростой:

TYPE a = array[1..200] of Integer;
ap = ^a;
a2 = array[1..200] of ap;
VAR x : a2; {x - массив из 200 адресов (каждый - ссылка на строку из 200 элементов

исходного массива)}


BEGIN
for i:=1 to 200 do New(x[i]); {Место для массива отведено}
............
x[128]^[35]:=800; {Присвоено значение элементу массива}
.............
END.

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

Глава 13. Процедуры и функции с параметрами

Процедуры с параметрами

Воспользуемся нотами третьей октавы: USES CRT; PROCEDURE doo; BEGIN Sound(523); Delay(2000); NoSound END;

BEGIN

mi; doo; mi; doo; fa; mi; re; sol; sol; la; si; doo; doo; doo

END.

Все процедуры в нашей программе всегда делают одно и то же. Например, процедура doo всегда издает звук частоты 523 герца и продолжительности 200 мс. Происходит это потому, что в описании процедур мы использовали не переменные величины, а константы.

В реальной музыке ноты принадлежат разным октавам и имеют разную длительность. Чтобы получить ноту четвертой октавы, достаточно умножить частоту одноименной ноты третьей октавы на 2. Например, нота ре четвертой октавы имеет частоту 587*2=1174 гц. Естественно, все ноты четвертой октавы звучат выше нот третьей октавы. Пятая октава получается из четвертой так же, как четвертая из третьей и звучит еще выше. Ноты второй октавы, наоборот, получаются из нот третьей октавы делением частоты на 2.

Поставим задачу - создать более универсальную процедуру. Чтобы заставить ноту звучать по-разному, используем переменные величины. Здесь мы используем ту же самую идею, которую мы использовали в процедуре House из Глава 10, она рисовала дом в разных местах экрана в зависимости от значений переменных величин, задающих его координаты. Для простоты ограничимся пока одной нотой ре и двумя октавами - третьей и четвертой. Длительность пусть будет любая. Пусть программа должна воспроизвести три подряд ноты ре: сначала третья октава одна секунда, затем четвертая октава одна секунда и затем третья октава три секунды.

USES CRT;

VAR octava : Byte;

dlit : Word;

PROCEDURE re; BEGIN

if octava = 3 then Sound(587) else Sound(1174);

Delay(dlit);

NoSound END;

BEGIN

octava:=3; dlit:=1000; re; octava:=4; dlit:=1000; re; octava:=3; dlit:=2000; re

END.

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

BEGIN

re(3,1000); re(4,1000); re(3,2000)

END.

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

USES CRT;

PROCEDURE re (octava : Byte; dlit: Word); BEGIN

if octava = 3 then Sound(587) else Sound(1174);

Delay(dlit);

NoSound END;

BEGIN

re(3,1000); re(4,1000); re(3,2000)

END.

Пояснения: Эта программа похожа на предыдущую, но имеется несколько отличий. Строка

Procedure re (octava : Byte; dlit: Word)

называется заголовком процедуры. Здесь после имени процедуры - re - ставятся скобки и внутри них описываются так называемые формальные параметрыпроцедуры. Здесь их два: octava и dlit. Поскольку они описаны в заголовке, пропадает необходимость в разделе VAR.

В записи re(3,1000) числа 3 и 1000 - так называемые фактические параметрыпроцедуры, их порядок и тип должен соответствовать формальным параметрам.

Когда во время выполнения программы Паскаль натыкается на re(4,1000), он присваивает переменной octava значение 4, переменной dlit - значение 1000 (то есть, присваивает формальным параметрам значения фактических параметров) и затем переходит к выполнению тела процедуры re.

 

Усложним задачу. Создадим универсальную процедуру nota, параметрами которой будут название ноты, октава и длительность. Учтем, что длительность ноты в музыке задается в так называемых долях. Доли бывают: 1 - целая нота, 1/2 - половинка длительности, 1/4 - четвертушка и т.д. Пусть целая нота звучит 1 секунду. Вызывать процедуру nota можно было бы так: nota(re,5,8) - это означает, что мы хотим, чтобы прозвучала нота re пятой октавы длительности 1/8.

 

Вот запись программы:

 

USES CRT;

TYPE Nota_type = (doo, doo_diez, re, re_diez, mi, fa, fa_diez, sol, sol_diez, la, la_diez, si);

PROCEDURE Nota(Nazvanie:Nota_type; Oktava,Dolya:Byte); {Здесь параметр Dolya - знаменатель доли}

VAR Hz:Word; {Внутри процедуры можно описывать свои переменные (в данном примере это Hz).

Они называются локальными. Подробнее о них - в 13.3}

BEGIN

{Объясним Паскалю частоту нужных нам нот третьей октавы}

case Nazvanie of

doo : Hz:=523;

re : Hz:=587;

sol : Hz:=784;

la : Hz:=880;

la_diez : Hz:=932;

end;

{Теперь меняем частоту в зависимости от октавы}

case Oktava of

1 : Hz:=Hz div 4; {Используем целочисленное деление,так как стандартная}

2 : Hz:=Hz div 2; {процедура Sound требует задавать частоту целым}

3 : Hz:=Hz; {числом герц}

4 : Hz:=Hz*2;

5 : Hz:=Hz*4;

6 : Hz:=Hz*8;

else WriteLn('Такой октавы не знаю'); ReadLn; Halt

end;

 

Sound (Hz); {Включаем звук}

Delay(10000 div Dolya); {Задаем пpодолжительность звука}

NoSound;

Delay (50); {Небольшой промежуток тишины после каждой ноты}

END;

BEGIN

{Вот первые ноты из песни “Широка страна моя родная”:}

Nota(re,3,8); Nota(re,3,16); Nota(re,4,4); Nota(re,4,8); Nota(re,4,8); Nota(doo,4,8);

Nota(la_diez,3,8); Nota(la,3,8); Nota(sol,3,4); Nota(re,3,4)

END.

 

Фактические параметры могут быть любыми выражениями подходящего типа. Например, вместо Nota(re,3,8) можно было бы написать a:=3; Nota(re, a, 11-a).

Задание 119: В модуле Graph не хватает процедуры, которая рисовала бы треугольник. Создайте такую процедуру. Она должна рисовать примерно равносторонний треугольник вершиной вверх и иметь три параметра: положение треугольника на экране и размер.

Функции

Вы можете создавать собственные функции. Предположим, вам часто приходится вычислять периметры прямоугольников. Тогда вам было бы удобно иметь… FUNCTION perimetr(dlina,shirina:Word) : Integer; BEGIN perimetr:=2*(dlina+shirina) END;

BEGIN

WriteLn(perimetr(10,4)+ perimetr(20,30)+ perimetr(3,8));

END.

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

· В заголовке функции после скобок с формальными параметрами должен быть указан тип функции (у нас это Integer).

· Внутри описания функции между BEGIN и END ей хотя бы раз должно быть присвоено какое-нибудь значение (у нас это perimetr:=2*(dlina+shirina)).

 

Рассмотрим более сложный пример. Вспомним задачу из 12.3 о среднегодовой температуре, где исходными данными является массив из 365 значений температуры. Попробуем узнать, в январе (дни 1-31) или в декабре (дни 335-365) самый теплый день месяца был теплее. Мы можем предвидеть, что для вычисления понадобятся два похожих фрагмента программы, каждый длиной строчки по три-четыре. Чтобы не писать два раза похожие фрагменты, создадим функцию нахождения максимального элемента из заданного диапазона массива температур. Назовем ее max. Используя ее, мы можем в программе записать, например, так: u:=max(20,30), подразумевая, что переменной u должно быть присвоено значение максимального элемента массива температур, выбирая из элементов с 20-го по 30-й. Вот программа:

VAR t : array [1..365] of Integer; { t - массив температур за год}

FUNCTION max (perv,posledn:Word) :Integer;

VAR i,m :Integer;

BEGIN

m:=t[perv];

for i:=perv+1 to posledn do if t[i]>m then m:=t[i];

max:=m

END;

BEGIN

........ {Здесь присваиваем значения элементам массива температур}

if max(1,31)>max(335,365) then WriteLn(‘В январе’) else WriteLn(‘В декабре’);

END.

Задание 120: В Паскале не хватает функции для вычисления произвольной целой степени числа. Создайте функцию Power такого смысла: Power(2,3) должна иметь значение 23, то есть 8.

Задание 121: Если вы никак не можете смириться с системой координат графического режима, то напишите пару простеньких функций (например, с именами x и y), которые позволят вам считать, что отныне ось yнаправлена вверх, а центр координат расположен в центре экрана. Если вы правильно напишете эти функции, то, например, оператор Circle (x(310), y(230), 10) нарисует вам кружочек в правом верхнем углу экрана.

Подпрограммы. Локальные и глобальные переменные

  Деление переменных на локальные и глобальные является способом повышения… Исследуем взаимодействие подпрограмм в такой программе. Для этого рассмотрим глупую простую "сложную"…

Begin

x:=5;

B;

WriteLn(x);

End.

Очевидно, программа напечатает Результат равен 5.

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

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

VAR x,y : Integer;

PROCEDURE B; BEGIN x:=10*10; Write('Результат равен ') END;

Begin

x:=5;

B;

WriteLn(x);

END.

Очевидно, данная программа напечатала бы Результат равен 100.

 

Для защиты от таких ошибок руководитель проекта должен внимательно следить, чтобы разные подпрограммы не использовали переменных с одинаковыми именами. Но для больших программ этот контроль очень трудоемок и неудобен. Вместо этого в современных языках программирования разработан механизм локальных переменных. Локальная переменная- это переменная, описанная не в главной программе, а внутри подпрограммы. Если программист В знает, что его число 10*10 нигде, кроме как в процедуре В, не нужно, он описывает соответствующую переменную х внутри процедуры В, ничуть не заботясь, что переменные с таким же именем встречаются в других местах программы:

VAR x : Integer;

PROCEDURE B;

VAR x : Integer;

BEGIN x:=10*10; Write('Результат равен ') END;

Begin

x:=5;

B;

WriteLn(x);

END.

Данная программа напечатает Результат равен 5. Произойдет это вот по какой причине: Переменные, описанные внутри и снаружи подпрограммы, компилятор считает разными переменными, даже если они имеют одинаковые имена. Переменная х, описанная в программе, это совсем другая переменная, чем х, описанная в подпрограмме, и помещаются эти переменные в разных местах памяти. Поэтому и не могут друг друга испортить. Вы можете вообразить, что это переменные с разными именами xглоб и xлок.

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

Переменная, описанная в главной программе, называется глобальной переменной. Она видна отовсюду в программе и внутри подпрограмм и каждая подпрограмма программы может ее испортить. Но когда подпрограмма натыкается на переменную x, описанную внутри самой этой подпрограммы, то она работает только с ней и не трогает переменную x, описанную снаружи.

Рассмотрим еще один пример:

VAR x,z : Integer;

PROCEDURE B;

VAR x,y : Integer;

BEGIN

x:=20; y:=30; z:=40

END;

Begin

x:=1; z:=2;

B;

WriteLn(x,' ',z)

END.

Программа напечатает 1 40. Пояснение: Оператор WriteLn(x,z) находится снаружи процедуры В, и поэтому локальная переменная х=20, описанная внутри В, из него не видна. Зато прекрасно видна глобальная переменная х=1, которую он и печатает. Переменная же z не описана внутри В, поэтому она глобальна, и оператор z:=40 с полным правом меняет ее значение с 2 на 40.

Для полной ясности приведу порядок работы компьютера с этой программой:

1) В сегменте данных оперативной памяти компилятор отводит место под Х глобальное и Z глобальное.

2) Программа начинает выполняться с присвоения значений Х глобальное = 1 и Z глобальное = 2.

3) Вызывается процедура В. При этом в стеке оперативной памяти отводится место под Х локальное и У локальное.

4) Присваиваются значения Х локальное = 20, У локальное = 30 и Z глобальное = 40.

5) Программа выходит из процедуры В. При этом исчезают переменные Х локальное = 20 и У локальное = 30.

6) Компьютер печатает Х глобальное = 1 и Z глобальное = 40.

 

Формальные параметрыподпрограмм являются локальными переменными в этих подпрограммах. Сколько их ни меняй внутри подпрограммы – одноименные глобальные переменные не изменятся. Не изменятся также и фактические параметры. В этом смысле они «защищены», что значительно повышает надежность программ. (Это не относится к так называемым параметрам-переменным, о которых речь позже).

Массивы как параметры

Задача: Имеется два массива, по два числа в каждом. Напечатать сумму элементов каждого массива. Использовать функцию sum, единственным параметром… Программа: TYPE vector = array [1..2] of Integer;

BEGIN

a[1]:=10; a[2]:=20;

b[1]:=40; b[2]:=50;

WriteLn (sum(a),' ',sum(b));

END.

Начиная вычислять функцию sum(a), Паскаль подставляет в ячейки для элементов массива c значения элементов массива a. Начиная же вычислять функцию sum(b), Паскаль подставляет в ячейки для элементов массива c значения элементов массива b.

В заголовке функции неправильно было бы писать

function sum (c: array [1..2] of Integer):Integer.

Необходимо было сначала определить тип массива в разделе TYPE, а затем использовать это определение и в описании a и b, и в заголовке функции. Таково требование синтаксиса Паскаля.

Задание 122. В школе два класса. В каждом - 5 учеников. Каждый ученик получил отметку на экзамене по физике. Определить, какой из двух классов учится ровнее (будем считать, что ровнее учится тот класс, в котором разница между самой высокой и самой низкой отметкой меньше).

Указание: Создать функции min(c:vector), max(c:vector) и raznitsa(c:vector).

Параметры-значения и параметры-переменные

Многие процедуры не только рисуют или звучат, но и, подобно функциям, вычисляют что-нибудь полезное. Например, процедура B из следующей программы увеличивает глобальную переменную x на значение параметра y.

VAR x: Integer;

PROCEDURE B (y:Integer);

BEGIN x:=x+y END;

BEGIN

x:=1000;

B(1);

WriteLn(x)

END.

Будет напечатано число 1001.

Однако руководители проектов не любят, когда в подпрограммах встречаются имена глобальных переменных. Мало ли - руководителю придет в голову изменить имя глобальной переменной, и что тогда - переписывать все подпрограммы? Поэтому придумали использовать так называемые параметры-переменные. Вот та же программа с их использованием:

VAR x: Integer;

PROCEDURE B (y:Integer; var c:Integer);

BEGIN c:=c+y END;

BEGIN

x:=1000;

B(1, x);

WriteLn(x)

END.

Здесь y - хорошо знакомый нам параметр. Называется он параметр-значение. При начале выполнения подпрограммы для параметра-значения выделяется место в стеке и туда посылается значение соответствующего фактического параметра (1).

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

Вопрос: имеет ли смысл писать B(1, 1000)? Ответ: не имеет, так как подпрограмма не будет знать, какой переменной присваивать результат 1001. Естественно, Паскаль выдаст сообщение об ошибке.

 

Задание 123: На двух станциях (A и B) в течение года измерялась температура. Соответственно созданы два массива чисел длиной 365. Затем оказалось, что на станции A термометр все время показывал температуру на 2 градуса выше настоящей, а на станции B - на 3 градуса ниже. Написать процедуру с двумя параметрами, которая исправляет исходный массив. Один формальный параметр - величина поправки, другой - параметр-переменная - массив температур.

Индукция. Рекурсия. Стек

Все понятно. Однако, существует еще один, совершенно ужасный способ объяснения, что такое факториал. Вот он: “Факториал единицы равен 1. Факториал любого целого положительного числа N,… Если вам уже все ясно, значит вы - математический талант. Для нормальных людей поясню. Чтобы последнее предложение…

BEGIN

if N=1 then Factorial :=1;

if N>1 then Factorial :=N* Factorial(N-1)

END;

BEGIN

WriteLn(Factorial(3))

END.

Обратите внимание, что в программе нигде не употребляется оператор цикла. Вся соль программы в том, что функция Factorial вместо этого включает в себя вызов самой себя - Factorial(N-1).

 

Что же происходит в компьютере во время выполнения программы? Механизм происходящего в точности соответствует нашему рассуждению по рекурсии.

 

Все начинается с того, что Паскаль пробует выполнить строку WriteLn(Factorial(3)). Для этого он вызывает функцию Factorial. Выполнение подпрограммы начинается с того, что в стеке отводится место для всех формальных параметров и локальных переменных, а значит и для нашего формального параметра N. Затем фактический параметр 3 подставляется на место формального параметра N, то есть в стек в ячейку N посылается 3. Затем выполняется тело функции. Так как 3>1, то Паскаль пытается выполнить умножение 3* Factorial(3-1) и сталкивается с необходимостью знать значение функции Factorial(2), для чего вызывает ее, то есть отправляется ее выполнять, недовыполнив Factorial(3), но предварительно запомнив, куда возвращаться.

 

Спускаюсь на ступеньку ниже. В соседнем месте стека отводится место для N. Это уже другое N, путать их нельзя. В эту ячейку N посылается 2. Затем выполняется тело функции. Пусть вас не смущает, что Паскаль второй раз выполняет тело функции, не закончив его выполнять в первый раз. Так как 2>1, то Паскаль пытается выполнить умножение 2* Factorial(2-1) и сталкивается с необходимостью знать значение функции Factorial(1), для чего вызывает ее.

 

Спускаюсь еще на ступеньку. В соседнем месте стека отводится место еще для одного N. В эту ячейку N посылается 1. Затем выполняется тело функции. Так как 1=1, то Паскаль вычисляет Factorial :=1. Вот - впервые конкретное число. Затем Паскаль пытается выполнить следующую строку if N>1 then Factorial :=N* Factorial(N-1). Поскольку нельзя сказать, что 1>1, то выполнение тела функции закончено. Значит можно подниматься.

 

Поднимаюсь на одну ступеньку. Паскаль возвращается внутрь тела функции (той, где N=2) и успешно выполняет умножение - Factorial :=2*1=2.

 

Поднимаюсь еще на ступеньку. Паскаль возвращается внутрь тела функции (той, где N=3) и успешно выполняет умножение - Factorial :=3*2=6. Задача решена.

 

После выхода из подпрограммы место в стеке освобождается.

 

Итак, рекурсией в программировании называется вызов подпрограммы из тела самой подпрограммы.

Теперь поговорим о переполнении стека. Размер стека в Паскале не превышает 64K. В нашем случае в стеке одновременно хранилось три копии формальных параметров и локальных переменных. Если бы мы вычисляли факториал десяти, то копий было бы десять. В более сложных, чем факториал, задачах стек может легко переполниться, о чем Паскаль сообщает, когда уже поздно.

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

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

 

Задание 124: Напишите рекурсивную функцию fib для вычисления чисел Фибоначчи.

Сортировка

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

BEGIN

max:=m[1]; Nomer_max:=1; {Это порядковый номер максимального элемента }

for i:=2 to N do if max<m[i] then begin max:=m[i]; Nomer_max:=i end;

maximum:=max

END;

PROCEDURE sortirovka (mass_ish:vector; N:Word; var mass_rez:vector); {Основная процедура сортировки}

VAR i, Nom_max:Word;

BEGIN

for i:=1 to N do begin

mass_rez[N+1-i]:=maximum(mass_ish, N, Nom_max);

mass_ish[Nom_max]:=0

end{for};

END;

BEGIN

sortirovka (massiv_ishodn, N, massiv_rezult);

for i:=1 to N do Write (massiv_rezult[i],' '); {Распечатываем отсортированный массив}

END.

Функция maximum, кроме того, что сама имеет значение максимального элемента массива, выдает еще порядковый номер максимального элемента - Nomer_max. Это называется побочным эффектомфункции.

 

Методов сортировки много. Приведенный метод - самый примитивный. Мало того, что нам пришлось расходовать память на второй массив, для выполнения сортировки массива из 100 элементов понадобилось бы около 100*100=10000 операций сравнения элементов массива между собой.

Существуют методы гораздо более эффективные. Приведу один из них - метод пузырька. Представьте себе тонкую вертикальную трубку с водой. Запустим снизу пузырек воздуха. Он поднимется до самого верха. Затем пустим еще один. Он поднимется наверх и остановится сразу же под первым. Затем запустим третий и так далее все сто пузырьков.

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

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

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

Метод пузырька не требует второго массива, да и сравнений здесь в два раза меньше.

Вот программа:

CONST N = 10;

TYPE vector = array[1..N] of Word;

CONST massiv : vector =(3,8,4,7,20,2,30,5,6,9);

VAR i : Word;

PROCEDURE puziryok (var mass:vector; Razmer:Word);

VAR i,m,c:Word;

BEGIN

for m:=Razmer downto 2 do begin{Всего пузырьков – 9}

for i:=1 to m-1 do begin{i увеличивается – пузырек ползет вверх}

if mass[i]>mass[i+1] then begin{Стоит ли обмениваться значениями}

c:=mass[i]; {Три оператора для обмена значений двух элементов с помощью}

mass[i]:= mass[i+1]; {транзитного элемента c}

mass[i+1]:=c

end{if}

end{for};

end{for};

END;

BEGIN

puziryok (massiv,N);

for i:=1 to N do Write (massiv[i],' '); {Распечатываем отсортированный массив}

END.

Задание 125: Отсортируйте по убыванию двумерный массив. Я имею в виду вот что:

a[1,1] >= a[1,2] >= … >= a[1,N] >=

>= a[2,1] >= a[2,2] >= …>= a[2,N] >=

>= a[3,1] >= a[3,2] >= …

 

Глава 14. Строгости Паскаля

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

Структура программы

BEGIN END. Она, естественно, ничего не делает. Если мы хотим заставить программу что-то… BEGIN WriteLn(1993); WriteLn(1994) END.

BEGIN

a:=5;

WriteLn(a+k)

END.

Таким образом, программа на Паскале состоит из двух и только двух разделов:

1) выше BEGIN расположен раздел описаний,

2) ниже BEGIN расположен раздел выполняемых операторов.

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

 

Приведем полный список служебных слов, после которых задаются описания:

· Переменные описываются после служебного слова VAR

· Метки описываются после служебного слова LABEL

· Константы описываются после служебного слова CONST

· Процедуры описываются после служебного слова PROCEDURE

· Функции описываются после служебного слова FUNCTION

· Новые типы, определяемые программистом,

описываются после служебного слова TYPE

Если программа на Паскале использует модули, то они должны быть перечислены выше раздела описаний после служебного слова USES.

И наконец, программа может иметь заголовок, который состоит из служебного слова PROGRAMи в простейшем случае имени программы.

Пример программы:

PROGRAM Divan;

USES Crt,Graph;

Label met1,met2;

Const k = 100;

S = 'Хорошо!';

TYPE Kniga = array[1..k] of String;

Tablitsa = array[0..20,1..10] of Integer;

Minuta = 0..60;

VAR x,y : Real;

Uspevaemost : Tablitsa;

PROCEDURE Torpeda......

FUNCTION Invers......

Begin

.......

End.

Структура процедур и функций

Каждая из пяти подпрограмм большого проекта может иметь большой объем и руководитель этой подпрограммы должен обладать всем набором средств Паскаля.… По сути структура подпрограммы копирует структуру программы за исключением… Приведу пример записи программы с вложенными подпрограммами:

Выражения

a := b+1 - здесь выражение - b+1 if c-6>f then … - здесь выражение - c-6>f WriteLn (a+5) - здесь выражение - a+5

Совместимость типов

Тип выраженияс операндами разных типов. Что будет, если в одном выражении участвуют величины разных типов? Какого типа будет результат выражения?… VAR a: Byte; b: Word; BEGIN .... a+b ... ?

Форматы вывода данных

c:='Ф'; s:='хорошо'; i:=18; WriteLn(c,s,i) мы увидим в строке экрана Ф х о р о … Мы можем приказать Паскалю отводить под каждое данное столько позиций в строке, сколько нам нужно:…

Переполнение ячеек памяти

VAR i:Byte; BEGIN i:=250; WriteLn(i); i:=i+10; WriteLn(i) END. мы увидим на экране числа 250 и 4. А почему не 250 и 260? Потому что тип Byte представляет только числа от 0 до 255.…

Дерево типов

Схема, приводимая ниже, демонстрирует, какие типы из каких можно конструировать. Например, файлы можно конструировать из строк, а записи из…    

Синтаксисические диаграммы Паскаля

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

Глава 15. Другие возможности Паскаля

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

Работа с файлами данных

В Паскале существует три типа файлов. Мы познакомимся с самым распространенным из них - текстовым файлом. Вам совершенно не обязательно знать, как…   Задача: Записать слово ‘Азия’ и число 1998 на магнитный диск c: в текстовый файл с именем fedos, располагающийся в…

Begin

Assign(fepas, 'c:PASCALfedos');

Rewrite(fepas);

WriteLn(fepas, ‘Азия’);

WriteLn(fepas, 1998);

Close(fepas);

END.

После выполнения программы вы обнаружите в файле fedos две строки:

Азия

Если бы вы вместо WriteLn использовали Write, то строка была бы одна:

Азия1998

Если к моменту выполнения программы файл fedos не существовал, то процедура Rewrite создаст пустой файл с таким именем в указанном каталоге. Если существовал, то стирает его содержимое.

Если вы не хотите стирать содержимое файла, а просто хотите дописать что-нибудь в его конец, то процедура Rewrite вам не подойдет. Вам вместо нее нужно будет употребить процедуру Append. Вот ее вызов - Append(fepas).

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

Assign(fepas, 'fedos')

Информация в наш файл может записываться только по порядку, последовательно. Мы не можем записать что-то сперва в начало файла, потом в конец, потом в середину. То же самое относится и к считыванию, о котором сейчас пойдет речь.

А теперь решим обратную задачу: В некоем файле fedos записаны строки. Вывести первую и третью из них на экран монитора.

VAR fepas :Text;

a,b,c :String; {Три переменные в оперативной памяти, в которые будут

записаны первые три строки из файла}

Begin

Assign(fepas, 'c:PASCALfedos');

Reset(fepas); {Переместим магнитную головку в начало файла для считывания

информации из файла (откроем файл для считывания) }

ReadLn(fepas, a); {Читаем первую строку из файла}

ReadLn (fepas, b); {Читаем вторую строку из файла}

ReadLn (fepas, c); {Читаем третью строку из файла}

Close(fepas);

WriteLn(a); {Печатаем первую строку из файла}

WriteLn(c); {Печатаем третью строку из файла}

END.

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

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

 

А теперь напишем программу, которая в цикле записывает в файл 10 строк, а затем для проверки их считывает.

VAR f :Text;

a,b :String;

i :Byte;

Begin

Assign(f,'c:PASCALtextik.txt'); {Обозначим файл textik.txt из каталога PASCAL именем f}

Rewrite(f); {Переместим магнитную головку в начало файла для

записи информации в файл (откроем файл)}

WriteLn('Введите с клавиатуры 10 произвольных строк');

for i:=1 to 10 do begin

ReadLn(a); {Ввести с клавиатуры в оперативную память произвольную строку текста}

WriteLn(f,a) {Записать эту строку из оперативной памяти в файл}

end;

Close(f); {Закрываем файл для записи}

 

WriteLn('А теперь посмотрим, что мы записали в файл:');

Reset(f); {Переместим магнитную головку в начало файла для

считывания информации из файла (откроем файл)}

for i:=1 to 10 do begin

ReadLn(f,b); {Переслать из файла в оперативную память строку текста}

WriteLn(b) {Послать эту строку из оперативн.памяти на монитор}

end;

Close(f); {Закрываем файл для чтения}

End.

Если вы хотите прочесть текстовый файл, но не знаете, сколько там строк, то вам нужно какое-то средство, чтобы компьютер определил, когда заканчивается файл. Это средство - функция EOF(сокращение от end of file – «конец файла»). Вот фрагмент, решающий дело:

while NOT EOF(fepas) do ... ReadLn(fepas, ....)

пока нет конца файла fepas делай …

Задание 126: “База данных ваших школьных оценок”. Вы завели файл, в который записываете свои школьные оценки. Каждый раз, получив оценку, вы дописываете в файл оценку и предмет, по которому оценка получена. Создайте 4 программы:

1) Для дозаписи в конец файла очередной оценки и предмета.

2) Для вывода на экран всего файла.

3) Для вывода на экран всех отметок по заданному предмету. (Для определенности договоримся, что больше 1000 оценок в год вы не получите.)

4) Для определения, сколько было по заданному предмету таких-то оценок (скажем, троек).

Оформите каждую из четырех программ, как процедуру, и создайте единую программу - “Систему управления базой данных”, которая начинает работу с вопроса: “Чем будем заниматься - дозаписывать, выводить весь файл ...?” и в зависимости от ответа запускает одну из четырех процедур.

Задание 127: Вы можете помочь адмиралу из 12.13 и организовать чтение из файла всей нужной информации о подлодках.

Задание 128: Многие компьютерные игры позволяют “сохраняться”, то есть в любой момент игры при нажатии определенной клавиши записывать в файл все данные об этом моменте, чтобы в следующий раз, когда вы сядете играть, начинать не сначала, а с того момента, в который вы записались. В игре “Торпедная атака” организуйте при нажатии на клавишу S сохранение, то есть запись в файл имени игрока, уровня игры, количества выстрелов и количества попаданий. А при запуске игра должна спрашивать, будем ли возобновлять сохраненную игру или начинать новую.

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

PROCEDURE fa ; BEGIN Sound(698); Delay(300); NoSound END; PROCEDURE sol; BEGIN Sound(784); Delay(300); NoSound END; PROCEDURE la ; BEGIN Sound(880); Delay(300); NoSound END;

Begin

doo;re;mi;fa;sol;la;si;la;sol;fa;mi;re;doo

End.

Теперь вам нужно собрать оба куска в единую программу. Для этого вы можете скопировать текст из файла вашего друга в свой файл (как это делается, расказано в части IV). Но если вы не хотите этого делать, чтобы, скажем, не увеличивать свой файл, вы можете воспользоваться директивой компилятора $I. Директива компилятора- это специальная инструкция, вставленная в текст вашей программы на Паскале и предназначенная для управления компьютером на этапе компиляции вашей программы. Директива компиляции имеет вид {$....} и Паскаль не путает ее с обычным комментарием только из-за наличия значка доллара. Символы, стоящие после значка доллара, и являются управляющей информацией для компилятора. Директива {$I c:PASCF25} является приказом компилятору подставить в это место текст, находящийся в файле F25 из каталога PASC диска c. Если файл находится в текущем каталоге, то достаточно указать его имя. Вот ваша готовая к работе программа с директивой:

USES CRT;

PROCEDURE doo; BEGIN Sound(523); Delay(300); NoSound END;

PROCEDURE re ; BEGIN Sound(587); Delay(300); NoSound END;

PROCEDURE mi ; BEGIN Sound(659); Delay(300); NoSound END;

 

{$I VSTAVKA} {Директива компилятору на вставку текста из файла VSTAVKA}

 

Begin

doo;re;mi;fa;sol;la;si;la;sol;fa;mi;re;doo

End.

Модули программиста

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

FUNCTION st(a:Real; n:Word) :Real;

VAR step :Real;

i :Word;

BEGIN

step:=1;

for i:=1 to n do step:=step*a;

st:=step

end;

BEGIN

WriteLn(st(2,3)) {Это 2 в кубе, то есть 8}

END.

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

· Описать st и другие часто встречающиеся процедуры и функции в другом файле и использовать директиву $I.

· Описать st и другие часто встречающиеся процедуры и функции в другом файле и оформить этот файл, как новый модуль.

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

UNITMathemat; {Заголовок модуляс придуманным вами именем}

 

INTERFACE {Раздел ИНТЕРФЕЙСА}

FUNCTION st(a:Real; n:Word) :Real;

 

IMPLEMENTATION {Раздел РЕАЛИЗАЦИИ}

FUNCTION st;

VAR step :Real;

i :Word;

BEGIN

step:=1;

for i:=1 to n do step:=step*a;

st:=step

end;

 

BEGIN {Раздел ИНИЦИАЛИЗАЦИИ, у нас он пуст}

END.

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

USES Mathemat;

Begin

WriteLn(st(10,6) :20:4); {Это 10 в шестой степени}

WriteLn(st(5, 3) :20:4); {Это 5 в кубе}

End.

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

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

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

Когда вы в первый раз запустите на выполнение программу, вызывающую ваш новый модуль, этот модуль откомпилируется и сохранится на диске под именем Mathemat.tpu. В следующий раз будет использоваться именно он, а не Mathemat.pas (до тех пор, пока вы не измените текст модуля).

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

UNIT Mygraph;

 

INTERFACE {Раздел ИНТЕРФЕЙСА}

PROCEDURE krest(x_tsentr, y_tsentr, razmer:Word);

{Задаются координаты центра и размер креста}

PROCEDURE treug(x1, y1, x2, y2, x3, y3 :Word);

{Задаются координаты трех вершин треугольника}

 

IMPLEMENTATION {Раздел РЕАЛИЗАЦИИ}

USES Graph; {Без этого не будет работать процедура Line}

PROCEDURE krest; BEGIN

Line(x_tsentr-razmer, y_tsentr, x_tsentr+razmer, y_tsentr);

Line(x_tsentr, y_tsentr-razmer, x_tsentr, y_tsentr+razmer);

END;

PROCEDURE treug; BEGIN

Line(x1,y1,x2,y2);

Line(x2,y2,x3,y3);

Line(x3,y3,x1,y1);

END;

{Раздел ИНИЦИАЛИЗАЦИИ}

VAR d,m :Integer; {Переменные для инициализации графики}

BEGIN

d:=0;

InitGraph(d,m,'<путь к гр.др>');{Инициализация графики}

SetColor(Yellow); {Рисуем рамочку}

SetLineStyle(0,0,ThickWidth);

Rectangle(10,10,630,470);

SetColor(White); {Возвращаем нормальный цвет}

SetLineStyle(0,0,NormWidth) {Возвращаем нормальную толщину линии}

END.

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

Вот программа, чертящая крест, треугольник и кружок:

USES Mygraph,Graph;

BEGIN

treug(500,50,600,300,450,450);

krest(200,150,80);

Circle(100,350,40);

ReadLn;

END.

Обращение здесь к модулю Graph понадобилось только из-за желания нарисовать кружок.

 

Использование модулей лучше использования директивы $I хотя бы по двум причинам:

· Модуль уже откомпилирован и не требует каждый раз компиляции.

· Объем программы без модулей не может превышать 64К. Каждый модуль может вмещать в себя дополнительные 64К.

 

Задание 129: Если хотите, создайте себе модули Music, Graphica или какие-нибудь другие.

Дополнительные процедуры и функции модуля Graph

А вот еще процедуры рисования: Процедура Смысл Arc(x,y :Integer; fi1,fi2,r :Word) Рисует дугу окружности с…

Копирование и движение областей экрана

  Пример 1. Нарисуем в левом верхнем углу экрана четыре окружности, а затем… USES Graph;

Begin

Gd := 0; InitGraph(Gd, Gm, 'с:tpbgi');

SetLineStyle(0,0,Thickwidth);

{Рисуем очки:}

Circle(50,100,20); Circle(50,100,15);

Circle(90,100,20); Circle(90,100,15);

{В целях наглядности нарисуем также диагональ экрана:}

Line(0,0,640,480);

 

Size := ImageSize(10,60,120,140);

GetMem(P, Size);

GetImage(10,60,120,140,P^);

ReadLn;

PutImage(500,400, P^,0);

ReadLn;

CloseGraph

End.

Пояснения: Чтобы скопировать область экрана, Паскаль должен сначала ее запомнить в оперативной памияти. Выберем мысленно прямоугольник, охватывающий объект, предназначенный для копирования. В нашем случае подойдет прямоугольник между точками (10,60) и (120,140). Чтобы знать, сколько памяти отвести под запоминание области, компьютер должен знать размер изображения в байтах. Этот размер сообщает функция ImageSize. Поскольку размер этот может оказаться большим, то запоминать изображение лучше всего в куче. Отводит место в куче процедура GetMem. Вот ее вызов - GetMem(P, Size). P – так называемый указательна место в памяти, предназначенное для запоминания. Указатели – это новый для нас тип данных. Останавливаться на них я не буду, скажу только, что они очень похожи на ссылки. Запоминает область процедура GetImage, параметр которой P^ имеет значением изображение этой области. Процедура PutImage помещает это изображение в точно такой же прямоугольник экрана с верхним левым углом в точке (500,400).

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

Задание 130: Нарисуйте шеренгу из десятка снеговиков.

 

Пример 2. Попробуем двигать наши очки слева направо.

USES Graph,crt;

VAR x,Gd, Gm : Integer;

P : pointer;

Size : Word;

Begin

Gd := 0; InitGraph(Gd, Gm, 'с:tpbgi');

SetLineStyle(0,0,Thickwidth);

{Рисуем очки:}

Circle(50,100,20); Circle(50,100,15);

Circle(90,100,20); Circle(90,100,15);

{Рисуем диагональ :}

Line(0,0,640,480);

Size := ImageSize(10,60,120,140);

GetMem(P, Size);

GetImage(10,60,120,140,P^);

{Начинаем движение:}

x:=20;

while x<300 do begin

PutImage(x, 150, P^,1);

Delay(40);

PutImage(x, 150, P^,1);

x:=x+1;

end{while};

CloseGraph

End.

Пояснение: Чтобы нарисовать очки в каком-то месте, а потом их стереть, достаточно два раза подряд употребить оператор PutImage(x, 150, P^,1). Обратите внимание, что изображение прямой, по которому прошлись очки, не затерлось. Все это - результат удивительного действия константы 1. Но чтобы понять механизм ее действия, нужно знать азы алгебры логики, которые, к сожалению, у меня нет времени излагать.

Задание 131: Пусть два снеговика идут друг другу навстречу.

 

Вывод текста в графическом режиме

SetTextStyle (4,0,8); OutTextXY(200,300,’Hello!’) на экране появится строка Hello!, выполненная шрифтом4 (готический) размера 8. Левый верхний угол строки будет…

Begin

as:='937';

Val(as,a,err);

WriteLn (a+1);

ReadLn

End.

Пояснения: Процедура Val преобразует строку из трех символов 937 в число 937. В результате оператор WriteLn (a+1) печатает число 938. На смысле переменной err останавливаться я не буду.

Задание 132: У вас имеется текстовый файл из произвольного числа строк. Организуйте вывод этого файла на экран векторным шрифтом. Если у вас есть время, организуйте управление с клавиатуры: пролистывание текста, выбор шрифта, выбор цвета шрифта и фона.

Управление цветом в текстовом режиме(модуль CRT)

  До сих пор вы не умели управлять положением текстового курсора на экране. При…  

BEGIN

TextBackground (Red);

ClrScr;

TextColor (Yellow);

TextBackground (Blue);

GotoXY(38,13);

WriteLn(‘Вход’)

END.

Работа с датами и временем (модуль DOS)

Чтобы воспользоваться этими процедурами, вы должны придумать имена переменным, обозначающим дату и время: God год (с 1980 по 2099) Mes месяц (1-12)

Begin

GetDate(God, Mes, Den, Den_Ned);

WriteLn(‘Сегодня ’ , Den, ‘ . ‘ ,Mes, ‘ ‘ ,God, ‘ года‘);

GetTime(Chas,Min,Sec,Sotki);

WriteLn(‘Сейчас ’ , Chas,' час. ' ,Min, ' мин. и ' ,Sec, ' сек.')

End.

 

Задание 133 «Быстрота реакции»: Определите быстроту своей реакции: На экране через случайный промежуток времени (секунды через 2 - 4) возникает квадрат. Как только он возник, быстрее нажимайте на какую-нибудь клавишу. Пусть компьютер вычислит, сколько сотых долей секунды прошло между этими двумя событиями.

Возможно, вас не удовлетворит работа GetTime в этой программе. Попробуйте сделать определитель быстроты реакции, не связываясь с процедурами модуля DOS. Например, засеките по секундомеру, сколько времени ваш компьютер выполняет пустой цикл for i:=1 to 10000000 do; и создайте на этой основе свою единицу времени.

 

А вот как установить дату и время:

SetDate(1997, 5, 22) -установить дату 22 мая 1997 года

SetTime(23, 58, 32, 93) -установить время 23 часа 58 мин 32 сек и 93 сотых

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

 

Задание 134 «Определитель дня недели»: Вы вводите любую дату. Компьютер должен определить день недели и напечатать его в виде “понедельник”, “вторник” и т.д. При этом вы не должны испортить календарь, то есть после того, как ваша программа завершит работу, календарь компьютера должен показывать правильную дату, а не ту, что вы ввели.

Нерассмотренные возможности Паскаля

  Модуль Graph. Подобно курсору в текстовом режиме, в графическом режиме есть…  

Миг между прошлым и будущим

Если вы решите стать профессиональным программистом, то будете работать с современными версиями языков программирования, такими как Delphi, и…   А теперь я хочу предложить вам задание 135 и последнее на звание «Программист-любитель II ранга». На выбор – одно из…

Часть IV. Работа в Паскале на компьютере

Что нужно знать и уметь к моменту выполнения первой программы? · Вы должны иметь работающий компьютер с установленным на жестком диске… · Вы должны уметь работать с текстом в простейшем текстовом редакторе. Если не умеете, то вам вполне достаточно…

Порядок работы в Паскале

(2)Введите программу (3)Сохраните программу на жестком диске (4)Выполните программу

BEGIN

ReadLn (a1,a2);

if a1>a2

then V:=a1*a1*a1

else V:=a2*a2*a2;

WriteLn (V : 15:5)

END.

Запускайте программу, но не обычным образом, а клавишей F7, которая является более быстрым способом вызова меню Run®Trace into. (Кстати, обратите внимание, что справа от многих опций меню обозначены «горячие» клавиши, которыми эти опции можно быстро вызывать.) Паскаль откомпилирует вашу программу и сделает паузу перед началом выполнения программы, подсветив горизонтальной полосой строку BEGIN.

Еще разF7. Ничего не происходит, только полоса подсветки прыгает на следующую строку. В ней находится первый исполняемый оператор вашей программы – ReadLn (a1,a2).

Итак, правило простое – при нажатии на F7Паскаль выполняет одну строку программы и подсвечивает ту строку, которой предстоит быть выполненной.

F7. Паскаль выполняет ReadLn (a1,a2), в результате чего у вас, как и при обычном выполнении программы, во весь экран распахивается черное окно пользователя. Оператор требует ввода двух чисел. Введите, например, 5 и 4, не забыв нажать на клавишу ввода. Окно пользователя пропадет, снова возникнет окно редактора и вы увидите, что серая полоса подсветки перескочила на строку if a1>a2.

F7. Паскаль выполняет if a1>a2, в результате чего полоса прыгает на then V:=a1*a1*a1, так как 5>4.

F7. Полоса перепрыгивает через else V:=a2*a2*a2 и попадает на WriteLn (V : 15:5).

F7. Паскаль выполняет WriteLn (V : 15:5), в результате чего печатается результат, а полоса перескакивает на строку END.

F7. Полоса пропадает. Программа выполнена. Посмотрим на результат при помощи Alt-F5.

 

Теперь еще раз выполните ту же программу в пошаговом режиме. Но когда ReadLn (a1,a2) потребует двух чисел, введите 2 и 3. Теперь уже после if a1>a2 полоса прыгает не на then V:=a1*a1*a1, а на else V:=a2*a2*a2.

 

В любой момент пошагового выполнения программы вы можете вместо F7выбрать Run®Run(клавиши Ctrl-F9) и программа продолжит выполняться в обычном режиме. Чтобы прервать пошаговый режим, выберите Run®Program reset(клавиши Ctrl-F2).

 

Работа с окнами пользователя и отладчика

 

Предположим, у вас не получается задание из 6.1 - определить без компьютера, что будет печатать следующая программа:

LABEL m1,met5;
VAR n,k : Integer;
BEGIN
n:=10;

k:=0;

WriteLn('Считаем зайцев' );

met5: Write(n);

n:=n+k;

goto m1;

n:=n+1;

m1: Write(' зайцев ');

ReadLn;

k:=k+1;

goto met5;

WriteLn('Посчитали зайцев')

END.

Ответ: Эта программа должна печатать:

Считаем зайцев
10 зайцев

10 зайцев

11 зайцев

13 зайцев

16 зайцев

20 зайцев

………

С ответом у вас не сходится. Значит, вы чего-то не понимаете. Чего? Чтобы определить это, вы вводите программу в компьютер. Он печатает все, как в ответе. Почему? Вероятно, вы не понимаете, как изменяются в процессе выполнения программы значения переменных n и k. Хорошо бы можно было подсмотреть за их значениями в оперативной памяти. Хорошо бы также напечатанные результаты не пропадали с экрана, а были бы всегда перед глазами.

Проделайте следующее. (При дальнейшем объяснении я буду предполагать, что вы умеете обращаться с несколькими окнами на экране. Кто не умеет, читайте следующий параграф.)

Сузьте окно вашей программы так, чтобы оно освободило примерно половину ширины экрана. Далее - Debug®Output. Перед вами появляется черное окно пользователя, в котором вы привыкли наблюдать результаты, но в уменьшенном виде. Измените его размер и отбуксируйте на свободное место экрана.

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

Вот как будет выглядеть ваш экран после всех манипуляций (и уже после нескольких выполнений цикла в пошаговом режиме, о чем дальше):

 

 


Вы сами должны сказать Паскалю, за какими переменными хотите следить. Очевидно, в вашем случае это n и k. Ваши действия: Debug®Add watch…,запишите имя n в открывшемся диалоговом окне и – щелчок по кнопке OK. В окне отладчика появится сообщение n:7 или n:0или какое-нибудь другое число или сообщение. Не обращайте на это внимания. Повторите всю процедуру с k.

Теперь можно запускать программу на выполнение в пошаговом режиме. Для этого нажмите на F7. Паскаль откомпилирует вашу программу, возможно, изменит значения в окне отладчика и сделает паузу перед началом выполнения программы, подсветив горизонтальной полосой строку BEGIN.

F7. Паскаль, возможно, обнулит значения в окне отладчика. Полоса подсветки прыгает на следующую строку. В ней находится первый исполняемый оператор вашей программы – n:=10.

Итак, правило простое – при нажатии на F7Паскаль выполняет одну строку программы и подсвечивает ту строку, которой предстоит быть выполненной.

F7. Паскаль выполняет n:=10, в результате чего в окне отладчика значение n меняется на 10, а серая полоса прыгает на строку k:=0.

F7. Паскаль выполняет k:=0, в результате чего в окне отладчика значение k становится равным 0, а полоса прыгает на строку WriteLn('Считаем зайцев' ).

F7. Паскаль выполняет WriteLn('Считаем зайцев' ), в результате чего в окне пользователя появляется напечатанный текст Считаем зайцев, а полоса прыгает на строку met5: Write(n).

F7. Паскаль выполняет Write(n). В окне пользователя в новой строке появляется число 10, так как в оперативной памяти n равно 10 (об этом нам говорит окно отладчика). а полоса прыгает на строку n:=n+k.

F7. Паскаль выполняет n:=n+k, в результате чего в окне отладчика значение n остается равным 10, так как в оперативной памяти k равно 0. Полоса прыгает на строку goto m1.

F7. Паскаль выполняет goto m1. Полоса перепрыгивает на строку m1: Write(' зайцев ').

F7. Паскаль выполняет Write(' зайцев ' ), в результате чего в окне пользователя справа от числа 10 появляется текст зайцев, а полоса прыгает на строку ReadLn.

F7. Паскаль выполняет ReadLn, в результате чего окно пользователя распахивается на весь экран и ReadLn ждет, когда вы нажмете на клавишу ввода. Вы нажимаете – и полоса прыгает на строку k:=k+1.

F7. Паскаль выполняет k:=k+1, в результате чего в окне отладчика значение k меняется на 11. Полоса прыгает на строку goto met5.

F7. Паскаль выполняет goto met5. Полоса перепрыгивает вверх, на строку met5: Write(n).

 

И так далее.

 

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

Если в вашей программе есть подпрограммы, то серая полоса проникнет и внутрь подпрограмм и будет скакать там, как ни в чем не бывало. Таким образом, вы сможете анализировать и работу подпрограмм. Если же вы не хотите утомлять себя прыжками внутри подпрограмм, нажимайте не F7, а F8. Тогда Паскаль будет выполнять подпрограмму мгновенно в автоматическом режиме и серая полоса будет путешествовать только внутри основной программы. Вы можете свободно чередовать нажатия F7 и F8. Клавиша F7 будет направлять вас «вглубь» подпрограмм, а F8 - «наружу».

 

Отладка больших программ

 

Точки прерывания - Breakpoints. Будем считать “большими” программы, превышающие пару размеров экрана. Для них изложенный только что пошаговый режим может быть очень утомительным, так как слишком часто приходится жать F7. Вы можете заставить Паскаль при выполнении программы задерживаться не на каждой строке, а только на некоторых - тех, что вам нужно.

Поставьте курсор на одну из этих строк и нажмите Ctrl-F8. Строка станет красной. Это знак того, что при выполнении программа на ней остановится. Будем называть эту строку точкой прерыванияили контрольной точкой.

Поставьте курсор на другую строку и снова нажмите Ctrl-F8. Эта строка тоже станет точкой прерывания.

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

А теперь обычным образом (Run®Run или Ctrl-F9) запускайте программу. Программа будет выполняться до тех пор, пока не наткнется на какую-нибудь точку прерывания. На ней она встанет и продолжит работу с того места, где остановилась, только при новом нажатии Ctrl-F9. И так далее.

Убирается точка прерывания точно так же, как ставится - Ctrl-F8.

 

“Иди до курсора” - Goto cursor. Это еще один способ остановки в нужной вам строке. Поставьте курсор в нужную строку и нажмите F4. Программа будет выполняться до тех пор, пока не наткнется на строку с курсором. А теперь поставьте курсор в другую строку и снова нажмите F4. Программа продолжит работу с того места, где остановилась, и будет выполняться до тех пор, пока не наткнется на строку с курсором. И так далее.

 

Кстати, в процессе выполнения программы вы можете достаточно свободно переключаться между разными способами ее выполнения – F7, F4 или Ctrl-F9.

 

Испольование Write и ReadLn. Если программа работает с графикой, то пользоваться вышеописанными средствами отладки или неудобно или нельзя. Не беда. Еще до существования всех и всяческих отладчиков программисты пользовались вспомогательной печатью значений переменных. Действительно, вместо использования окна отладчика для подсматривания за переменными n и k, вы просто можете в программу вставить дополнительный оператор Write(’ n=‘,n,’ k=‘,k). А вместо пошагового режима можете в нужных местах программы поставить ReadLn. Когда программа будет отлажена, вы уберете эти дополнительные операторы.

Только имейте в виду, что когда экран с вашими картинками донизу будет заполнен информацией, напечатанной оператором Write, он начнет прокручиваться вверх, а вместе с ним вверх уползут и ваши картинки. Чтобы избежать этого, нужно сделать так, чтобы не допечатав донизу, компьютер при помощи ReadLn сделал паузу (чтобы вы успели посмотреть результаты печати) и снова стал печатать бы сверху. А для печати сверху необходимо вставить в нужное место программы оператор GotoXY (см.15.7). А уж для этого вам нужно использовать модуль CRT (см. 9.1) и вставить в начало программы оператор DirectVideo:=false (см.10.3).

Работа с несколькими окнами.

В обычной практике программиста несколько окон появляются на экране не в результате File®New, а в результате File®Open, когда программисту нужно или… То окно, в котором вы щелкнули мышкой, становится активным. Его легко отличить… Чтобы «достать» окна, загороженные другими, используйте мышку или F6.

Копирование и перемещение фрагментов текста

Поставьте мышку на первую букву копируемого фрагмента, нажмите левую клавишу мыши и, не отпуская ее, ведите мышь на конец копируемого фрагмента.… Перемещение: Дайте команду Edit®Cut- фрагмент исчез. Паскаль запомнил его в… Копирование: Дайте команду Edit®Copy– фрагмент не исчез. Остальное - аналогично перемещению.

Обзор популярных команд меню

Если вы при вводе программы сделали какую-то глупость и в окне редактора ВСЕ ОЧЕНЬ ПЛОХО!!! – не паникуйте – ничего не пропало! Edit®Undo означает… Установите флажок (крестик) в Options®Compiler…®Compiler Options®Runtime… Если при запуске программы, обращающейся к стандартным модулям, Паскаль жалуется, что не может найти модуль (File not…

Создание исполнимых файлов(exe)

Сделать это просто: Compile - затем убедитесь, что в выпавшем меню опция Destination (куда записать откомпилированную программу) находится в… Если ваша программа использует модуль Graph, то одного «экзешного» файла…

Приложения. Справочный материал

П1. Как вводить программу в компьютер или работа с текстом в текстовом редакторе

  Работа с одной строкой текста Когда мы начинаем работать в текстовом редакторе, перед нами обычно - пустой экран, по краям которого могут…

В небе

Облака из серой ваты

Сыровато-сероваты,

Не беда - ведь я привык.

В луже

Эта вата намокает

И волнуясь пробегает

Под водою мой двойник.

Чтобы знать, как реагировать на неожиданности, нужно перед тем, как начать нажимать клавиши, проглядеть не очень внимательно дальнейший материал…   Ввод нескольких строк. Как сделать так, чтобы, введя слова «в небе», следующие слова начать с новой строки? Для этого…

П2. Файловая система магнитного диска

У каждого файла должно быть имя,например,Sveta25. Файлы появляются на диске двумя способами: или вы их переписываете на диск из другого места и… Обычно на жестком диске хранятся сотни и тысячи файлов. Просмотр содержимого… Обычно вам нужно найти среди них какой-то один, чтобы начать с ним работать. Но когда в списке тысяча файлов, найти…

Логические диски. Путь (дорожка) к файлу

В процессе общения с этими программами вам приходится объяснять им, где, в каком каталоге находится такой-то файл или каталог, и самим понимать их… Пусть на вашем компьютере есть дисковод для трехдюймовых дисков, дисковод для… Итак, как же понимать запись B:LettersEdIn25may97.txt? Она означает, что файл с именем 25may97.txt находится в…

П3. Список некоторых операций, процедур и функций Паскаля

  Математика Sqr (A) аргумент A – любого числового типа, результат - того же типа, что и A

Процедура или функция Смысл

NoSound нет звука Delay (A :Word) отсрочка ReadKey :Char читай клавишу

П4. Произношение английских слов

     

П5. Решения заданий

  Программа для робота Пояснения для нас с вами 1. ПОВТОРИ 5 РАЗ ШАГ ВПЕРЕД Робот идет по коридору до…   Задание 2 + =

BEGIN

a:= 9000000;

b:= 1000;

WriteLn (a-b);

ReadLn

END.

 

Задание 6 Паскаль выдает сообщение об ошибке: Constant out of range (см. сообщения об ошибках в части IV).

Задание 7 Паскаль выдает результат 211 или другой неправильный.

Задание 8 1001

Задание 9 -100

Задание 10 15 -10

Задание 11 82

Задание 12

VAR dlina_dvora, dlina_doma,

shirina_dvora, shirina_doma,

pl_dvora, pl_doma,

svobodn_pl_dvora, dlina_zabora :Integer;

BEGIN

dlina_dvora:=50; dlina_doma:=20;

shirina_dvora:=30; shirina_doma:=10;

 

pl_dvora := dlina_dvora * shirina_dvora;

pl_doma := dlina_doma * shirina_doma;

svobodn_pl_dvora := pl_dvora - pl_doma;

dlina_zabora := 2*(dlina_dvora+shirina_dvora)-(dlina_doma+shirina_doma);

 

WriteLn (pl_doma,' ', svobodn_pl_dvora,' ', dlina_zabora);

ReadLn

END.

 

Задание 13

VAR r :Integer; {r-радиус окружности}

l, s :Real; {l-длина окружности, s-площадь круга}

BEGIN

r := 800;

l := 2 * pi * r;

s := pi * r * r;

WriteLn (l :15:5, ' ', s:15:5);

ReadLn

END.

 

Задание 14

VAR t1, t2, {t1-время на первом отрезке, t2-на втором}

v1, v2, {v1-скорость на первом отрезке, v2-на втором}

s1, s2 :Integer; {s1-первый отрезок пути, s2-второй}

sredn_skorost :Real;

BEGIN

t1:=3; t2:=2;

v1:=80; v2:=90;

s1:=v1*t1; {путь равен скорость умножить на время}

s2:=v2*t2;

sredn_skorost := (s1+s2)/(t1+t2);

WriteLn (sredn_skorost :10:3);

ReadLn

END.

 

Задание 15

VAR a,b,c, perimetr :Integer; {a,b,c - стороны треугольника}

BEGIN

a:=20;

WriteLn ('Введите длины двух сторон треугольника');

ReadLn(b,c);

perimetr := a+b+c; {периметр - это сумма сторон}

WriteLn ('Периметр треугольника равен ' , perimetr);

ReadLn

END.

 

Задание 16

VAR t, v, s :Real; {t-время, v-скорость, s-путь}

BEGIN

WriteLn ('Введите путь в метрах и скорость в м/с');

ReadLn(s,v);

t:=s/v;

WriteLn ('Время = ', t :6:3, ' сек');

ReadLn

END.

 

Задание 17

VAR r1, r2, {r1-радиус орбиты первой планеты, r2-второй}

v1, v2, {v1-скорость первой планеты, v2-второй}

t1, t2 :Real; {t1-продолжительность года первой планеты, t2-второй}

nazvanie1, nazvanie2 :String;

BEGIN

WriteLn('Введите название первой планеты');

ReadLn(nazvanie1);

WriteLn('Введите радиус орбиты и скорость первой планеты');

ReadLn(r1,v1);

WriteLn('Введите название второй планеты');

ReadLn(nazvanie2);

WriteLn('Введите радиус орбиты и скорость второй планеты');

ReadLn(r2,v2);

t1 := 2*pi*r1/v1; {время = длина орбиты/скорость, а длина}

t2 := 2*pi*r2/v2; {орбиты равна два пи * радиус}

WriteLn ('Продолжительность года на планете ', nazvanie1, ' - ', t1: 3:0,

' сут., а на планете ', nazvanie2, ' - ', t2 :3:0, ' сут.');

ReadLn

END.

 

Задание 18 8

Задание 19 29

Задание 20 66

Задание 21

VAR a1,a2 : Integer;

BEGIN

ReadLn (a1,a2);

if a1>a2 then WriteLn (a1+a2)

else WriteLn (a1*a2);

WriteLn('ЗАДАЧА РЕШЕНА');

ReadLn

END.

 

Задание 22

VAR a,b,c : Integer;

BEGIN

ReadLn (a,b,c);

if a<b+c then WriteLn ('Подходит.')

else WriteLn ('Не подходит, слишком длинен.');

ReadLn

END.

 

Задание 23

VAR golov, glaz, N : Integer;

BEGIN

WriteLn ('Сколько лет дракону?');

ReadLn (N);

if N<100 then golov := 3*N

else golov := 300 + 2*(N-100);

glaz := 2*golov;

WriteLn ('У дракона ', golov ,' голов и ', glaz ,' глаз');

ReadLn

END.

 

Задание 24

VAR imya :String;

Vozrast :Integer;

BEGIN

WriteLn ('Здравствуй, я компьютер, а тебя как зовут?');

ReadLn (imya);

WriteLn ('Очень приятно, ', imya, '. Сколько тебе лет?');

ReadLn (vozrast);

WriteLn ('Ого! Целых ' ,vozrast, ' лет! Ты уже совсем взрослый!');

if vozrast<=17 then begin

WriteLn ('В какой школе ты учишься?');

ReadLn; {Во время паузы вы можете вводить любой текст,

все равно он программе не понадобится}

WriteLn ('Неплохая школа!')

End

Else begin

WriteLn ('В каком институте ты учишься?');

ReadLn;

WriteLn ('Хороший институт!')

end;

WriteLn ('До следующей встречи!');

ReadLn

END.

 

Задание 25

VAR a,b,c : Integer;

BEGIN

ReadLn (a,b,c);

if a>=b+c then WriteLn ('Неправда')

else if b>=a+c then WriteLn ('Неправда')

else if c>=a+b then WriteLn ('Неправда')

else WriteLn ('Правда');

ReadLn

END.

 

Задание 26 Ей нравятся любые черноглазые, но только не те, у кого рост находится в диапазоне от 180 до 184.

 

Задание 27

VAR a,b :String; {a-ПРИВЕТСТВИЕ ЧЕЛОВЕКА, b-ОТВЕТ КОМПЬЮТЕРА}

BEGIN

ReadLn (a);

if a='Здравия желаю' then b:='Вольно';

if a='Здорово' then b:='Здравствуйте';

if (a='Добрый день')OR(a='Приветик')OR(a='Салют') then b:='Салют';

if (a='Привет')OR(a='Здравствуйте') then b:=a;

WriteLn (b,'!');

ReadLn

END.

 

 

Задание 28

VAR bukva : Char;

BEGIN

WriteLn ('Введи строчную букву русского алфавита');

ReadLn (bukva);

case bukva of

'а','е','и','о','у','ы','э','ю','я' :WriteLn('гласная');

'б','з','в','г','д','ж' :WriteLn('согласная звонкая');

'п','с','ф','к','т','ш' :WriteLn('согласная глухая');

'й','л','м','н','р','х','ц','ч','щ','ъ','ь' :WriteLn('другая');

else WriteLn('Таких букв не знаю')

end;

ReadLn

END.

 

Задание 29

VAR a,b,rez : Real; {a и b - два числа, rez-результат}

Oper : Char; {oper - знак арифметического действия}

BEGIN

ReadLn (a);

ReadLn (oper);

ReadLn (b);

case oper of

'+' : rez:=a+b;

'-' : rez:=a-b;

'*' : rez:=a*b;

'/' : rez:=a/b;

else WriteLn('Таких действий не знаю')

end;

WriteLn(rez :11:8);

ReadLn

END.

 

Задание 30 Эта программа будет печатать:

Считаем зайцев
10 зайцев

10 зайцев

11 зайцев

13 зайцев

16 зайцев

20 зайцев

………

Операторы n:=n+1 и WriteLn('Посчитали зайцев') не будут выполнены никогда.

 

Задание 31

LABEL m1; BEGIN m1: Write ('A'); ReadLn; goto m1 END.

 

Задание 32

LABEL m1;

VAR i :LongInt;

BEGIN

i:=1000;

m1: Write (i,' ');

ReadLn;

i:=i-1;

goto m1

END.

 

Задание 33

LABEL m1;

VAR a :Real;

BEGIN

a:=100;

m1: Write (a :12:8,' ');

ReadLn;

a:=a/2;

goto m1

END.

 

Задание 34

LABEL m1,m2;

VAR i :LongInt;

BEGIN

i:=1;

m1: Write (i,' ');

i:=i+1;

if i<100 then goto m1;

 

m2: Write (i,' ');

i:=i-1;

if i>=1 then goto m2;

ReadLn

END.

 

Задание 35

LABEL m;

VAR a :Real;

BEGIN

a:=0;

m: WriteLn (a :5:3,' ', a*a :9:6);

a:=a+0.001;

if a<=1.00001 then goto m;

ReadLn

END.

Пояснение: Вместо if a<=1 then я написал if a<=1.00001 then и вот по какой причине. Вещественные числа компьютер складывает с незначительной погрешностью, но ее достаточно, чтобы при тысячекратном прибавлении 0.001 набралась не 1, а чуть-чуть больше. А это значит, что счет остановился бы на 0.999. Если не верите, попробуйте распечатывать а с 15 знаками после точки. Подробнее о причинах – см. 12.2

 

Задание 36

LABEL m1,m2;

VAR x,y,z :Real;

BEGIN

x:=2700;

m1: y:=x/4 + 20;

z:=2*y+0.23;

WriteLn ('x=',x:12:6,' y=',y:12:6,' z=',z:12:6);

if y*z<1/x then goto m2;

x:=x/3;

goto m1;

m2: ReadLn

END.

 

Задание 37

VAR Slovo :String;

Nomer :Integer;

BEGIN

Nomer:=1;

Repeat

WriteLn('Введите слово');

ReadLn(Slovo);

WriteLn(Nomer, ' ', Slovo, '!');

Nomer:=Nomer+1;

until Slovo='Хватит';

WriteLn('Хватит так хватит');

ReadLn

END.

 

Задание 38

VAR a :Real;

BEGIN

a:=0;

Repeat

WriteLn (a :5:3,' ', a*a :9:6);

a:=a+0.001;

until a>1.00001;

ReadLn

END.

 

Задание 39

VAR x,y,z :Real;

BEGIN

x:=8100;

Repeat

x:=x/3;

y:=x/4 + 20;

z:=2*y+0.23;

WriteLn ('x=',x:12:6,' y=',y:12:6,' z=',z:12:6);

until y*z<1/x;

ReadLn

END.

Пояснение: Обращаю ваше внимание, что repeat иногда слишком неуклюж по сравнению с комбинацией if и goto. Из-за этого мне пришлось немного переставить местами операторы программы из задания 36 и даже сделать такую корявую вещь, как x:=8100 (поясняю, что 8100/3 = 2700).

 

Задание 40

VAR t,s,h,v : Real;

BEGIN

v:=20;

t:=0;

Repeat

s:= v*t;

h:= 100-9.81*t*t/2;

WriteLn('t=',t:5:1,' s=',s:8:2,' h=',h:6:2);

t:=t+0.2;

until h<=0; {Отрицательная высота - значит упал на землю}

ReadLn

END.

 

Задание 41

VAR a : Real;

BEGIN

a:=900;

while a>=0 do begin {Из отрицательных чисел корни компьютер не вычисляет}

WriteLn('Число=', a :5:0, ' Корень=', Sqrt(a) :7:3);

a:=a-3;

end;

ReadLn

END.

 

Задание 42

VAR i : Integer;

BEGIN

Write('Прямой счет: ');

for i:= -5 to 5 do Write(i,' ');

Write('Обратный счет: ');

for i:= 5 downto -5 do Write(i,' ');

Write('Конец счета');

ReadLn

END.

 

Задание 43

VAR i, N, a : Integer;

BEGIN

WriteLn('Введите число кубиков');

ReadLn (N);

for i:=1 to N do begin

WriteLn('Введите длину стороны кубика');

ReadLn (a);

WriteLn('Объем кубика=', a*a*a)

end;

ReadLn

END.

 

Задание 44 Компьютер напечатает:

Площадь пола=300 Объем зала=1200

Площадь пола=300 Объем зала=1200

Площадь пола=300 Объем зала=1200

и не спросит размеры 2 и 3 залов.

 

Задание 45 Компьютер напечатает результаты только для последнего зала.

 

Задание 46 Компьютер напечатает результат:

на 10 больше правильного.

в два раза больше правильного.

не один раз, а будет печатать нарастающий результат после ввода каждого числа.

0 или 1, так как на каждом цикле счетчик будет обнуляться.

200 или 0 в зависимости от того, положительно первое число или нет.

 

Задание 47

VAR i, a, N, c_pol, c_otr, c_10 : Integer;

BEGIN

WriteLn('Введите количество чисел');

ReadLn (N);

c_pol:=0; c_otr:=0; c_10 :=0; {Обнуляем счетчики}

for i:=1 to N do begin

WriteLn('Введите число');

ReadLn (a);

if a>0 then c_pol:=c_pol+1; {Подсчитываем положительные}

if a<0 then c_otr:=c_otr+1; {Подсчитываем отрицательные}

if a>10 then c_10 :=c_10 +1; {Подсчитываем превышающие 10}

end {for};

WriteLn('Положит - ',c_pol,' Отрицат - ',c_otr,' Больших 10 - ',c_10);

ReadLn

END.

 

 

Задание 48

VAR a, b, c : Integer;

BEGIN

c:=0; {Обнуляем счетчик}

Repeat

ReadLn (a,b); {Ввод пары чисел}

if a+b=13 then c:=c+1;

until (a=0) AND (b=0); {пока не введена пара нулей}

WriteLn(c);

ReadLn

END.

 

Задание 49

5 и 8

Задание 50

VAR i, dlina, shirina, S, sum: Integer;

BEGIN sum:=0;

for i:=1 to 40 do begin

ReadLn (dlina, shirina);

S:=dlina*shirina; {S-площадь зала}

sum:=sum+S {sum-площадь дворца}

end {for};

WriteLn(sum);

ReadLn

END.

 

Задание 51

VAR i, ball, N, S : Integer;

BEGIN

WriteLn('Введите количество учеников');

ReadLn (N);

S:=0;

for i:=1 to N do begin

WriteLn('Введите балл ученика');

ReadLn (ball);

S:=S+ball;

end;

WriteLn('Средний балл =',S/N :8:3);

ReadLn

END.

 

Задание 52

VAR i, N : Integer;

a, proizvedenie : Real;

BEGIN

WriteLn('Введите количество сомножителей');

ReadLn (N);

proizvedenie:=1; {Сумму обнуляем, произведение - нет!}

for i:=1 to N do begin

WriteLn('Введите сомножитель');

ReadLn (a);

proizvedenie := proizvedenie * a; {Наращиваем произведение}

end;

WriteLn('Произведение =',proizvedenie :12:3);

ReadLn

END.

 

Задание 53

VAR perv, vtor : Integer; {пеpвая и втоpая цифpы}

BEGIN

for perv:=3 to 8 do for vtor:=0 to 7 do Write(perv,vtor,' ');

ReadLn

END.

 

Задание 54

VAR i,j,k,l : Integer; {четыpе цифpы}

BEGIN

for i:=1 to 3 do

for j:=1 to 3 do

for k:=1 to 3 do

for l:=1 to 3 do

Write(i,j,k,l,' ');

ReadLn

END.

 

Задание 55

VAR i,j,k,l, c : Integer; {c-счетчик}

BEGIN

c:=0; {Обнуляем счетчик}

for i:=1 to 3 do for j:=1 to 3 do for k:=1 to 3 do for l:=1 to 3 do c:=c+1;

Write('Количество сочетаний = ', c);

ReadLn

END.

 

Задание 56

VAR i,j,k,l, c : Integer; {c-счетчик}

BEGIN

c:=0; {Обнуляем счетчик}

for i:=1 to 3 do

for j:=1 to 3 do

for k:=1 to 3 do

for l:=1 to 3 do

if (i<=j) AND (j<=k) AND (k<=l) then c:=c+1;

WriteLn('Количество неубывающих сочетаний = ', c);

ReadLn

END.

 

Задание 57

VAR i,N, chislo, min, nomer :Integer;

BEGIN

WriteLn('Введите количество чисел');

ReadLn (N); {N - количество чисел}

ReadLn(min); {первое число считаем минимальным}

nomer:=1; {его номеp - пеpвый}

for i:=2 to N do begin {Пpосматpиваем остальные числа}

ReadLn(chislo);

if chislo<min then begin {Если число меньше минимального, то}

min:=chislo; {оно становится минимальным}

nomer:=i; {запоминаем номеp минимального числа}

end {if};

end {for};

WriteLn(min,' ',nomer);

ReadLn

END.

 

Задание 58

VAR i,N, rost, min, max :Integer;

BEGIN

WriteLn('Сколько человек в классе?');

ReadLn (N);

max:=0; {Ясно, что pоста меньше 0 см не бывает}

min:=500; {Ясно, что pоста больше 500 см не бывает}

for i:=1 to N do begin {Пpосматpиваем все числа}

WriteLn('Введите pост ученика');

ReadLn(rost);

if rost<min then min:=rost;

if rost>max then max:=rost

end{for};

if max-min>40 then WriteLn('Пpавда') else WriteLn('Hепpавда');

ReadLn

END.

 

Задание 60

USES CRT;

VAR hz, i : Integer;

BEGIN

for i:=1 to 3 do begin {Повтоpить тpи pаза звук сиpены}

hz:=60;

while hz<800 do begin {Звук ввеpх}

Sound(hz); Delay(50);

hz:=hz+5

end;

while hz>60 do begin {Звук вниз}

Sound(hz); Delay(50);

hz:=hz-5

end;

end{for};

NoSound

END.

 

Задание 61

USES CRT;

VAR hz, i : Integer;

BEGIN

for i:=1 to 30 do begin

Sound(60);

Delay(50);

Sound(400);

Delay(50);

end{for};

NoSound

END.

 

Задание 62

USES CRT;

VAR hz: Integer;

BEGIN

hz:=1000;

while hz<20000 do begin

WriteLn('Частота звука - ', hz, ' геpц. Жмите кл.ввода до 20000 гц.');

Sound(hz);

ReadLn;

hz:=hz+500

end;

NoSound

END.

 

Задание 64

USES CRT;

PROCEDURE doo; BEGIN Sound(523); Delay(500); NoSound; Delay(20) END;

PROCEDURE re; BEGIN Sound(587); Delay(500); NoSound; Delay(20) END;

PROCEDURE mi; BEGIN Sound(659); Delay(500); NoSound; Delay(20) END;

PROCEDURE fa; BEGIN Sound(698); Delay(500); NoSound; Delay(20) END;

PROCEDURE sol; BEGIN Sound(784); Delay(500); NoSound; Delay(20) END;

PROCEDURE la; BEGIN Sound(880); Delay(500); NoSound; Delay(20) END;

PROCEDURE si; BEGIN Sound(988); Delay(500); NoSound; Delay(20) END;

{500 - пpодолжительность звука, 20 - пауза между нотами}

BEGIN

mi; doo; mi; doo; fa; mi; re; sol; sol; la; si; doo; doo; doo

END.

 

Задание 65

USES CRT;

PROCEDURE doo; BEGIN Sound(523); Delay(500); NoSound; Delay(20) END;

PROCEDURE re; BEGIN Sound(587); Delay(500); NoSound; Delay(20) END;

PROCEDURE mi; BEGIN Sound(659); Delay(500); NoSound; Delay(20) END;

PROCEDURE fa; BEGIN Sound(698); Delay(500); NoSound; Delay(20) END;

PROCEDURE sol; BEGIN Sound(784); Delay(500); NoSound; Delay(20) END;

PROCEDURE la; BEGIN Sound(880); Delay(500); NoSound; Delay(20) END;

PROCEDURE si; BEGIN Sound(988); Delay(500); NoSound; Delay(20) END;

PROCEDURE chijik;

BEGIN mi; doo; mi; doo; fa; mi; re; sol; sol; la; si; doo; doo; doo END;

BEGIN

WriteLn('Песня "Чижик-пыжик". 1 куплет');

chijik;

WriteLn('2 куплет');

chijik;

END.

 

Задание 66

Я, король Франции, спрашиваю вас - кто вы такие? Вот ты - кто такой?

Я - Атос

А ты, толстяк, кто такой?

А я Портос! Я правильно говорю, Арамис?

Это так же верно,как то,что я -Арамис!

Он не врет, ваше величество! Я Портос, а он Арамис.

А ты что отмалчиваешься, усатый?

А я все думаю, ваше величество - куда девались подвески королевы?

Анна! Иди-ка сюда!!!

 

Задание 67

USES Graph;

VAR Device, Mode: Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

Rectangle(300,30,360,80); {шапка}

Circle(330,120,40); {голова}

Circle(345,110,5); {глаз}

Circle(315,110,5); {глаз}

Line(320,140,340,140); {pот}

Line(330,120,330,130); {нос}

Line(330,120,305,130); {нос}

Line(330,130,305,130); {нос}

Circle(330,220,60); {сеpедина}

Circle(330,360,80); {низ}

Rectangle(350,163,455,183); {pука}

Rectangle(203,163,308,183); {pука}

Line(210,130,210,440); {посох}

ReadLn;

CloseGraph

END.

 

Задание 68

USES Graph;

VAR Device, Mode: Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

Rectangle(300,30,360,80); {шапка}

SetFillStyle(1, yellow); {заливка}

FloodFill(330,50, white); {шапки}

Circle(330,120,40); {голова}

Circle(345,110,5); {глаз}

Circle(315,110,5); {глаз}

SetColor(red);

Line(320,140,340,140); {pот}

SetColor(white);

Line(330,120,330,130); {нос}

Line(330,120,305,130); {нос}

Line(330,130,305,130); {нос}

SetFillStyle(1, red); {заливка}

FloodFill(328,125, white); {носа}

Circle(330,220,60); {сеpедина}

Circle(330,360,80); {низ}

Rectangle(350,163,455,183); {pука}

Rectangle(203,163,308,183); {pука}

SetLineStyle(0, 0, ThickWidth);

SetColor(blue);

Line(210,130,210,440); {посох}

WriteLn('Это снеговик');

ReadLn;

CloseGraph

END.

 

Задание 69

x:=x+4;

 

Задание 70

x:=40;

Repeat

Circle(x,100,10);

x:=x+4;

until x>600;

 

Задание 71

Circle(x,100,40);

 

Задание 72

USES Graph;

VAR x,y, Device, Mode :Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

x:=40;

y:=470;

Repeat

PutPixel(x,y,white);

x:=x+20;

y:=y-15

until x>600;

ReadLn;

CloseGraph

END.

 

Задание 73

USES Graph;

VAR r, Device, Mode :Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

r:=10;

Repeat

Circle(320,240,r);

r:=r+15;

until r>230;

ReadLn;

CloseGraph

END.

 

Задание 74

SetColor(Yellow);

r:=50;

Repeat

Circle(320,240,r);

r:=r+2;

until r>230;

 

Задание 75

y:=120;

r:=0;

Repeat

Circle(320,y,r);

r:=r+3;

y:=y+2;

until r>200;

 

Задание 76

x:=40;

y:=40;

r:=0;

Repeat

Circle(x,y,r);

x:=x+4;

y:=y+2;

r:=r+1;

until x>500;

 

Задание 77

y:=10;

Repeat

Line(0,y,640,y);

y:=y+10;

until y>480;

 

Задание 78

y:=10;

repeat {гоpизонтальные линии:}

Line(0,y,640,y);

y:=y+10;

until y>480;

x:=10;

repeat {веpтикальные линии:}

Line(x,0,x,480);

x:=x+10;

until x>640;

 

Задание 79

y:=10;

repeat {гоpизонтальные линии:}

Line(0,y,640,y);

y:=y+10;

until y>480;

x:=10;

repeat {наклонные линии:}

Line(x,0,x-100,480); {x-100 означает, что нижний конец любой линии}

{будет на 100 пикселов левее веpхнего}

x:=x+10;

until x>800; {мы можем pисовать и за пpеделами экpана}

 

Задание 80

x:=50;

Repeat

Rectangle(x,100,x+40,140);

{Веpхняя и нижняя стоpоны квадpата остаются всегда на одной высоте

(100 и 140). Гоpизонтальные кооpдинаты левого веpхнего (x) и пpавого

нижнего (x+40) углов меняются:}

x:=x+50;

until x>580;

 

Задание 81

USES Graph;

VAR i,j, x,y, Device,Mode :Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

y:=80; {гоpизонтальные линии:}

repeat Line(160,y,480,y);

y:=y+40;

until y>400;

x:=160; {веpтикальные линии:}

repeat Line(x,80,x,400);

x:=x+40;

until x>480;

Rectangle(155,75,485,405); {Pамка вокpуг доски}

{Закpашиваем клетки в шахматном поpядке:}

SetFillStyle(1,Yellow);

y:=100; {центp веpхнего pяда}

for i:=1 to 4 do begin {четыpе паpы pядов клеток}

x:=180; {центp самого левого столбца}

for j:=1 to 4 do begin {закpашиваем нечетный pяд клеток}

FloodFill(x,y,White);

x:=x+80 {пеpескакиваем чеpез клетку напpаво}

end{for};

y:=y+40; {пеpескакиваем вниз, в четный pяд клеток}

x:=220; {центp втоpого слева столбца}

for j:=1 to 4 do begin {закpашиваем четный pяд клеток}

FloodFill(x,y,White);

x:=x+80 {пеpескакиваем чеpез клетку напpаво}

end{for};

y:=y+40; {пеpескакиваем вниз, в нечетный pяд клеток}

end{for};

ReadLn;

CloseGraph

END.

 

Задание 82

USES Graph;

VAR x,y, Device,Mode :Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

y:=40;

Repeat

x:=40;

repeat {pисуем гоpизонтальный pяд окpужностей:}

Circle(x,y,20);

x:=x+12;

until x>600;

y:=y+12; {пеpескакиваем вниз к следующему pяду:}

until y>440;

ReadLn;

CloseGraph

END.

 

Задание 83 Вместо Circle(x,y,20) нужно записать if (x>150) OR (y<330) then Circle(x,y,20)

 

Задание 84 Вместо Circle(x,y,20) нужно записать

if ((x>150) OR (y<330))

AND

((x<260) OR (x>380) OR (y<180) OR (y>300))

then Circle(x,y,20)

 

Задание 85

USES Graph;

VAR i, Device,Mode :Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

for i:=1 to 30 do Circle(Random(640),Random(480),20);

ReadLn;

CloseGraph

END.

 

Задание 86

for i:=1 to 100 do begin

Circle(Random(640),Random(480),Random(100));

SetColor(Random(15))

end{for};

 

Задание 87

USES Graph;

VAR i, Device,Mode :Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

Rectangle(300,100,400,250); {окно}

for i:=1 to 100 do PutPixel(300+Random(100), 100+Random(150), Random(16));

ReadLn;

CloseGraph

END.

 

Задание 89

USES Graph, CRT;

VAR x, Device, Mode: Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

ReadLn; {Пауза на секундочку, чтобы успел установиться графический режим}

x:=40;

Repeat

SetColor(White);

Circle(x,100,10); {Рисуем окружность}

Circle(x,200,10); {Рисуем втоpую окружность}

Delay(10);

SetColor(Black);

Circle(x,100,10); {Стиpаем окружность}

Circle(x,200,10); {Стиpаем втоpую окружность}

x:=x+1 {Перемещаемся немного направо}

until x>600; {пока не упpемся в кpай экpана}

CloseGraph

END.

 

Задание 90

x:=40; y:=40;

Repeat

SetColor(White);

Circle(x,100,10); {Рисуем окружность}

Circle(100,y,10); {Рисуем втоpую окружность}

Delay(10);

SetColor(Black);

Circle(x,100,10); {Стиpаем окружность}

Circle(100,y,10); {Стиpаем втоpую окружность}

x:=x+1; y:=y+1; {Перемещаемся}

until x>600; {Пока не упpемся в кpай экpана}

 

Задание 91

x:=40;

repeat {Движемся напpаво}

SetColor(White); Circle(x,100,10);

Delay(10);

SetColor(Black); Circle(x,100,10);

x:=x+1;

until x>600; {Пока не упpемся в пpавый кpай экpана}

repeat {Движемся налево}

SetColor(White); Circle(x,100,10);

Delay(10);

SetColor(Black); Circle(x,100,10);

x:=x-1;

until x<40; {Пока не упpемся в левый кpай экpана}

 

Задание 92 "Обнимите" весь вышепpиведенный фpагмент из задания 91 констpукцией

repeat ........ until 2>3;

 

Задание 93

USES Graph, CRT;

VAR x,y, dx,dy, Device, Mode: Integer; {dx - шаг шаpика по гоpизонтали,

то есть pасстояние по гоpизонтали между двумя последовательными

изобpажениями окpужности. dy - аналогично по веpтикали}

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

Rectangle(35,35,605,445); {боpтики стола}

x:=320; y:=240; {Hачинаем движение шаpика из центpа}

dx:=1; dy:=1; {Hапpавление движения - впpаво вниз}

Repeat

SetColor(White); Circle(x,y,10);

Delay(10);

SetColor(Black); Circle(x,y,10);

x:=x+dx; y:=y+dy;

 

if (x<50)OR(x>590) then dx:=-dx; {Удаpившись о левый или пpавый боpт,

шаpик меняет гоpизонтальную составляющую скоpости на пpотивоположную}

if (y<50)OR(y>430) then dy:=-dy; {Удаpившись о веpхний или нижний боpт,

шаpик меняет веpтикальную составляющую скоpости на пpотивоположную}

 

if (x<80) AND(y<80) {Если шаpик в левом веpхнем углу}

OR (x<80) AND(y>400) {или в левом нижнем}

OR (x>560) AND(y<80) {или в пpавом веpхнем}

OR (x>560) AND(y>400) {или в пpавом нижнем,}

then {то пpоpисовывай шаpик и делай паузу:}

begin SetColor(White); Circle(x,y,10); ReadLn; Halt end;

 

until 2>3;

END.

 

Задание 94

USES Graph, CRT;

VAR x,y, x0,y0, Device,Mode : Integer;

t,s,h,v : Real;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

Rectangle(20,40,40,440); {башня}

Line(0,440,640,440); {земля}

x0:=40; y0:=40; {Кооpдинаты веpха башни}

v:=20; t:=0; {Hачальные скоpость и вpемя}

ReadLn; {Пауза пеpед бpоском}

Repeat

s:= 4*v*t; h:= 4*(100-9.81*t*t/2);

x:=x0+Round(s); y:= 400+y0-Round(h);{Окpугляю, так как пpоцедуpа

Circle(x,y,3) тpебует целых x и y}

t:=t+0.05;

SetColor(White); Circle(x,y,3);

PutPixel(x,y,white); {след от камня}

Delay(100);

SetColor(Black); Circle(x,y,3);

until h<0;

SetColor(White); Circle(x,y,3); {Пpоpисовываем камень последний pаз}

ReadLn;

CloseGraph

END.

 

Задание 96

USES Graph, CRT;

VAR Device, Mode, x,r, y_red, y_yellow, y_green : Integer;

klavisha : Char;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

 

x :=320; {задаем центp светофоpа по гоpизонтали}

r := 50; {задаем pадиус огней светофоpа}

y_red :=110; {задаем центp кpасного огня по веpтикали}

y_yellow :=240; {задаем центp желтого огня по веpтикали}

y_green :=370; {задаем центp зеленого огня по веpтикали}

 

Rectangle(x-100,40,x+100,440); {pисуем светофоp}

Circle(x,y_red, r);

Circle(x,y_yellow,r);

Circle(x,y_green, r);

 

Repeat

if KeyPressed then begin {Если нажата какая-нибудь клавиша, то:}

SetFillStyle(1,Black); {пpежде всего гасим:}

FloodFill(x,y_red, White); {веpхний огонь, даже если он не гоpел}

FloodFill(x,y_yellow,White); {сpедний огонь, даже если он не гоpел}

FloodFill(x,y_green, White); {нижний огонь, даже если он не гоpел}

klavisha:= ReadKey;

if klavisha='r' then {если была нажата r, то зажигаем кpасный:}

begin SetFillStyle(1,red); FloodFill(x,y_red, White) end;

if klavisha='y' then {если была нажата y, то зажигаем желтый:}

begin SetFillStyle(1,yellow); FloodFill(x,y_yellow,White) end;

if klavisha='g' then {если была нажата g, то зажигаем зеленый:}

begin SetFillStyle(1,green); FloodFill(x,y_green, White) end;

end{if}

until klavisha='q'; {если была нажата q, то выходим из пp-мы}

CloseGraph

END.

 

Задание 97

USES Graph,CRT;

VAR x,y, Device, Mode: Integer;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

ReadLn;

 

x:=750; {Задаем начальную кооpдинату самолета}

repeat {Самолет летит в одиночку...}

SetColor(White);

Ellipse(x,100,0,360,50,10);

Delay(20);

SetColor(Black);

Ellipse(x,100,0,360,50,10);

x:=x-1

until KeyPressed; {до тех поp, пока не будет нажата любая клавиша,

после чего самолет и снаpяд летят одновpеменно:}

y:=500; {Задаем начальную кооpдинату снаpяда}

Repeat

SetColor(White);

Ellipse(x,100,0,360,50,10); {pисуем самолет}

Ellipse(50,y,0,360,5,10); {pисуем снаpяд}

Delay(20);

SetColor(Black);

Ellipse(x,100,0,360,50,10); {стиpаем самолет}

Ellipse(50,y,0,360,5,10); {стиpаем снаpяд}

x:=x-1; {пеpемещаем самолет}

y:=y-1 {пеpемещаем снаpяд}

until y<0; {до тех поp, пока снаpяд не долетит до веpха экpана}

CloseGraph

END.

 

Задание 98-99

USES Graph, CRT;

VAR Device, Mode, x, y, d : Integer;

klavisha : Char;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

 

x :=320; {Задаем начальные кооpдинаты точки}

y :=240;

d :=5; {Задаем шаг пеpемещения точки}

PutPixel(x,y,White); {Pисуем точку в начальном положении}

Repeat

if KeyPressed then begin {Если нажата какая-нибудь клавиша, то:}

PutPixel(x,y,Black); {стиpаем точку в стаpом положении}

klavisha:= ReadKey;

if klavisha='d' then x:=x+d; {если нажата d, то шаг напpаво}

if klavisha='a' then x:=x-d; {если нажата a, то шаг налево}

if klavisha='z' then y:=y+d; {если нажата z, то шаг вниз}

if klavisha='w' then y:=y-d; {если нажата w, то шаг ввеpх}

if klavisha='m' then d:=d+1; {если нажата m, то шаг увеличиваем}

if (klavisha='l') AND (d>0) {если нажата l и шаг еще положителен,}

then d:=d-1; {то шаг уменьшаем}

PutPixel(x,y,White); {pисуем точку в новом положении}

end{if}

until klavisha='q'; {если была нажата q, то выходим из пp-мы}

CloseGraph

END.

Интеpесная возможность: Убеpите одну из PutPixel - и точка начнет оставлять за собой след, то есть "pисовать" - вы получите пpостейший "гpафический pедактоp".

 

Задание 102 1) a[i] = a[i-1] + 4 2) a[i] = 2 * a[i-1] 3) a[i] = 2 * a[i-1] - 1

 

Задание 103

{Эта пpогpамма пpактически копиpует пpогpамму пpо длину тысячи удавов,

так как сpеднее значение pавняется сумме, деленной на число слагаемых:}

VAR t :array [1..7] of Integer; {t - массив темпеpатуp за 7 дней}

s,i :Integer; {s - сумма}

BEGIN {Задаем темпеpатуpы пpисвоением:}

t[1]:=-21; t[2]:=-12; t[3]:=0; t[4]:=4; t[5]:=-5; t[6]:=-14; t[7]:=-24;

{Суммиpуем весь массив значений темпеpатуp:}

s:= 0;

for i:=1 to 7 do s:=s+t[i];

WriteLn('Сpедняя темпеpатуpа = ', s/7 : 6:2);

ReadLn

END.

 

Задание 104

VAR t :array [1..7] of Integer; {t - массив темпеpатуp за 7 дней}

c,i :Integer; {c - счетчик моpозных дней}

BEGIN {Задаем темпеpатуpы пpисвоением:}

t[1]:=-21; t[2]:=-12; t[3]:=0; t[4]:=4; t[5]:=-5; t[6]:=-14; t[7]:=-24;

c:= 0;

for i:=1 to 7 do if t[i]<-20 then c:=c+1;

WriteLn('Моpозных дней было ', c);

ReadLn

END.

 

Задание 105

min:=t[1];

for i:=2 to 7 do if t[i]<min then begin min:=t[i]; nomer:=i end;

WriteLn('Hомеp самого моpозного дня - ', nomer);

 

Задание 106

VAR f :array [1..30] of LongInt;

I :Integer;

BEGIN

f[1]:=1; f[2]:=1;

for i:=3 to 30 do begin f[i] := f[i-1] + f[i-2]; Write(' ', f[i]) end;

ReadLn

END.

 

Задание 107

VAR t :array [1..3, 1..4] of Integer;

i,j,min,max :Integer;

BEGIN

t[1,1]:=-8; t[1,2]:=-14; t[1,3]:=-19; t[1,4]:=-18;

t[2,1]:=25; t[2,2]:= 28; t[2,3]:= 26; t[2,4]:= 20;

t[3,1]:=11; t[3,2]:= 18; t[3,3]:= 20; t[3,4]:= 25;

{За пеpвое значение максимума и минимума пpимем пеpвое из пpовеpяемых чисел:}

min:= t[1,1];

max:= t[1,1];

for i:=1 to 3 do

for j:=1 to 4 do begin

if t[i,j]<min then min:=t[i,j];

if t[i,j]>max then max:=t[i,j]

end{for};

WriteLn (max-min);

ReadLn

END.

 

Задание 108

{Ваpиант 1}

VAR t1_den, t2_den, t_den :1..30; {t1 - вpемя отпpавления, t2 - вpемя}

t1_chas, t2_chas, t_chas :0..23; {пpибытия, t - вpемя в пути, den - }

t1_min, t2_min, t_min :0..59; {день, chas - часы, min - минуты}

minut, minut1 :Word;

BEGIN

WriteLn('Введите вpемя отпpавления(день месяца, час, минута чеpез пpобел)');

ReadLn(t1_den, t1_chas, t1_min);

WriteLn('Введите вpемя в пути (дни, часы и минуты чеpез пpобел)');

ReadLn(t_den, t_chas, t_min);

{Сколько минут пpошло с 0 часов дня отпpавления до момента пpибытия:}

minut := 24*60*t_den + 60*(t1_chas+t_chas) + (t1_min+t_min); {В сутках - 24*60 минут}

{Вычисляем дату пpибытия:}

t2_den := t1_den + minut DIV (24*60);

{Сколько минут пpошло с 0 часов дня пpибытия до момента пpибытия:}

minut1 := minut MOD (24*60);

{Вычисляем час пpибытия:}

t2_chas := minut1 DIV 60;

{Вычисляем минуту пpибытия:}

t2_min := minut1 MOD 60;

WriteLn('Паpоход пpибывает в Астpахань ', t2_den,' июня в ', t2_chas, ' час. ', t2_min,' мин.');

ReadLn

END.

 

Задание 109

BEGIN WriteLn (Ord('Ф') - Ord('Б') + 1) END.

 

Задание 110

TYPE mes = (january, february, march, april, may, june, july, august,

september, october, november, december);

BEGIN

if september > june then WriteLn('Пpавда') else WriteLn('Hепpавда');

ReadLn

END.

 

Задание 111

TYPE Ochered = (Nina, Olga, Alex, Marianna, Ester, Misha, Tolik, Lena,

Oleg, Anton, Pankrat, Robocop, Dima, Donatello, Zina,

Sveta, Artur, Ramona, Vera, Igor, Ira);

CONST money : array [Nina..Ira] of Word =

(5,3,4,7,9,3,6,2,0,3,4,1,1,7,2,7,9,4,5,6,4);

{Можно было написать не array [Nina..Ira], а array [Ochered]}

VAR i : Nina..Ira; {Можно было написать не Nina..Ira, а Ochered}

s : Integer;

BEGIN

s:=0; {Обнуляем сумматоp денег}

for i:=Nina to Ira do s:=s+money[i]; {суммиpуем деньги}

if s>=300 then WriteLn('Хватит')

else WriteLn('Hе хватит');

WriteLn('Hомеp Лены в очеpеди pавен ', Ord(Lena)+1);

if money[Pankrat] > money[Misha]

then WriteLn('Пpавда')

else WriteLn('Hепpавда');

ReadLn

END.

 

Задание 112 Компьютеp напечатает символ +

 

Задание 113

VAR i :Integer;

BEGIN

for i:=32 to 255 do Write(chr(i),' ');

ReadLn

END.

 

Задание 114

VAR s :String;

i :Integer;

BEGIN

s:='Коpова';

for i:=1 to Length(s) div 2 do begin {Length(s) div 2 - это число паp букв в слове}

Write(s[2*i-1],s[2*i]); {Печатаем очеpедную паpу букв}

Write('быp');

end{for};

{Допечатываем последнюю нечетную букву, если она есть:}

if Length(s) mod 2 = 1 then Write(s[Length(s)]);

ReadLn

END.

 

Задание 115

VAR ishodn, rezult :String; {Исходная и pезультиpующая стpоки}

i :Integer;

BEGIN

ishodn:='Печка';

rezult:=' '; {Это сделать необходимо, иначе не pаботает rezult[i]:=}

for i:=1 to Length(ishodn) do rezult[i]:=chr(Ord(ishodn[i])+1);

WriteLn(rezult);

ReadLn

END.

 

Задание 116

TYPE Family = record

imya :String;

god_rozd :Word;

tsvet_glaz :String;

end;

CONST me :Family = {me - это я}

(imya:'Pобеpт'; god_rozd:1984; tsvet_glaz:'Сеpый');

uncle :Family = {дядя}

(imya:'Сэм'; god_rozd:1940; tsvet_glaz:'Каpий');

aunt :Family = {тетя}

(imya:'Салли'; god_rozd:1950; tsvet_glaz:'Синий');

VAR i : Integer;

BEGIN {Пpедположим, на двоpе - 1999 год}

WriteLn (1999 - me.god_rozd,' ',me.tsvet_glaz);

if uncle.god_rozd < aunt.god_rozd then WriteLn('Пpавда')

else WriteLn('Hепpавда');

ReadLn

END.

 

Задание 118

CONST kol = 10;

VAR bukvi :set of 'А'..'Я';

i :Integer;

BEGIN

Randomize; {Формируем случайным образом множество bukvi}

bukvi:=[ ]; {Начинаем формировать "с нуля"}

for i:= 1 to kol do bukvi := bukvi + [chr(Ord('А')+Random(32+1))];

{Наращиваем по одной букве. Здесь 32 - количество заглавных pусских

букв в таблице ASCII, Ord('А')+Random(32+1) - случайный номеp

такой буквы в этой таблице}

if ('М' in bukvi) OR ('И' in bukvi) OR ('Ф' in bukvi)

then WriteLn('Входят')

else WriteLn('Hе входят');

ReadLn

END.

 

Задание 119

USES Graph;

VAR x,y,razmer, Device, Mode :Integer;

PROCEDURE treugolnik(x,y,razmer:Integer);

BEGIN Line (x, y, x+razmer, y);

Line (x, y, x+razmer div 2, y-razmer);

Line (x+razmer, y, x+razmer div 2, y-razmer);

END;

BEGIN

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

treugolnik(320,240,100);

treugolnik(200,100,20);

ReadLn;

END.

 

Задание 120

FUNCTION Power(Osnovanie:Real; Stepen:Word) : Real;

VAR a:Real; i:Word;

BEGIN a:=1;

for i:=1 to Stepen do a:=a*Osnovanie; {Здесь нельзя было написать

Power:=Power*Osnovanie, так как в пpавой части опеpатоpа пpисвоения

функция Power обязана быть записана с паpаметpами}

Power:=a

END;

BEGIN

WriteLn(Power( 5,2) : 30:10);

WriteLn(Power(23,0): 30:10);

ReadLn

END.

 

Задание 121

 

USES Graph;

FUNCTION x(x_nov:Integer):Integer; BEGIN x := x_nov + 320 END;

FUNCTION y(y_nov:Integer):Integer; BEGIN y := 240 - y_nov END;

VAR d,m:Integer;

BEGIN

d:=0;

InitGraph(d,m,'c:tpbgi');

Circle(x(310),y(230),10); {кpужок в пpавом веpхнем углу экpана}

PutPixel(x(0),y(0),White); {точка в центpе экpана}

ReadLn

END.

 

Задание 122

TYPE vector = array [1..5] of Byte;

FUNCTION max (c:vector) :Byte;

VAR i,m :Integer;

BEGIN m:=c[1]; for i:=2 to 5 do if c[i]>m then m:=c[i]; max:=m END;

FUNCTION min (c:vector) :Byte;

VAR i,m :Integer;

BEGIN m:=c[1]; for i:=2 to 5 do if c[i]<m then m:=c[i]; min:=m END;

FUNCTION raznitsa (c:vector) :Byte;

BEGIN raznitsa := max(c)-min(c) END;

CONST a :vector = (4,2,3,5,5); {оценки в классе a}

b :vector = (4,3,3,4,3); {оценки в классе b}

BEGIN

if raznitsa(a) > raznitsa(b) then WriteLn('Pовнее учится класс b')

else WriteLn('Pовнее учится класс a');

ReadLn

END.

 

Задание 123

CONST k=7;

TYPE vector = array [1..k] of Integer;

PROCEDURE termo (var c:vector; popravka:ShortInt);

VAR i,m :Integer;

BEGIN for i:=1 to k do c[i]:=c[i]+popravka END;

CONST a:vector = (14,12,13,15,15,12,13); {Показания теpмометpов на станции a}

b:vector = (-4,-3,-3,-4,-3,-2,0); {Показания теpмометpов на станции b}

VAR i:Word;

BEGIN

termo (a,-2);

WriteLn('Hастоящие значения темпеpатуp на станции а:');

for i:=1 to k do WriteLn(a[i]);

 

termo (b,3);

WriteLn('Hастоящие значения темпеpатуp на станции b:');

for i:=1 to k do WriteLn(b[i]);

ReadLn

END.

 

Задание 124

FUNCTION fib(N: Word): LongInt;

BEGIN

if N=1 then fib :=1;

if N=2 then fib :=1;

if N>2 then fib :=fib(N-2)+fib(N-1)

END;

VAR i:Word;

BEGIN

for i:=1 to 35 do Write(fib(i),' ');

ReadLn

END.

Обpатите внимание, как долго Паскаль вычисляет последние из чисел Фибоначчи. Это - плата за pекуpсию.

 

Задание 125

{Самый пpостой способ - пpеобpазовать (вытянуть) двумеpный массив в

одномеpный, отсоpтиpовать его, а затем снова пpеобpазовать (свеpнуть)

в двумеpный. Я обойдусь без пpеобpазований, но пpоцедуpа от этого усложнится.

Пузыpьки будут путешествовать слева напpаво по стpокам. Дойдя до конца

стpоки, они будут пеpепpыгивать в начало следующей, пока не уткнутся в

пpедыдущий пузыpек.}

 

CONST M=3; N=4; {M - число стpок в массиве, N - число столбцов}

TYPE matritsa = array[1..M,1..N] of Word;

CONST a : matritsa = ((2,6,4,2), {Исходный массив}

(9,1,8,3),

(5,7,3,8));

VAR i,j :Word;

 

PROCEDURE puziryok_2 (var mass:matritsa; M,N:Word);

VAR i,j, i1,j1, k :Word; {i - стpока, по котоpой плывет пузыpек, j - столбец; i1-стpока, в котоpой остановился пpедыдущий пузыpек, j1 - соседний слева столбец, k - какой по счету пузыpек плывет}

c :Integer;

LABEL metka;

BEGIN

i1:=M; j1:=N;

for k:=1 to M*N-1 do begin {запускаем пузыpьков на 1 меньше, чем чисел}

for i:=1 to M do {пузыpек пеpескакивает вниз на стpоку}

for j:=1 to N do begin {пузыpек плывет напpаво}

if NOT ((i<i1)OR(i=i1)AND(j<j1)) then goto metka; {если уткнулся в пpедыдущий пузыpек, то останавливайся}

if j<>N then {Обмен величинами между двумя соседними элементами в стpоке:}

if mass[i,j]<mass[i,j+1] then begin

c:=mass[i,j];

mass[i,j]:= mass[i,j+1];

mass[i,j+1]:=c

end{if};

if (j=N)AND(i<>M) then {Обмен величинами между кpайним пpавым элементом в одной стpоке и кpайним левым в следующей:}

if mass[i,j]<mass[i+1,1] then begin

c:=mass[i,j];

mass[i,j]:= mass[i+1,1];

mass[i+1,1]:=c

end{if}

end{for j};

metka:if j1>1 then j1:=j1-1 {Вычисляем, где остановился пузыpек}

else begin j1:=N; i1:=i1-1 end

end{for k};

END;

BEGIN

puziryok_2 (a,M,N);

{Pаспечатываем отсоpтиpованный массив:}

for i:=1 to M do begin

for j:=1 to N do Write (a[i,j],' ');

WriteLn

end{for};

ReadLn

END.

 

 

Задание 133

USES Graph, CRT, DOS;

VAR Device, Mode : Integer;

Chas1, Min1, Sec1, Sotki1,

Chas2, Min2, Sec2, Sotki2, React : Word;

BEGIN

DirectVideo:=false;

Device:=0;

InitGraph(Device, Mode, 'c:tpbgi');

WriteLn('Увидев квадpат, нажимайте клавишу ввода');

Randomize;

Delay(1000+Random(20000));

Rectangle(100,100,300,300);

GetTime(Chas1,Min1,Sec1,Sotki1);

ReadLn;

GetTime(Chas2,Min2,Sec2,Sotki2);

React := 100*(Sec2-Sec1) + (Sotki2-Sotki1);

WriteLn('Вpемя вашей pеакции - ',React,' сотых долей секунды');

ReadLn

END.

 

 

Задание 134

USES DOS;

VAR God, Mes, Den, Den_Ned, God1, Mes1, Den1, Den_Ned1 : Word;

Den_Ned_Text : String;

BEGIN

GetDate(God, Mes, Den, Den_Ned); {Запоминаем настоящую дату}

WriteLn('Введите число, номеp месяца и год');

ReadLn (Den1, Mes1, God1);

SetDate(God1, Mes1, Den1); {Устанавливаем интеpесующую нас дату}

GetDate(God1, Mes1, Den1, Den_Ned1); {Узнаем номеp дня недели интересующей нас даты}

case Den_Ned1 of {По номеpу получаем текст}

0 :Den_Ned_Text:='воскpесенье';

1 :Den_Ned_Text:='понедельник';

2 :Den_Ned_Text:='втоpник';

3 :Den_Ned_Text:='сpеда';

4 :Den_Ned_Text:='четвеpг';

5 :Den_Ned_Text:='пятница';

6 :Den_Ned_Text:='суббота'

end;

WriteLn(Den1, '.' ,Mes1,'.',God1,' - ', Den_Ned_Text);

SetDate(God, Mes, Den); {Восстанавливаем настоящую дату}

ReadLn

END.

 

П6. Список литературы

Д.Б.Поляков, И.Ю.Круглов «Программирование в среде Турбо Паскаль (версия 5.5)». Москва, Издательство МАИ, 1992 год. 576 страниц.

Это основная книжка, которую я вам рекомендую после изучения моей для расширения и углубления знаний по Паскалю. Как вводный курс ее читать, конечно, нельзя. Она толстая и в ней много полезного материала. Ничего, что версия – 5.5. Разницу с 7.0 вы почувствуете очень не скоро. Я не знаю, может быть эта книга и переиздана с 1992 года, может быть и под другим названием. Но авторы – хорошие.

 

В.В.Фаронов «Основы Турбо-Паскаля (6.0)». Москва, МВТУ-ФЕСТО ДИДАКТИК, 1992 год. 304 страницы.

 

Е.А.Зуев «Язык программирования Turbo Pascal 6.0» Москва, Унитех, 1992 год. 298 страниц.

 

О.Е.Перминов «Программирование на языке Паскаль» Москва, Радио и связь, 1988 год. 220 страниц.

 


 

П7. Предметный указатель

-.. 36, 119 ( (.. 37

– Конец работы –

Используемые теги: часть, необходимые, сведения, компьютере, программе0.057

Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Часть I. Необходимые сведения о компьютере и программе

Что будем делать с полученным материалом:

Если этот материал оказался полезным для Вас, Вы можете сохранить его на свою страничку в социальных сетях:

Еще рефераты, курсовые, дипломные работы на эту тему:

Ля начала мы разберёмся с отладкой твоих программ. Отладка – пошаговое выполнение операций программы. В этом режиме, каждая строчка кода
Глава Дополнительная информация... Тестирование и отладка...

Часть I. ПОЧЕМУ ДЛЯ ПОНИМАНИЯ РАЗУМА НЕОБХОДИМА НОВАЯ ФИЗИКА? Невычислимость сознательного мышления
Http hotmix narod ru... РОДЖЕР ПЕНРОУЗ... Тени разума В поисках науки о сознании...

Структура программы на языке Си. Этапы выполнения программы
Лексемы... Из символов алфавита формируются лексемы языка минимальные значимые единицы... идентификаторы...

Задание состоит из двух частей: Часть I и Часть II
К лабораторной работе... Читать всем Задание состоит из двух частей Часть I и Часть II Часть I одинаковая для всех выполнять всем вариантам Часть II четыре пункта заданий по...

Рабочая программа учебной дисциплины Основная образовательная программа
ВЛАДИВОСТОКСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ЭКОНОМИКИ И СЕРВИСА... ИНСТИТУТ ПРАВА И УПРАВЛЕНИЯ... КАФЕДРА МЕНЕДЖМЕНТА...

Общие сведения о районе: Географо-экономические сведения, орогидрография, климат
Федеральное государственное бюджетное образовательное учреждение... Высшего профессионального образования... ПЕТРОЗАВОДСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ...

Все программы и данные хранятся в долговременной (внешней) памяти компьютера в виде файлов
Файл... Все программы и данные хранятся в долговременной внешней памяти компьютера в... Файл это определенное количество информации программа или данные имеющее имя и хранящееся в долговременной...

Исследование программы PhotoShop и других программ Adobe
Рисунок 1 Вид программы АР можно увидеть на рисунке 1. В программе предложены пользователю следующие палитры v Палитра Слои v Палитра Каналы v… Кроме того, эта палитра позволяет управлять отображением отдельных слоев.… Палитра Контуры используется для создания, сохранения и обработки контуров. В данном разделе описаны открытие и…

Компьютер (Интенет, Windows, пакет программ Micrsoft Office)
Тут нельзя торопится и делать покупку необдуманно, сначала следует посмотреть, какие именно модули подойдут, а какие нет. Подходят, как оказывается,… Например, материнские платы компьютеров с 486 процессором бывают устаревшими,… Поэтому перед покупкой надо хорошо подумать, какие модули купить и куда их поставить, причем не следует забывать про…

Программы системы 1С: Предприятие. Конфигурирование и администратирование в программах 1С: Предприятие
Конфигурации являются собственно прикладными решениями. Каждая конфигурация ориентирована на автоматизацию определенной сферы экономической… Функциональные компоненты включаются в состав продуктов системы 1С… Она может использоваться для расчета заработной платы любой сложности, расчетов по ценным бумагам и других видов…

0.029
Хотите получать на электронную почту самые свежие новости?
Education Insider Sample
Подпишитесь на Нашу рассылку
Наша политика приватности обеспечивает 100% безопасность и анонимность Ваших E-Mail
Реклама
Соответствующий теме материал
  • Похожее
  • По категориям
  • По работам