75
§1. Первое знакомство с системой программирования Турбо Паскаль Турбо Паскаль появился на рынке программных продуктов в 1984 году и совершил настоящую революцию в программировании. До этих пор при обучении программированию предпочтение чаще всего отдавалось Бейсику простому, дешевому и легко осваиваемому. Паскаль же был аппаратно зависимым, дорогим и сложным. С появлением Турбо Паскаля положение изменилось. Турбо Паскаль состоит из языка программирования и среды, которая обеспечивает удобную и производительную работу. Изучение Паскаля как языка программирования идет вместе с изучением всей системы Турбо Паскаль. Язык программирования Паскаль был разработан Н.Виртом в 1968−1970 годах и получил широкое распространение благодаря наглядности программ и легкости изучения. Он послужил основой для разработки других языков программирования (например, Ада, Модула−2). Первая версия Турбо Паскаля использовалась не очень долго − она появилась в 1983 году, а уже в 1984 году ее заменила вторая версия, которая получила широкое распространение. К осени 1985 года появляется третья версия, еще более удобная в работе. Четвертая версия (1988 год) представила Турбо Паскаль в новом виде (появилась новая среда, компилятор стал встроенным). Осенью этого же года вышла пятая версия, в которой появился встроенный отладчик. А в 1989 году появилась версия 5.5, позволившая перейти к объектно−ориентированному программированию. Шестая версия уже обеспечивала многооконный и многофайловый режим работы, использование мыши, применение объектно−ориентированного программирования, обладала встроенным ассемблером и имела другие возможности. В 1992 году фирма Borland International выпустила два пакета программирования на языке Паскаль − это Borland Pascal 7.0 и Turbo Pascal 7.0. Пакет Turbo Pascal 7.0 использует новейшие достижения в программировании. Он может использоваться практически на любой машине и относительно дешев. Язык этой версии обладает широкими возможностями, имеет большую библиотеку модулей. Среда программирования позволяет создавать тексты программ, компилировать их, находить и исправлять ошибки, компоновать программы из отдельных частей, использовать модули, отлаживать и выполнять программы. §2. Основные элементы языка Язык Турбо Паскаль состоит приблизительно из 80 зарезервированных слов и специальных символов. Алфавит языка составляют буквы латинского алфавита, цифры, а также специальные символы, такие, например, как +, -, *. Специальными символами языка являются и некоторые пары символов. Зарезервированные слова, такие как Program, Begin, End, Writeln, Readln и т. д., в языке Паскаль могут применяться только по своему прямому назначению, то есть в качестве имен операторов, названий операций и т. д. Кроме зарезервированных слов в программах на языке Паскаль используются как отдельные символы, так и пары символов, которые имеют специальное назначение. Перечень таких символов: := Присваивание переменной значения выражения. ; Разделитель операторов в программе. ( )Скобки для арифметических и логических выражений. : Разделитель в описаниях переменных и формате операторов вывода. .. Многоточие для списков. + Бинарные операции (не только арифметические). - * / = Логическое равенство, элемент описания констант 3

1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

§1. Первое знакомство с системой программирования Турбо Паскаль

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

Язык программирования Паскаль был разработан Н.Виртом в 1968−1970 годах и получил широкое распространение благодаря наглядности программ и легкости изучения. Он послужил основой для разработки других языков программирования (например, Ада, Модула−2).

Первая версия Турбо Паскаля использовалась не очень долго − она появилась в 1983 году, а уже в 1984 году ее заменила вторая версия, которая получила широкое распространение. К осени 1985 года появляется третья версия, еще более удобная в работе.

Четвертая версия (1988 год) представила Турбо Паскаль в новом виде (появилась новая среда, компилятор стал встроенным). Осенью этого же года вышла пятая версия, в которой появился встроенный отладчик. А в 1989 году появилась версия 5.5, позволившая перейти к объектно−ориентированному программированию.

Шестая версия уже обеспечивала многооконный и многофайловый режим работы, использование мыши, применение объектно−ориентированного программирования, обладала встроенным ассемблером и имела другие возможности.

В 1992 году фирма Borland International выпустила два пакета программирования на языке Паскаль − это Borland Pascal 7.0 и Turbo Pascal 7.0.

Пакет Turbo Pascal 7.0 использует новейшие достижения в программировании. Он может использоваться практически на любой машине и относительно дешев. Язык этой версии обладает широкими возможностями, имеет большую библиотеку модулей. Среда программирования позволяет создавать тексты программ, компилировать их, находить и исправлять ошибки, компоновать программы из отдельных частей, использовать модули, отлаживать и выполнять программы.

§2. Основные элементы языка

Язык Турбо Паскаль состоит приблизительно из 80 зарезервированных слов и специальных символов. Алфавит языка составляют буквы латинского алфавита, цифры, а также специальные символы, такие, например, как +, -, *. Специальными символами языка являются и некоторые пары символов. Зарезервированные слова, такие как

Program, Begin, End, Writeln, Readln и т. д., в языке Паскаль могут применяться только по своему прямому назначению, то есть в качестве имен операторов, названий операций и т. д.

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

выражений.: Разделитель в описаниях переменных и формате

операторов вывода... Многоточие для списков.+ Бинарные операции (не только арифметические).-*/= Логическое равенство, элемент описания констант

и типов.<> Логическое неравенство.< > Отношения «меньше чем» и «больше чем».<= Отношение «меньше или равно».>= Отношение «больше или равно».. Конец программы или модуля.' Ограничители константы строкового типа.{ } Пары скобок для комментариев.(* *) Пары скобок для комментариев., Разделитель элементов списка.[ ] Скобки для ссылки на элемент массива или

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

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

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

3

Page 2: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

действительных чисел.Действительные числа изображаются в

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

4.7 -0.71 +151.75150.0 0.00067 0.0

Примеры неправильно записанных чисел:15. – оканчивается точкой;.65 – начинается с точки;155.27.54 – содержит две точки.Экспоненициальная (полулогарифмическая) форма

записи используется для представления очень больших и очень маленьких чисел, которые нелегко изобразить обычной десятичной записью. Например, масса покоя электрона приблизительно равна 9,1*10-31кг. При записи таких чисел в языке Паскаль часть числа, которая читается как "умножить на десять в степени", обозначается буквой Е и число в программе выглядит следующим образом: 9.1Е-31. Цифры, предшествующие букве Е, образуют мантиссу числа, цифры, следующие за буквой Е, порядок. Следует помнить, что при написании числа мантисса не должна отсутствовать или начинаться и оканчиваться точкой.

Примеры правильно записанных чисел в экспоненциальной форме:

-0.131Е5 50Е7 -5Е-02 123.7Е-5Примеры неправильно записанных чисел в

экспоненциальной форме:Е-05 – отсутствует мантисса;-5.Е02 – мантисса числа оканчивается точкой;-Е12 – отсутствует мантисса.Строка – это последовательность символов языка,

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

Примеры строк: 'A', 'Таблица значений', 'контрольная работа по курсу информатики', 'XYZ', '575', '0.5+17E-5'.

Примеры неверно записанных строк:'CONST – нет конечного апострофа;PROGRAM – отсутствуют апострофы;'15.8'E5 – апостроф стоит не в конце строки;'+*.;" – не хватает еще одного апострофа в

конце строки.Используются строки для работы с текстами,

например для вывода текстов и комментариев на печать. Максимальная длина строки определяется конкретной реализацией языка.

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

превышала 6−8 символов.Выбор имени следует осуществлять исходя из

логической или физической сущности обозначаемого объекта, при этом рекомендуется придерживаться следующих правил:

1) в пределах области определения имя должно быть уникальным (каждому имени должен соответствовать лишь один обозначаемый объект и наоборот), в противном случае соответствие между именем и обозначаемым объектом будет неоднозначным;

2) в качестве имен не разрешается использовать служебные слова;

3) в языке определен некоторый набор заранее предопределенных имен, их называют стандартными; программист может переопределить эти имена (использовать не по стандартному назначению), но делать это не рекомендуется;

4) длинные имена или имена, состоящие из нескольких слов, следует сокращать;

5) следует избегать схожих по виду имен (АХ1 и AXI), подобных по написанию символов в пределах одного идентификатора (DO20, где второй символ – буква О, последний – цифра 0);

6) если в имени нужно использовать цифры, то лучше писать их в конце идентификатора (А32, REG15).

Имена используются для обозначения данных – величин, над которыми производятся некоторые действия. Постоянные величины, значения которых не меняются в процессе выполнения программы, называются константами. Константы в программе могут быть представлены либо непосредственно своим значением (числом, строкой), либо именем. Для некоторых констант в языке определены стандартные имена: FALSE, TRUE, MAXINT,

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

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

§3. Команды редактора

Команды управления движением курсора− перемещение курсора на символ вправо;

− перемещение курсора на символ влево;

− перемещение курсора на строку вверх;

− перемещение курсора на строку вниз;

[Home] − перемещение курсора в начало текущей строки;

4

Page 3: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

[End] − перемещение курсора в конец текущей строки;

[Page Up] − перемещение курсора на страницу вверх;

[Page Down] − перемещение курсора на страницу вниз;

Примечание. Страница − это один экран (21 строка).

[Ctrl^Home] − перемещение курсора в левый верхний угол экрана;

[Ctrl^End] − перемещение курсора в левый нижний угол экрана.

Команды вставки и удаления текста[Insert] − включение и выключение режима

вставки;Примечание. Если режим вставки включен, то

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

[Delete] − удаление символа, стоящего в позиции курсора;

[Back Space] − удаление символа, стоящего слева от курсора;

Примечание. Иногда на этой клавише написано <BS>, а иногда это стрелка [←], расположенная над клавишей ввода [Enter]).

[Ctrl^N] − вставка пустой строки над строкой, в которой находится курсор;

[Ctrl^Y] − удаление строки, в которой находится курсор.

§4. Первая программа

Программа начинается с заголовка, имеющего следующий вид;

Program <имя программы>;За ним идут разделы описаний, в которых должны

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

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

Разбор примераProgram Proizvedenie_1;Var a,b,rez: Integer;Begin

Writeln('Введите два числа через пробел');

Readln(a, b);rez:=a*b;

Writeln('Их произведение равно ',rez);Writeln('Нажмите <Enter>');Readln;

End.Пояснения к программе

Имя этой программы Proizvedenie_1. Заметим, что в имени программы не должно быть пробелов, оно должно начинаться с буквы, состоять только из латинских букв, цифр и некоторых специальных символов (в нашем примере использован символ "подчеркивание"). Из разделов описаний имеется лишь один − раздел описания переменных. Он начинается со служебного слова Var, после которого идет последовательность объявлений переменных, разделенных точкой с запятой. В каждом объявлении перечисляются через запятую имена переменных одного типа, после чего ставится двоеточие и указывается тип переменных. В нашем примере описаны три переменные: все они (a, b и rez) имеют целый тип (integer), то есть значения переменных этого типа − целые числа.

После раздела описаний переменных идет раздел операторов, начинающийся со служебного слова Be-gin, после которого расположены операторы языка. Первый оператор − это Writeln('текст') − записать (вывести) на экран текст, заключенный между апострофами, Ln добавляется в конце этого оператора для того, чтобы курсор автоматически переходил в начало следующей строки.

Следующий оператор − Readln(a,b) − читать данные с клавиатуры. В данном случае необходимо ввести два целых числа через пробел, тогда переменной а присваивается значение, равное первому введенному числу, а переменной b присваивается значение, равное второму введенному числу. Например, вы ввели числа 12 и 45, тогда а=12, а b=45. В конце этого оператора также можно ставить Ln.

После этих двух операторов стоит оператор присваивания: rez:=a*b; (:= − это знак присваивания в языке Паскаль). При выполнении этого оператора переменная rez получит значение, равное произведению числа а на число b. Так как в результате умножения двух целых чисел получается целое число, то переменная rez описана как целая (integer).

Следующий оператор − это снова оператор вывода Writeln('текст', rez) − он выведет на экран текст, заключенный между апострофами, а за ним значение переменной rez. Затем следующий оператор − Writeln − выведет на экран сообщение <Нажмите [Enter]>, а оператор Readln будет ожидать нажатия указанной клавиши. В конце раздела операторов стоит служебное слово End, после которого ставится точка.

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

5

Page 4: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

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

Важной частью исходного текста программы являются комментарии. Комментарий представляет собой текст, который находится между фигурными скобками { } или между парами символов, состоящими из круглой скобки и звездочки (* *). Комментарии позволяют включить подробное описание программы и пояснения к ней прямо в исходный текст. Грамотное и уместное применение комментариев упрощает понимание программы, облегчает жизнь ее автору и программистам, работающим с уже готовым текстом. У фигурных скобок есть и нестандартное применение во время отладки программы часто возникает необходимость временно убрать из программы какие-то операторы, сохранив, тем не менее, их запись. Простейший способ − заключить соответствующий фрагмент программы в фигурные скобки.

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

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

ввести два целых числа через пробел и нажать клавишу [Enter]. Появится сообщение:

Их произведение равно...Вместо точек будет напечатано значение

переменной rez, то есть число, равное произведению первого введенного числа на второе. Это сообщение останется на экране до тех пор, пока не будет нажата клавиша [Enter].

Сохранение программыДля того чтобы сохранить программу, необходимо

выйти в главное меню и выбрать пункт File. Затем в появившемся вертикальном меню надо выбрать пункт Save as... Появится окно, в котором можно ввести имя файла. Например, а:\prim1_1. pas; здесь а: − это название диска, "\" − каталог (корневой), prim1_1 − имя файла (оно может содержать не более

8 символов), .pas − расширение, указывающее, что файл содержит программу, написанную на языке Паскаль.

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

* = + [ ] \ | ;:,.<>/?. Также не следует использовать в именах файлов

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

клавишу [Enter].Примечание. Для быстрого сохранения файла

можно воспользоваться командами Save или Save all меню File.

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

§5. Управление позициями и цветом вывода

К программам в языке Паскаль можно подключать библиотечные модули, в которых находятся множество процедур для работы с экраном в текстовом режиме, реализации графических возможностей Паскаля и др. Модули поставляются вместе с системой программирования Паскаль, а также могут создаваться программистом для собственных программ. Один из модулей, к которому вы часто будете обращаться − это модуль CRT, который содержит процедуры для работы с экраном в текстовом режиме. Для подключения модуля после заголовка программы запишите оператор использования Uses и после него используемый модуль, например Uses CRT.

В модуле CRT имеется процедура позиционирования курсора, который позволяет установить координаты вывода информации на экран (номер строки y и номер столбца x). Экран при этом представляется в виде прямоугольной сетки знакомест размером 80 столбцов и 25 строк с началом отсчета в левом верхнем углу.

Оператор позиционирования имеет следующий вид:

GotoXY(x,y).Этот оператор устанавливается непосредственно

перед выводом информации.Для изменения цвета выводимой информации в

модуле CRT реализованы операторы изменения параметров цвета символов и знакомест:

TextColor(c1); TextBackGround(c2).Здесь с1 означает цвет символа (может менять

значение от 0 до 15), с2 − цвет фона этого символа (0...7) из стандартной таблицы цветов. В Паскале эти значения могут задаваться как встроенными константами (yellow, red,...), так и их числовыми эквивалентами (14, 4) (кодами).

Цвет Константа КодЧерныйСинийЗеленыйБирюзовыйКрасный

BlackBlueGreenCyanRed

01234

6

Page 5: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

МалиновыйКоричневыйСветло-серыйТемно-серыйСветло-синийСветло-зеленыйСветло-бирюзовыйСветло-красныйСветло-малиновыйЖелтыйБелый

MagentaBrownLightGrayDarkGrayLightBlueLightGreenLightCyanLightRedLightMagentaYellowWhite

56789101112131415

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

Program Proizvedenie_1;Uses CRT;Var a,b,rez: Integer;Begin

ClrScr;TextColor(Yellow);TextBackGround(Red);Writeln('Введите два числа через

пробел');Readln(a, b);rez:=a*b;Writeln('Их произведение равно ', rez);GotoXY(30,15);Writeln('Нажмите <Enter>');Readln;

End.

§6. Арифметический квадрат.Абсолютная величина

Функция SQR(х) возвращает квадрат значения аргумента, то есть SQR(х)=х2=х*х.

Примеры:sqr(4)=42=16;при х=13, sqr(х)=sqr(13)=132=169;npu d=2, e=5, sqr(d+e)=sqr(2+5)=sqr(7)=49;при x=3, sqr(sqr(x))=sqr(sqr(3))=sqr(9)=81.

Функция ABS(х) возвращает абсолютную величину значения аргумента.

Примеры:abs(12)=12;abs(-12)=12;при х=3, у=-5;abs(x+y)=abs(3+(-5))=abs(-2)=2;abs(x)+abs(у)=abs(3)+abs(-5)=3+5=8.

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

§7. Типы данных

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

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

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

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

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

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

Переменная в программе может иметь какое−либо значение. Для человека значение − это информационное содержание, а для компьютера − это код в памяти.

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

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

7

Page 6: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

преемника) элементы.В языке Паскаль имеются стандартные функции,

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

функция Pred(x) определяет значение, предшествующее х;

функция Succ(x) определяет значение, следующее за х;

функция Ord(x) возвращает порядковый номер величины х.

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

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

К структурным типам данных относятся массив (Array), множество (Set), файл (File) и запись(Record).

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

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

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

§8. Целый тип данных

В Паскале имеется несколько целых типов со знаком и беззнаковые. Однобайтовые типы ShortInt и Byte особенно полезны в больших массивах, если их элементы принимают значения из ограниченного диапазона. Их применение в этом случае позволяет уменьшить требования программы к оперативной памяти.

Целочисленные типыТип Диапазон возможных

значенийФормат

Shortint -128...127 1 байт со зн.Integer -32768...32767 2 байта со зн.Longint -2147483648..2147483647 4 байта со зн.Byte 0…255 1 байт без зн.

Word 0...65535 2 байта без зн.

К данным целого типа можно применять операции "+" − сложение, "—" − вычитание, "*" − умножение и некоторые другие.

Так как в результате деления одного целого числа на другое не всегда получается целое число, то имеются операции:

div − целая часть от деления;mod − остаток от деления.Примеры:19 div 4=4; 12 div 4=3;-21 div 4=-5; -7 div (-4)=1;19 mod 4=3; 12 mod 4=0;-21 mod 4=-1; -7 mod (-4)=-3.Для быстрой работы с целыми числами определены

процедуры:

Inc(X) X:=X+1Inc(X,N) X:=X+NDec(X) X:=X-1Dec(X,N) X:=X-N

Пример 1Дано целое трехзначное число а. Написать

программу выделения количества сотен и количества единиц этого числа.

Program Example_1;Var a, a1, c: integer;begin

Writeln('Введите трехзначное число');Readln(a);a1:=a mod 10;c:=a div 100;Writeln('Количество единиц=', a1,

'Количество сотен=', c);end.

Пример 2Даны два числа x и y. Написать программу выдачи на печать меньшего из них, пользуясь формулой

min(x, y)=(x+y-(x-y))/2

Program Example_2;Var x, y, c: integer;begin

writeln('Введите два числа');readln(x,y);c:=(x+y-abs(x-y)) div 2;writeln('меньшее из двух чисел',x, 'и',

y, 'равно', c);end.

Пример 3Ввести с клавиатуры 2 целых числа m, n>0. Если m

делится на n или n делится на m, то вывести 1, в противном случае – любое другое число.

Program Example_3;Var m, n, c: integer;begin

write('Введите 2 натуральных числа:');readln(m,n);c:=(m mod n)*(n mod m)+1;writeln('Ответ: ', c);

end.

8

Page 7: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Пример 4Ввести с клавиатуры 2 целых числа m, n>0. Если

n≤m, то вывести 1, в противном случае – любое другое число.Примечание: основная идея решения: n div m=0, если n<m, и n-m=0, если n=m.

Program Example_4;Var n, m ,r: integer;begin

write('Введите 2 натуральных числа:');readln(m,n);r:=(n div m)*(n-m)+1;writeln(r);readln;

end.

Пример 5Если в четырехзначном числе, введенном с

клавиатуры, есть одинаковые цифры, то вывести 1, в противном случае – любое другое число.Примечание: в переменных a, b, c, d находятся цифры введенного числа, начиная со старшей (разряд тысяч).

Program Example_5;Var m, n, a, b, c, d: integer;Begin

write('Введите четырехзначное число: ');readln(m);a:=m div 1000; {первая цифра}b:=m mod 1000 div 100;c:=m mod 100 div 10;d:=m mod 10; {последняя цифра}n:=(a-b)*(b-c)*(c-d)*(d-a)*(a-c)*(b-d)+1;writeln('Ответ:', n);readln;

end.Пример 6

Если четырехзначное число, введенное с клавиатуры, является симметричным (например, 1331, 0550), то вывести 1, в противном случае – любое другое число.Примечание: в переменных a, b, c, d находятся цифры введенного числа, начиная со старшей (разряд тысяч).

Program Example_6;Var m,a,b,c,d,a1,b1,c1,v,n:integer;begin

writeln('Введите четырехзначное число:');readln (m);a:= m div 1000; {первая цифра}b:=m mod 1000 div 100;c:=m mod 100 div 10;d:=m mod 10; {последняя цифра}n:=1000*d+100*c+10*b+a;{переставляем цифры в обратном порядке}v:=m-n+1;writeln('Ответ:',v);readln;

end.Пример 7

Ввести с клавиатуры 4 целых числа m, n, k, p>0. Если остаток от деления m на n равен k или p, то вывести 1, в противном случае – любое другое число.

Program Example_7;Var m, n, k, p, a, b, c: integer;begin

write('Введите 4 целых числа:');readln(m, n, k, p);a:=1 div (1+abs(n));b:=m mod (n+a); {исключаем деление на ноль}c:=(b-p)*(b-k)+a+1; writeln('Ответ:',c);readln;

end. Пример 8

Часовая стрелка образует угол α с лучом, проходящим через центр и через точку, соответствующую 12 часам на циферблате, 0≤α<3600. Ввести с клавиатуры значение α и определить значения угла для минутной стрелки, а также количество часов и полных минут.Примечание: решение задачи основано на использовании следующих фактов: на 3600/12=300

поворачивается часовая стрелка, передвигаясь между двумя соседними цифрами. За это время минутная стрелка проходит целый круг, т.е. 60 минут. Таким образом, пока часовая стрелка поворачивается на 10, минутная проходит 2 минутных деления. Одно же минутное деление соответствует 3600/60=60.

Program Example_8;Var ha, h, ma, m: integer;begin

write('Введите угол:');readln(ha);h:=(ha div 30);m:=(ha mod 30)*2;ma:=m*6;writeln('количество часов= ',h);writeln('количество минут= ',m);writeln('угол минутной стрелки= ',ma);readln;

end.Примечание. Переменной целого типа

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

§9. Вещественный тип данных

В Паскале имеется несколько типов вещественных данных.

Вещественные типыТип Диапазон

возможных значений

Точность

Формат

Real 2.9E-39..1.7E38 11-12з. 6 байтSingle 1.5E-45..3.4E38 7-8з. 4 байтаDouble 5.0E-324..1.7E308 15-16з. 8 байтExtended 3.4E-4932..1.1E4932 19-20з. 10байтComp -9.2E18..9.2E18 19-20з. 8 байт

Константа действительного типа может быть

9

Page 8: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

представлена в двух видах: числом с фиксированной и плавающей точкой.

Число с фиксированной точкой изображается десятичным числом с дробной частью (дробная часть может быть нулевой). Дробная часть отделяется от целой с помощью точки, например: 127.3, 25.0, -16.003, 200.59, 0.54.

Число с плавающей точкой имеет вид mЕр, где m − мантисса, а р − порядок числа. В качестве m могут быть целые числа и действительные числа с фиксированной точкой, в качестве р − только целые числа. Как мантисса, так и порядок могут содержать знаки "+" и "−".

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

Abs(x) абсолютное значение хSqr(х) квадрат хSqrt(x) квадратный корень из хSin(х) синус хCos(х) косинус хArctan(х) арктангенс хЕхр(х) еx

Ln(х) натуральный логарифм хTrunc(х) целая часть хRound(х) ближайшее к х целое число

Примечание. В тригонометрических функциях синус и косинус аргумент задается только в радианах.

Выводить данные вещественного типа можно по формату и без него. Если при выводе данных вещественного типа не указан формат, то число выводится с плавающей точкой − мантисса и порядок. На число отводится 17 позиций, при этом в целой части мантиссы присутствует только одна значащая цифра. Изменить стандартную форму вывода можно, используя формат Write(x: m: n), где х − выводимое данное вещественного типа; m − общее количество позиций для вывода числа (включая знак числа, целую часть, точку и дробную часть); n − количество позиций для вывода дробной части. В качестве типа могут быть целые константы, переменные, выражения. Так, использование формата Write(r: 8: 4) для вывода значения r, равного -35,245367, приводит к выводу значения -35.2454.

Пример 1Даны первый член, разность и число членов

арифметической прогрессии. Написать программу вычисления суммы ее членов.

Program Example_9;Var a1, d, n: integer;

s: real;Begin

writeln('Введите первый член, разность ичисло членов арифм. прогрессии');

readln(a1, d, n);s:=(2*a1+d*(n-1))*n/2;writeln('Сумма членов арифметической

прогрессии=', s);end.

Пример 2Написать программу вычисления площади

треугольника по трем сторонам, пользуясь формулой Герона.

Program Example_10;Var a, b, c, p, s: real;begin

Writeln('Введите длины сторонтреугольника');

readln(a, b, c);p:=(a+b+c)/2;s:=sqrt(p*(p-a)*(p-b)*(p-c));Writeln('Площадь треугольника=',s);

end.Пример 3

Написать программу нахождения среднего арифметического и среднего геометрического двух чисел.

Program Example_11;Var a, b, sa, sq: real;begin

Writeln('Введите два числа');readln(a,b);sa:=(a+b)/2;sq:=sqrt(a*b);writeln('среднее арифметическое=',sa,

'ссреднее геометрическое=', sq);end.

Пример 4Написать программу нахождения площади и

гипотенузы прямоугольного треугольника по двум катетам.

Program Example_12;Var a, b, s, g: real;begin

Writeln('Введите длины двух катетов');readln(a,b);s:=a*b/2;g:= sqrt(a*a+b*b);Writeln('площадь=', s,' гипотенуза= ',g);

end.Пример 5

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

Program Example_13;Var a, b, c, m1, m2, m3: real;begin

Writeln('Введите длины сторонтреугольника');

readln(a, b, c);m1:=aqrt(2*a*a+2*b*b-c*c)/2;m2:=sqrt(2*a*a+2*c*c-b*b)/2;m3:=sqrt(2*b*b+2*c*c-a*a)/2;Writeln('медианы равны ', m1,

' ', m2,' ', m3);end.

Пример 6Смешали V1 литров воды, имеющей температуру

Т1 градусов по Цельсию, с V2 литрами воды, имеющей температуру Т2 градусов по Цельсию. Написать программу вычисления температуры и объема полученной смеси.

Program Example_14;Var v1, t1, v2, t2, v, t: real;begin

10

Page 9: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Writeln('Введите значения v1,t1,v2,t2');readln(v1, t1, v2, t2);v:=v1+v2;t:=(v1*t1+v2*t2)/(v1+v2);Writeln('Объем смеси = ', v,

'Температура смеси= ', t);end.

Пример 7Написать программу определения давления на

грунт опоры, форма основания которой – круг радиуса r с вырезанным из его центральной части квадратом со стороной а. Масса опоры равна m.

Program Example_15;Var m, r, a, d: real;begin

Writeln('Введите массу опоры, радиус основания опоры, длину стороны вырезанного квадрата');

readln(m, r, a);d:=9.8*m/(pi*r*r-a*a);Writeln('Давление на грунт= ',d);

end.Пример 8

Написать программу вычисления площади параллелограмма по двум сторонам и углу между ними, заданному в градусах.Program Example_16;Var a, b, l, s: real;begin

writeln('Введите длины двух сторонпараллелограмма и величину угла междуми');

readln(a, b, l);l:=l*pi/180;s:=a*b*sin(l);writeln('площадь параллелограмма= ', s);

end.

§10. Логический тип данных

Переменные логического типа описываются посредством идентификатора Boolean.

Они могут принимать только два значения − FALSE (ложь) и TRUE (истина).

Переменные логического типа обычно получают значения в результате выполнения операций сравнения (отношения): "<" (меньше), ">" (больше), "≤" (меньше или равно), "≥" (больше или равно), "<>" (не равно), "=" (равно). Результат операции отношения равен TRUE, если отношение удовлетворяется для значений входящих в него операндов, и FALSE в противном случае.

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

Значения операндов

Результат операции

X Y not X X and Y X or Y X xor Yfalse false true false false falsefalse true true false true truetrue false false false true truetrue true false true true false

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

• not;•and, *, div, mod;•or, xor, +, —;• операции отношения.

Кроме того, порядок выполнения операций определяется скобками. Например, в логическом выражении A or В and not (A or В) сначала выполняется заключенная в скобки операция or, а затем операции not, and, or.

В языке Паскаль нет возможности ввода логических данных с помощью оператора Read. Однако предусмотрен вывод значений переменных логического типа с помощью оператора Write. При вводе для идентификаторов FALSE и TRUE отводится по 6 позиций, а сами идентификаторы прижимаются к правому краю поля вывода.

§11. Условный оператор

If <условие> Then <оператор 1> Else <оператор 2>

Выполнение условного оператора начинается с вычисления значения логического выражения, записанного в условии. Если условие истинно, то выполняется <оператор 1>, в противном случае − <оператор 2>. Если в качестве оператора должна выполниться серия операторов, то они заключаются в операторные скобки Begin-End.

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

Пример 1Вывести на экран большее из двух данных чисел.

Program Example_17;Var x,y: Integer;Begin

Writeln('введите 2 числа'); {вводим два целых числа через пробел} Readln(x,у) ;If x>y Then Writeln(x){если (If) x больше у, то (Then)

выводим x,} Else Writeln(у);{иначе (Else) выводим у}

Readln;End.

Введем два числа − 5 и 7. Переменная х получит значение 5, а переменная у − значение 7 (х=5, у=7). Условие х>у не выполняется, так как 5 не больше 7. Управление передается на оператор, стоящий после Else, то есть Writeln(y), а следовательно, на экране появится 7.

Примечание. Обратите внимание на то, что перед служебным словом Else разделитель − точка с

11

Page 10: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

запятой − не ставится.

Неполный условный оператор

If <условие> Then <оператор>;Ветвь Else может отсутствовать, если в случае

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

If x<0 Then x:=-x;Если в условном операторе имеется ветка Else, он

называется полным, в противном случае − неполным.

Пример 2Написать программу, проверяющую, принадлежит

ли число, введенное с клавиатуры, интервалу (0;5) .Решение

Обозначим через х число, вводимое с клавиатуры пользователем (это переменная целого типа). х принадлежит заданному интервалу лишь в том случае, если одновременно выполняются оба условия: (х>0) и (х<5).Prugram Example_18;Var x: Integer;Begin

Writeln('Введите число х');Readln(х);If (x>0) and (x<5) Then

Writeln (х,' принадлежит (0,5)')Else

Writeln(x,' не принадлежит (0,5)');Readln;

End.

§12. Оператор безусловного перехода.Раздел описания меток

Общий вид оператораGoto <метка>

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

Label 1,12, 999;Раздел Label может отсутствовать, если в

программе меток нет.Оператор перехода Goto производит передачу

управления к оператору, помеченному указанной меткой.

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

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

ПримерНайти количество целых четных чисел, вводимых с

клавиатуры. Выход из программы по вводу 0.

Program Example_19;Label 1;var a,k: integer;begin

k:=0;1: Writeln('Введите число');Readln(a);If a<>0 then

BeginIf a mod 2=0 then k:=k+1;Goto 1;

End;Writeln('количество четных чисел= ',k);Readln;

End.С помощью оператора безусловного перехода

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

Halt − прерывание программы, независимо от того, в каком месте программы стоит эта процедура;

Exit − завершение выполнения текущего блока, переход в его конец.

§13. Вложенные условные операторы

При решении задач часто приходится рассматривать не два, а большее количество вариантов. Это можно реализовать, используя несколько условных операторов. В этом случае после служебных слов Then и Else записывается новый условный оператор.

Пример Даны целые числа а, b, с. Если а<b<с, то все

числа заменить их квадратами, если а>b>с, то каждое число заменить наименьшим из них, в противном случае сменить знак каждого числа.

РешениеУсловие задачи перепишем следующим

образом:а:=а2, b:=b2, c:=c2, если а≤b≤са:=с, b:=с, если а>b>са:=-а, b:=-b, с:=-с − в остальных случаях.

Program Example_20;Var a,b,c: Integer;Begin

Writeln('Введите числа а, b, с');Readln(a,b,с);If (a<=b) and (b<=c)

Then Begin a:=sqr(a); b:=sqr(b); c:=sqr(c)

12

Page 11: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

End Else If (a>b) and (b>c)

Then Begin a:=c; b:=c End Else Begin a:=-a; b:=-b; c:=-c

End;Writeln(a:3,b:3,c:3);Readln

End.

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

ЗаданиеВ приведенной выше программе изменим

условный оператор следующим образом:If (a<=b) and (b<=c) ThenBegin

a:=sqr(a); b:=sqr(b); c:==sqr(c) If (a>b) and (b>c) Then

Begin c:=a; b:=a End Else Begin a:=-a; b:=-b; c:=-c End;

End;Как изменится выполнение данной программы?

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

Решение задач

Задача 1Написать программу, которая определяет,

принадлежит ли точка х отрезку [a,b].

Program Example_21;{определение принадлежности точки заданному

отрезку}var a,b,x: real;begin

writeln('Введите значение переменной х');

readln(x);writeln('Введите значения границ

отрезка');readln(a,b);if (x<a) or (x>b) then

writeln ('точка не принадлежит отрезку)

else writeln ('точка принадлежитотрезку');

end.

Задача 2Точка плоскости задана своими координатами

(x,y). Написать программу, определяющую, принадлежит ли она окружности радиуса 4 с центром в точке (2,2).

Program Example_22;Var x, y: real;begin

writeln('Введите координаты точки');readln(x,y);if (x-2)*(x-2)+(y-2)*(y-2)<=16

then writeln('точка принадлежит окружности')

else writeln('точка не принадлежит окружности’)

end.

Задача 3Написать программу, вычисляющую значение

функции y(x) для заданного х.

210, при х≤10,y(x)=

x3 , при x>10.

Program Example_23;{вычисление значения функции y(x)}

var x,y: real;begin

writeln('Введите значение x');readln(x);if x<=10 then y:=210 else y:=x*x*x;

writeln('y(', x,')=',y);end.

Задача 4Написать программу вычисления значения

функции y(x) для заданного x.x2 , при x>5,

y(x)= 17x-1, при –7≤x≤5,25, при x≤-7

Program Example_24;{вычислить значение функции};var x,y: real;begin

writeln('Введите значение x');readln(x);if x>5 then y:=x*x

else if x>-7 then y:=25else y:=17*x-1;

writeln('y(',x,')=',y);end.

Задача 5Написать программу определения наименьшего из

трех чисел.

Program Example_25;{определение наименьшего из трех чисел}var a,b,c, min: real;begin

writeln('Введите три числа');readln(a,b,c);min:=a;if b<min then min:=b;if c<min then min:=c;writeln('Наименьшее число= ',min);

end.Задача 6

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

Program Example_26;var a,b,x,y: real;begin

writeln('Введите два числа');readln(a,b);

13

Page 12: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

if a=b then begin x:=a; y:=b end;if a>b then begin x:=b*b; y:=a end

else begin x:=a*a; y:=b end;writeln(x,' ', y);

end.

Задача 7Даны три числа x, y, z. Написать программу, в

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

Program Example_27;var x,y,z: real;begin

writeln('Введите три числа');readln(x,y,z);if (x<=y) and (y<=z) then

beginx:=2*x;y:=2*y;z:=2*z

endelse

beginx:=abs(x);y:=abs(y);z:=abs(z);

end;writeln (x, ' ', y, ' ', z);

end.

Задача 8Написать программу решения квадратного

уравнения вида ax2+bx+c=0.

Program Example_28;var a, b, c, d, x1, x2, x: real;begin

writeln('Введите коэффициенты квадратногоуравнения’);

readln(a,b,c);d:=b*b-4*a*c;if d>0 then

beginx1:=(-b+sqrt(d)/(2*a);x2:=(-b-sqrt(d)/(2*a);writeln('уравнение имеет два корня:

x1=',x1, 'и x2=',x2);endelse if d=0 thenbegin

x:=(-b)/(2*a);writeln('Уравнение имеет один

корень x=',x);endelse writeln('уравнение не имеет корней');

readln;end.

Задача 9Определить по номеру года, является ли он

високосным. Пример выдачи результата:2000 – високосный год1900 – невисокосный год.

Примечание. Год является високосным тогда и только тогда, когда его номер делится на 4 или, если номер года оканчивается на два ноля, − 400.

Program Example_29;var n: integer;begin

writeln('Введите год:');readln(n);if n mod 100=0 then

beginif n mod 400=0 then

writeln(n,'- високосный год')else writeln(n, '-невисокосный

год’);end

elsebegin

if n mod 4=0 thenwriteln(n, '-високосный год')

elsewriteln(n, '-невисокосный год');

end;readln

end.Задача 10

Даны три неравных числа a, b, c. Вычислить и вывести значение z, равное квадрату большего из них.

Program Example_30;var a, b, c, z: real;begin

wtiteln('введите 3 числа');readln(a, b, c);if a>b then z:=a

else z:=b;if c>z then z:=c;z:=sqr (z);writeln(‘квадрат максимального числа

z=’,z);readln;

end.

§14. Цикл с параметром

Оператор цикла с параметром:For <параметр>:= А То В Do

<тело цикла>;For <параметр>:=А Downto В Do

<тело цикла>;где А − начальное значение параметра, В − конечное значение параметра.

Оператор цикла с параметром применяют тогда, когда заранее известно число повторений одной и той же последовательности операторов.

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

Рассмотрим, как выполняется оператор цикла с параметром вида

For <параметр>:=А То В Do <тело цикла>

Сначала вычисляются значения выражений А и В. Если А<В, то <параметр> последовательно принимает значения, равные А, А+1,..., В-1, В и для каждого из этих значений выполняется <тело цикла>. Если А>В, то <тело цикла> не выполняется ни разу.

Оператор цикла с параметром

14

Page 13: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

For <параметр>:=А Downto В Do <тело цикла>

выполняется аналогичным образом, но значение <параметра> изменяется с шагом, равным -1.

Если <тело цикла> состоит из нескольких операторов, то операторы тела цикла заключаются в операторные скобки Begin-End.

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

выражения у=((...(202-192)2-182)2-...-12)2.Решение:

В данном случае целесообразно организовать цикл с параметром, изменяющимся от 19 до 1, то есть шаг изменения параметра равен -1.

Обозначим через у очередное значение квадрата числа, а через n − параметр цикла.

Program Example_31;Var у, n: Integer;Begin

y:=sqr(20);For n:=19 Downto 1 Do y:=sqr(y-sqr(n));Writeln('Значение выражения равно');Writeln(у);

End.Пример 2

Из чисел от 10 до 99 вывести те, сумма цифр которых равна s (0<n<18).

Обозначим через k очередное число, p1 − старшую цифру числа k, р2 − младшую цифру числа k, s − сумму цифр числа k. Число k будем печатать только в том случае, когда сумма р1 и р2 будет равна s.

Program Example_32;Var k,n,p1,p2,s:Integer;Begin

Writeln('введите целое число ');Readln(n); {вводим целое число}For k:=10 To 99 Do {для (For) k от 10 до(То) 99 делать(Do)}

Beginp1:=k div 10; {выделяем старшую цифру}p2:=k mod 10; {выделяем младшую цифру}s:=p1+p2; {находим сумму цифр} If s=n Then Writeln(k);{если сумма равна n, то выводим k}

End;Readln;

End.Пример 3

Следующая программа предназначена для вывода таблицы соответствия между температурными шкалами Цельсия и Фаренгейта в интервали температур от точки замерзания воды до точки ее кипения. Температурная шкала Фаренгейта была предложена немецким физиком Габриэлем Фаренгейтом и используется в настоящее время в ряде англоязычных стран. В этой шкале при стандартном атмосферном давлении температура замерзания воды равна 320F, а температура кипения составляет 2120F. В более привычной для нас шкале Цельсия аналогичными опорными точками являются соответственно 00С и 1000С. Эти значения и

используются для пересчета одних температур в другие. Нетрудно проверить, что формула для пересчета имеет вид: tf=9/5*tc+32, где tf − температура по Фаренгейту, а tc − температура по Цельсию.

program Example_33;var i, Celsius, Fahrenheit: Word;begin

Writeln ('Таблица соответствия между температурными шкалами',);

Writeln (' Цельсия и Фаренгейта');for i:=0 to 20 dobegin

Celsius:=5*i;Fahrenheit:=32+Celsius*9 div 5;Write(' C=' , Celsius);Write(' F=' , Fahrenheit);Writeln;

end;Writeln(' Нажмите <Enter>');Readln;

end.§15. Работа с окнами.

Метод пошагового выполнения программКаждый файл располагается в своем окне. Можно

открывать любое количество окон, но активным является только одно окно, в котором находится курсор. Активное окно находится над всеми другими окнами. Чтобы сделать окно с номером N активным, необходимо нажать комбинацию клавиш [Alt] и номер окна (клавишу с цифрой n).

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

Чтобы посмотреть список открытых окон, можно воспользоваться комбинацией клавиш [Alt^0] или командой List меню Window.Для закрытия окна можно воспользоваться командой Close меню Window (или комбинацией клавиш [Alt^F3]. Для закрытия всех окон нужно выбрать команду Close all меню Window.

При выборе пункта Size/Move меню Window ограничивающие линии окна меняют цвет. В это время с помощью клавиш управления курсором и клавиши [Shift] можно изменять размеры окна, без нажатия клавиши [Shift] можно изменять положение окна на экране. После выбора нужного размера и положения нажмите клавишу [Enter]. Выбор команды Zoom увеличивает размеры активного окна до максимального.

При составлении программ нередко возникает ситуация, когда программа работает не так, как предполагает программист. В этом случае требуется проследить выполнение программы по шагам. В среде Турбо Паскаль есть такая возможность. Для выполнения программы в пошаговом режиме требуется выполнить команду Step Over меню Run или нажать функциональную клавишу [F8].Примечание. Прежде чем проводить пошаговую отладку программы, необходимо убедиться, что опция Options/Debugger/Integrated активизирована.

15

Page 14: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Чтобы проследить за выполнением программы, нужно знать, как изменяются значения переменных. Активизируйте окно Watches, выполнив команду Watch меню Debug. Чтобы ввести в окно Watches какую-либо переменную, воспользуйтесь комбинацией клавиш [Ctrl^F7] (или выполнив команду Add Watch меню Debug), после чего откроется диалоговое окно Add Watch, в которое необходимо ввести имя переменной.Примечание. Чтобы облегчить процесс ввода переменных в окно Watches, можно перед нажатием комбинации клавиш [Ctrl^F7] установить курсор имени переменной, которую вы хотите ввести.

Для удаления переменной из окна Watches войдите в окно Watches, с помощью клавиш управления курсором выберите нужную переменную и нажмите клавишу [DELETE].

Иногда в процессе отладки возникает необходимость отладить в пошаговом режиме не всю программу, а лишь ее часть. В этом случае можно воспользоваться командой Go To Cursor меню Run (или просто нажать клавишу [F4]), предварительно установив курсор на так называемую строку останова (строка, до которой хотим выполнить программу). Программа будет выполнена до этой строки, а далее вы сможете выполнять программу в пошаговом режиме либо снова воспользоваться командой Go To Cursor и выполнить программу до вновь выбранной строки останова.

Кроме того, можно установить в некоторой строке так называемую точку останова (можно установить несколько точек останова). Программа будет выполняться до тех пор, пока не достигнет точки останова. Чтобы установить точку останова, переместите курсор в нужную строку и нажмите комбинацию клавиш [Ctrl^F8] (или выполните команду Add breakpoint меню Debug), соответствующая строка будет отмечена подсветкой. После повторного нажатия [Ctrl^F8] точка останова снимается.

Какими свойствами обладает точка останова? Активизируйте команду Breakpoint меню Debug. Появится таблица с указанием имени файла, номера строки, в которой находится точка останова, здесь же можно указать условие, выполнение которого будет приводить к прерыванию работы программы, или количество проходов контрольной точки (после выполнения которых произойдет останов). Загрузите любой файл, установите точку останова на интересующей Вас строке и нажмите клавишу Edit. Запустите программу.

§16. Решение задач с использованием цикла с параметром

Задача 1Дано число n. Каким образом можно построить

перевертыш данного числа Решение

Обозначим через n вводимое число, m − дубликат числа n, а − перевертыш числа n, i − переменная

цикла для создания перевертыша.

Program Example_34;Var n,m,a,i:Integer;Begin

Writeln('введите целое число, не большее 9999');

Readln(n); {вводим целое число}m:=n; a:=0;

{создание перевертыша}For i:=l To 4 Do {так как число

четырехзначное}Begin

a:=a*10+m Mod 10; m:=m div 10;End;If a=n Then Writeln('ДА!')

Else Writeln('НЕТ!');{если перевертыш равен данному числу,то выводим "ДА", иначе - "НЕТ"}

Readln;End.

Задача 2. Даны натуральные числа n, k (n, k<9999). Из

чисел от n до k выбрать те, запись которых содержит ровно три одинаковые цифры. Например, числа 6766, 5444, 0006, 0060 содержат ровно три одинаковые цифры.

Фрагмент решенияProgram Example_35;Begin

Writeln(' Введите два числа, не больших 9999');

Readln(n, k);For i:=n To k DoBegin

m:=i;{Выделяем цифры: a1 - первая, a2 - вторая, а3 - третья, а4 - четвертая}a4:=m mod 10; m:=m div 10;а3:=m mod 10; m:=m div 10;a2:=m mod 10; a1:=m div 10;{Проверка условий} If ((a1=a2) and (a1=a3) and(a1<>a4)) or {Первое условие}((a1=a2) and (a1=a4) and(а1<>а3)) or {Второе условие} ((a1=a3) and (a1=a4) and(a1<>a2)) or {Третье условие} ((а2=а3) and (a2=a4) and(а2<>а1)) {Четвертое условие} Then Writeln(i:5);

End;Readln;

End.Задача 3

Задано натуральное число n. Написать программу вычисления суммы натуральных чисел от 1 до n:

S=1+2+3+…nProgram Example_36;{вычисление суммы натуральных чисел}var n, s, I: integer;begin

writeln('Введите натуральное число');readln(n);s:=0for I:=1 to n do s:=s+I;writeln('сумма натуральных чисел= ',s);readln;

16

Page 15: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

end.Задача 4

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

Program Example_37;var n, i,: integer;begin

writeln('Введите натуральное число');readln(n);for i:=n downto 1 do

writeln(i);readln;

end.Задача 5

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

S:=1+sqrt(2)+sqrt(3)+…sqrt(n)

Program Example_38;var n, i: integer;

s: real;begin

writeln('Введите натуральное число');readln(n);s:=0;for i:=1 to n do s:=s+sqrt(i);

writeln('Сумма= ', s);readln

end.Задача 6

Для заданного натурального числа n написать программу вычисления выражения:k:=sqrt(2+sqrt(2+sqrt(2+sqrt(2+…sqrt(2)))))где число 2 повторяется n раз.

Program Example_39;var n, i: integer;

k: real;begin

writeln('Введите натуральное число');readln(n);k:=0for i:=1 to n do k:=sqrt(2+k);

writeln('Значение выражения= ', k);end.

Задача 7 Для заданного натурального числа n написать

программу вычисления выражения:P=sqrt(3+sqrt(6+sqrt(9+sqrt(3*n)))).

Program Example_40;{вычисление выражения}var n, I, k: integer;

p: real;begin

writeln('Введите натуральное число');readln(n);p:=0;for I:=1 to n do

begink:=n+1-I;p:=sqrt(p+3*k);

end;writeln('Значение выражения= ',p);

end.

Задача 8Для заданного натурального числа n написать программу вычисления выражения:

Program Example_41;var x, n: integer;

s, m, k: real;begin

writeln('Введите натуральное число');readln(n);s:=0;m:=0;for x:=1 to n do

begink:=sin(x); s:=s+k; m:=m+1/s

end;writeln('Значение выражения= ', m)

end.

Задача 9Для заданного натурального числа n написать

программу вычисления его факториалаn!=1*2*...*n

Восклицательный знак в конце буквы n! − это знак математической операции, называется он факториал и обозначает произведение всех натуральных чисел от единицы до указанного числа. Например:

6!=1*2*3*4*5*6=720.program Example_42;var f, i, n: integer;begin

writeln('Введите натуральное число');readln(n);f:=1;for i:=1 to n do f:=f*i;writeln(n, '!= ', f);readln;

end.

ЦИКЛЫ С УСЛОВИЯМИ

§17. Цикл с предусловием

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

Оператор цикла с предусловиемWhile <условие> Do <тело цикла>;

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

Примечание1. Если <тело цикла> состоит из нескольких операторов, то они объединяются операторными скобками.2. В теле цикла обязательно должен быть оператор,

17

Page 16: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

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

Пример 1Подсчитать количество цифр заданного

натурального числа n.Решение

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

Program Example_43;Var m, n: Longint;

k: Integer; {счетчик цифр}Begin

Writeln('Введите натуральное число');{вводим натуральное число n>0}Readln(n); m:=n; k:=0; While m<>0 Do{пока (While) число m<>0 делать (Do)}Begin Inc(k); {k:=k+1;}m:=m div 10;

{"выбрасываем" из числа последнюю цифру} End;Writeln('В числе ',n,' - ' ,

k,' цифр');{вывод количества цифр} Readln;

End.Пример 2

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

РешениеОбозначим через х и i очередной элемент

последовательности и его номер; min и k − минимальный элемент последовательности и его номер. Считывание элементов последовательности производится до тех пор, пока не будет введен 0, то есть пока х<>0. Начальное значение минимума определяется значением первого элемента последовательности. Очередное вводимое число (очередной элемент последовательности) требуется сравнивать с текущим значением минимума, и если текущее значение min окажется больше очередного элемента последовательности, то min нужно изменить, а номер очередного элемента последовательности − запомнить. Учитывая вышесказанное, составим программу:

Program Example_44;Var x, i, min, k: Integer;Begin

Writeln('Введите первый элементпоследовательности');

Read(x); k:=1;min:=x; i:=2;While x<>0 Do Begin

If x<min Then Begin min:=x; k:=i-1 End;

Writeln('Введите ', i , ' элемент последовательности');

Read(x);Inc(i);

End;Writeln('Номер минимального

элемента - ', k);End.

Пример 3Напечатать таблицу значений функции sin x на

отрезке [0,1] с шагом 0,1 (каждое вещественное число вывести в четырех позициях на отдельной строке).

РешениеДля перебора всех значений из отрезка с

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

Сравните два решения этой задачи, представленные ниже.

Program Example_45;Var i: Real;Begin

i:=0;While i<=1 Do Begin

Writeln(i: 2: 1,' ', sin(i): 4: 3);i:=i+0.1;

End;Readln;

End.

Program Example_46;Var i: Integer;Begin

i:=0;While i<=10 Do Begin

Writeln(i,' ',sin(i/10):4:3);Inc(i);

End;Readin;

End.На первый взгляд эти программы должны работать

одинаково, но, запустив их, мы обнаружим, что первая программа выдает значения функции для всех значений х от 0 до 0,9, а вторая программа − для всех значений х от 0 до 1. Это происходит из-за приближенного представления вещественного числа последнее значение получается чуть больше 1.

Как вы знаете, вся информация представляется в памяти ЭВМ в виде 0 и 1. Для хранения переменной типа Real в памяти ЭВМ отводится 48 бит (6 байт). При решении задач следует избегать использования циклов, в условиях которых используются вещественные переменные.

§18. Цикл с постусловием

Для программной реализации циклических алгоритмов с неизвестным заранее числом повторений имеется еще один оператор − оператор цикла с

18

Page 17: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

постусловием, который имеет следующий вид:Оператор цикла с постуславием

Repeat (повторять}<оператор 1>;<оператор 2>;……………<оператор n>;

Until {до тех пор, пока не} <условие>;Этот оператор отличается от цикла с предусловием

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

Обратите внимание на то, что данный оператор цикла предполагает наличие нескольких операторов в теле цикла, поэтому служебные слова Begin и End не нужны.

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

С помощью процедуры KeyPressed модуля CRT и цикла с постусловием можно организовать ожидание нажатия любой клавиши:

Repeat Until KeyPressed.

Пример 1Составить программу планирования закупки товара

в магазине на сумму, не превышающую заданной величины.

РешениеОбозначим через х и k цену и количество товара,

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

Program Example_47;Var x, k, p, s: Integer;Begin

Writeln('Предельная сумма');Readln(p);s:=0;Repeat

Writeln('Введите цену товара и его количество');

Readln(x, k);s:=s+x*k;Writeln('Стоимость покупки равна ',s);

Until s>p;Writeln('Суммарная стоимость покупки

превысила предельную сумму');End.

Пример 2Дано х, принадлежащее интервалу от -1 до 1.

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

ряда х-(х2/2)+(х3/3-… с заданной точностью е. Нужная точность считается полученной, если очередное слагаемое оказалось по модулю меньше, чем е (это и все последующие слагаемые учитывать не надо).

Program Example_48;Var x, st, sl, у, e: Real;

n, z: Integer;Begin

Write('Введите х, принадлежащее(-1,1)');

Readln(х);Write('Введите погрешность

вычисления ');Readln(е);у:=0; n:=1; z:=1; st:=x; sl:=x;Repeat

Inc(y, z*sl); Inc (n); z:=-z;st:=st*x; sl:=st/n;

Until sl<e;Writeln(y);Readln;

End.

§19. Алгоритм Евклида

Алгоритм Евклида это алгоритм нахождения наибольшего общего делителя (НОД) двух целых неотрицательных чисел.

Пусть х и y одновременно не равные нулю целые неотрицательные числа, и пусть x>y. Если y=0, то НОД(х, у)=х, а если y0, то для чисел х, y и r, где r − остаток от деления x на y, выполняется равенство НОД(х,y)=НОД(x,r).Например, пусть х=48, а у=18.НОД(48,18)=НОД(18,12)=НОД(12,6)=

НОД(6,0)=6.Пример 1

Написать программу нахождения наибольшего общего делителя двух неотрицательных чисел.

РешениеДля решения данной задачи воспользуемся циклом

с постусловием:

Program Example_49;Var x, у: Integer;Begin

Writeln('Введите два числа');Readln(х,у);Repeat {выполнять}If x>y Then x:=x mod у Else y:=y mod х;Until (x=0) or (y=0);

{до тех пор, пока одно из чисел не станет равно нулю}

Writeln('НОД=', х+у); {вывод НОД.Одно из чисел обязательно равно нулю}Readln;

End.Пример 2

Даны натуральные числа х и у, не равные нулю одновременно. Найти d=НОД(х, у) и такие целые q и w, что d=q*x+w*y.

РешениеВведем переменные р, q, r, s, m и n, такие, что

19

Page 18: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

m=p*a+q*b, n=r*a+s*b. Первоначально m=a=x, n=b=y.Program Example_50;Var x, y: Integer; {исходные данные}

p, q, r, s, m, n: Integer;{введенные вспомогательные переменные} к: Integer; {для изменения значений P, q, r, s} d: Integer; {значение наибольшего общего делителя}

BeginRead(x, у);m:=x; n:=y; р:=1; q:=0; r:=0; s:=1;Repeat

If m>n ThenBegin k:=m div n; m:=m mod n;p:=p-k*r; q:=q-k*s

EndElse Begin

k:=n div m; n:=n mod m; r:=r-k*p;s:=s-k*q; End;

Until (m=0) or (n=0);If m=0 Then Begin d:=n; q:=r; w:=s; End

Else Begin d:=m; q:=p; w:=q; End;Writeln(d, '=',q,'*',x,'+',w,'*',y);

End.Значения переменных p, q, r, s изменяются

следующим образом:• как только значение переменной m уменьшается на k*n, значение р уменьшается на k*r, а q уменьшается на k*S;• аналогично, как только значение n уменьшается на k*m, значения переменных r и s уменьшаются соответственно на k*p и на k*q.

§20. Вложенные циклы

Пример 1Даны натуральные числа n и k. Составить

программу вычисления выражения 1k+2k+…+nk.Решение

Для вычисления указанной суммы целесообразно организовать цикл с параметром i, в котором, во-первых, находилось бы значение очередного члена ряда (у:=ik) и, во−вторых, осуществлялось бы накопление искомой суммы путем прибавления полученного слагаемого к сумме всех предшествующих (s:=s+y).

Program Example_51;Var n, k, у, i, s, m: Integer;Begin

Writeln('Введите n и k ');Readln(n,k);s:=0;For i:=1 To n DoBegin

y:=1;For m:=1 To k Do y:=y*i;{нахождение степени k числа i}

s:=s+y;End;Writeln('Ответ: ',s);

End.

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

Пример 2Написать программу, которая находит и выводит

на печать все четырехзначные числа abcd, где а, b, с, d − различные цифры, для которых выполняется соотношение: ab-cd=a+b+c+d.

РешениеЗадачу можно решать несколькими способами.

Можно просто перебрать все четырехзначные числа и для каждого проверять соблюдение условий. Попробуем сократить перебор, для этого преобразуем второе условие:аb-cd=а+b+с+d;10a+b-(10c+d)=a+b+c+d;9(a-c)=2(c+d);a-c/(c+d)=2/9

Учитывая первое условие (a, b, с, d − различные цифры), получаем, что a=с+2, d=9-с и 0≤с≤7.

Program Example_52;Var a, b, с, d: Integer;Begin

For c:=0 To 7 Do Begin

a:=c+2; d:=9-c;For b:=0 To 9 DoIf (b<>c) and (b<>a) and (b<>d) Then Write(a, b, c, d,' ');

Writeln End;

End.Таким образом, мы решили задачу, значительно

сократив перебор.

Пример 3Модифицировать пример 1 так, чтобы в ней

вычислялась сумма 11+22+…+nn

РешениеДанная задача отличается от предыдущей тем, что

показатель степени очередного слагаемого совпадает со значением ее основания, следовательно, верхняя граница внутреннего цикла (в котором вычисляется очередное слагаемое) определяется значением счетчика внешнего цикла.

Program Example_53;Var n, у, i, s, m: Integer;Begin

Writeln('Введите значение n');Readln(n);s:=0;For i:=1 To n DoBegin

y:=1;For m:=1 To i Do y:=y*i;{нахождение степени k числа i}

s:=s+y;End; Writeln('Ответ: ',s);

End.Пример 4

20

Page 19: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Cтаринная задача. Cколько можно купить быков, коров и телят, если плата за быка − 10 рублей, за корову − 5 рублей, за теленка − полтинник (0,5 рубля) и на 100 рублей надо купить 100 голов скота?

РешениеОбозначим через b количество быков; k −

количество коров; t − количество телят. После этого можно записать два уравнения: 10b+5k+0.5t=100 и b+k+t=100. Преобразуем их: 20b+10k+t=200 и b+k+t=100.

На 100 рублей можно купить:• не более 10 быков, т.е. 0≤b≤10;• не более 20 коров, т.е. 0≤k≤<20;• не более 200 телят, т.е. 0≤t≤200. Таким образом, получаем:

Program Example_54;Var b, k, t: Integer;Begin

For b:=0 To 10 DoFor k:=0 To 20 Do For t:=0 To 200 DoIf (20*b+10*k+t=200) and (b+k+t=100)Then Writeln('быков ',b,' коров ',

k,' телят ',t);End.

Значение переменной b изменяется 11 раз (от 0 до 10), для каждого ее значения переменная k изменяется 21 раз, а для каждого значения переменной k переменная t изменяется 201 раз. Таким образом, условие будет проверяться 11х21х201 раз. Но если известно количество быков и коров, то количество телят можно вычислить по формуле t=100-(b+k) − и цикл по переменной t исключается.Program Example_55;Var b, k, t: Integer;Begin

For b:=0 To 10 DoFor k:=0 To 20 DoBegin

t:=100-(b+k);If (20*b+10*k+t=200) Then Writeln('быков ',b,' коров ',

k,' телят ',t);End;

End.При этом решении условие проверяется 11х21

раз.Пример 5

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

Program Example_56;var k, a, b: integer;begin

k:=0;for a:=1 to 100 do

for b:=1 to 100 dobegin

if a+b=a*b thenbegin

k:=k+1;writeln('Искомая пара

чисел: ',a, ' и ', b);end;

end;if k=0 then writeln('Таких чисел нет');

end.

§21. Решение задач с использованием циклов с условием

Задача 1Если мы сложим все цифры какого-либо числа,

затем все цифры найденной суммы и будем повторять этот процесс, мы, наконец, получим однозначное число (цифру), называемое цифровым корнем данного числа. Например, цифровой корень числа 34 697 равен 2 (3+4+6+9+7=29; 2+9=11; 1+1=2). Составим программу для нахождения цифрового корня натурального числа.

РешениеПрограмма, вычисляющая цифровой корень

данного числа, может выглядеть следующим образом:

Program Example_57;Var n, k, s: Longint;Begin

Writeln('Введите число');Readln(n);s:=n;While s>9 Do

Begink:=s; s:=0;Repeats:=s+k mod 10;k:=k div 10;

Until k=0;End;

Writeln('Цифровой корень числа ',n,' равен',s);

End.Задача 2

Задано целое четное число n. Написать программу вычисления квадратов целых четных чисел от 0 до n.

Program Example_58;var i, y, n: integer;begin

writeln('Введите целое четное число');readln(n);i:=0;while i<=n do

beginy:=i*i;writeln('Квадрат числа ' ,i,

' равен ',y);i:=i+2

end;readln;

end.

§22. СИМВОЛЬНЫЙ ТИП ДАННЫХ

Данные символьного типа описываются с помощью идентификатора Char.

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

21

Page 20: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

символу алфавита соответствует индивидуальный числовой код от 0 до 255.

Примечание. Наиболее распространенной международной системой кодирования символов является система ASCII. Символы с кодами от 0 до 127 составляют так называемую основную таблицу кодов ASCII. Эта часть идентична на всех IBM-совместимых компьютерах. Символы с кодами от 128 до 255 составляют так называемую национальную кодовую таблицу. Именно в ней располагаются, например, русские буквы.

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

Обычно значения для переменных типа Char задаются в апострофах: ch:='*'; а:='3'; let-ter:='G'.

Кроме того, имеется возможность задавать значения непосредственно указанием ASCII-кода: kd:=#65 (символ 'А'); s:=#13 (код клавиши En-ter).

Первые 32 символа ASCII являются управляющими. Для указания этих символов используются записи #<ASСII-код> или ^<символ>. Например, ^[ − символ, соответствующий клавише [Esc]; ^G − звуковой сигнал.

В модуле CRT имеется функция ReadKey, которая осуществляет ввод одного символа с клавиатуры.

Формат применения:имя переменной:=ReadKey.Выражение n:=ReadKey читается как n

присвоить значение ReadKey.Так как символьный тип является порядковым, то

для него справедливо все, что было сказано о порядковых типах.

Пример 1Написать программу вывода последовательности

символов ААВАВС...АВ...YZ.Решение

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

Program Example_59;Var i, j: Char;Begin

For i:='a' To 'z' Do{количество начальных отрезков алфавита}

For j:='а' То i Do{количество символов в данном

начальном отрезке} Write(j);Readln;

End.

Пример 2Написать программу, которая подсчитывает

количество цифр, входящих в исходный текст. Текст − это последовательность символов, ввод которой заканчивается нажатием клавиши [Enter].

РешениеТак как признаком конца ввода

последовательности символов служит нажатие клавиши [Enter] (ей соответствует символ с кодом 13), то будем вводить символы до тех пор, пока значение очередного символа не совпадет со значением #13. Анализируя каждый символ, будем увеличивать счетчик, если символ является цифрой:

Program Example_60;Var ch: Char;

k: Integer;Begin

k:=0;While ch<>#13 Do

{пока не нажата клавиша <Enter>} Begin

If (ch>='0') and (ch<='9') Then Inc(k);Read(ch);

End;Writeln(^G,' Количество цифр равно ',k);

End.

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

RepeatWriteln('Хотите продолжить работу

(у/n)?');Readln(ch);

Until Upcase (ch)='N';

Функция Upcase(ch) преобразует букву ch в прописную (эта функция работает только с буквами английского алфавита, все другие символы не изменяются).

§23. Ограниченный тип данных

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

Var a: 1..25; ch: 'a'..'z';Здесь переменные а и ch могут принимать

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

Переменная ограниченного типа сохраняет все свойства переменных базового типа.

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

22

Page 21: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

программе переменная b может принимать только значения 3,4, 5, 6, 7, 8, то лучше описать ее следующим образом:

Var b:3..8; а не просто Vаг b:Integer;тогда в случае выхода значения b за диапазон 3..8 при использовании первого описания будет выдано диагностическое сообщение, которое поможет найти ошибку.

ПримерНапишите программу, в результате выполнения

которой переменной t присваивается значение true, если первая дата предшествует (в рамках одного года) второй дате, и значение false в противном случае.

РешениеТак как в условии задачи оговаривается, что обе

даты должны находиться в рамках одного года, то дату достаточно задать указанием дня и месяца. Количество дней любого месяца года не может быть более 31, количество месяцев в году равно 12. Значение переменной t равно true, если номер первого месяца меньше второго, либо значение первого дня меньше второго при условии, что номера месяцев совпали.

Program Example_61;Var d1, d2: 1..31;

m1, m2: 1..12;t: Boolean;

BeginWrite('Введите первую дату

(день, месяц)');Readln(d1, m1);Write('Введите вторую дату

(день, месяц) ');Readln(d2, m2);t:=(m1<m2) or ((m1=m2) and (d1<d2));Writeln(t);

End.§24. Оператор варианта (выбора)

Case <порядковая переменная> Of<константа 1>: <оператор 1>;<константа 2>: <оператор 2>;<константа n>: <оператор n>;[Else <оператор>;]

End;Выполнение оператора выбора начинается с

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

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

Примечание1. Тип константы должен совпадать с типом выражения.

2. Ветвь Else заключена в квадратные скобки, что говорит о том, что эта часть оператора выбора необязательна.3. В конструкции выбора, в отличие от условного оператора, перед Else ставится точка с запятой.4. В качестве операторов могут использоваться и составные операторы.5. Можно задавать не только одну константу, но и спи-сок и диапазон констант. Соответствующие примеры приведены далее.

Пример 1Составьте программу, в которой определяется,

какой буквой − гласной или согласной − является введенный символ английского алфавита.

РешениеРазделим все символы на три группы:• гласные буквы английского алфавита;• согласные буквы английского алфавита;• символы, не являющиеся буквами английского алфавита.

Program Example_62;Var ch: Char;Begin

Write('Введите символ ');Readln(ch);Case Upcase(ch) Of 'A','E','I','0','U': Writeln ('Это гласная буква английского алфавита ');'A'..'Z': Writeln('Это согласная буква

английского алфавита');Else Writeln('Этот символ не является буквой английского алфавита ');End; {case}

End.Обратите внимание на то, что в первом случае

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

Пример 2Подсчитать число пятниц, приходящихся на 13

числа в ХХ веке, если известно, что 13 января 1901 года было воскресенье.

РешениеПри решении данной задачи не требуется

рассматривать все дни нашего века, достаточно изучить дни недели только у всех 13−х чисел. Следует учитывать, что 2000 год входит в ХХ век (а 1900 год − в XIX век). Переменная d принимает значение дня недели для очередного 13–го числа (d=4 соответствует пятнице), в операторе case определяется день недели для 13−го числа в следующем месяце.

Program Example_63;var d, s, i,j: word;begin

d:=6; s:=0;for i:=1 to 100 do {цикл по годам}

for j:=1 to 12 dobegin

if d=4 then s:=s+1;case j of

1,3,5,7,8,10,12:d:=(d+3)mod 7;4,6,9,11: d:=(d+2) mod 7;

23

Page 22: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

2: if (i mod 4=0) thend:=(d+1) mod 7;

end; {case}end; {for}

writeln(s);end.

Пример 3Для натурального числа k от 1 до 99 напечатать

фразу "мне k лет", учитывая, что при некоторых значениях k слово "лет" надо заменить на слово "год" или "года".

РешениеКлючевое слово ("лет", "год", или "года") в

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

program Example_64;var k: 1..99;begin

writeln('Введите возраст в годах');readln(k);write('мне ',k);if k in [11..14] then write('лет')

else case k mod 10 of

0, 5..9: write('лет');1: write('год');2..4: write('года');

end {case}end.

Пример 4По введенному с клавиатуры номеру года

напечатать римскими буквами век, к которому относится данный год.Program Example_65;var century, year, c: word;begin

write('Введите номер года==>');readln(year);century:=(year-1) div 100+1;

{если номер года делится на сто, то это конец предыдущего века, а не начало нового, поэтому из номера года вычитается 1}

if century>=11 thenbegin

write('x');century:=century mod 10;

end; {if}case century of

1..3: for c:=1 to century do write ('I');

4: write(IV');5..8:begin

write('V');for c:=1 to century-5 do

write ('I')end;

9:write('IX');0, 10: write('X')

end; {case}readln;

end.

§25. Перечисляемый тип данных

Этот тип данных получил название

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

Например,Var month:(january, february, march,

april, may,june, july, august,september, october, november, december);

Порядок элементов перечисляемого типа определяется порядком их следования в описании. Левый имеет минимальное значение (значение функции Ord для него равно 0), а правый − максимальное.

К переменным перечисляемого типа можно применять операции сравнения. Так, например, feb-ruary<november.

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

§26. Описание переменных, констант и типов Раздел описания констант

Константа − это величина, которая не изменяет своего значения в процессе выполнения программы. С константами мы уже встречались, так как в общем случае константой является любое целое или вещественное число, символ, идентификаторы false и true, а также идентификаторы, обозначающие значения переменных перечисляемого типа. Но константа может быть обозначена и именем. В этом случае она должна быть объявлена в разделе описания констант. Раздел описания констант начинается словом Const (от англ. constancy − постоянство).

Например,Const N=25; K=38; D=(N+K) Div 2;Letter='f'; M=5E15;

Здесь N, К, D − целочисленные константы, Letter − константа символьного типа, а М − константа вещественного типа. Следует отметить, что константа D принимает свое значение после вычисления выражения. В разделе описания констант можно ис-пользовать лишь некоторые стандартные функции, такие, как Abs, Chr, Pred, Succ, Odd, Ord.

Именование констант делает программу более удобной для понимания и внесения исправлений. При изменении констант достаточно будет изменить соответствующие значения в разделе описания констант.

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

24

Page 23: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

например,Const N: Integer=15; ch: Char=#87;Типизированные константы являются, собственно

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

Раздел описания типовВ языке Паскаль все данные, используемые

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

Тип данных определяет:• формат представления данных в памяти ЭВМ;• множество допустимых значений;• множество допустимых операций.

Примечание. Следует отметить, что все типы данных изучались по этой схеме.

Все простые типы языка Паскаль можно разделить на стандартные и пользовательские. К стандартным типам относятся типы: Integer, Real, Char, Bool-ean, а также некоторые другие.

Пользовательские типы объявляются в разделе описания типов, который открывается словом Type.

ПримерType

week=(sunday, monday, tuesday,wednesday, thursday, friday,

saturday);work_week=monday..friday;day=l..31;

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

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

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

§27. Преобразование типов. Совместимость типов

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

Рассмотрим такую ситуацию. Пусть заданы типы Т1 и Т2, а также описаны переменные р1 и р2 следующим образом:

Var p1:T1; p2:T2;Когда можно присвоить переменной р1 значения

р2: р1:=р2? Чтобы ответить на этот вопрос, рассмотрим совместимость простых типов по присваиванию. Операция р1:=р2 является допустимой, если истинно одно из следующих утверждений:

• Т1 и Т2 − тождественные типы.Типы являются тождественными, если они

описаны одним и тем же идентификатором или

происходят от одного и того же идентификатора.Пример

Type T1=Real; T2=Real; T3=T1;T4=(red, green, blue, black, white);T5=(red, green, blue, black,white);T6=T4;

Здесь T1, Т2 и Т3 − тождественные типы, Т4, Т5 − не тождественные, поскольку (red, green, blue, black, white) не являются идентификаторами типа, Т4 и Т6 являются тождественными.

• Т2 является поддиапазоном типа Т1. Например, Type T1=Real; T2=Integer;

(множество целых чисел входит в диапазон вещественных чисел).

• T1 и Т2 являются отрезками одного и того же типа.

Например:Type T1=1..100; T2=-3..20;week= (dl, d2, d3, d4, d5, d6, d7);working_week=(d1..d5);

Совместимость по присваиванию станет более понятна, если вспомнить, что переменные в памяти занимают определенное число байт. Так, переменная типа Integer занимает 2 байта, типа Real − 6 байт. Переменной, которая занимает 6 байт, можно присвоить значение, занимающее 2 байта, а наоборот − не всегда.

Совместимость типов необходима также в выражениях и операциях сравнения.

Program Example_66;Var a: Byte; b: Integer; c: Longint;Begin

Writeln('Введите 2 числа:Byte,Integer)');

Readln(a, b);c:=a+b;Writeln(c);

End.Определить тип следующих выражений: a+b;

a+b+c; a+b+c+x, если переменные описаны так:Var a:Byte; b:Integer;

c:Longint; x:Real;Выражение справа в операторе присваивания

вычисляется независимо от размера или типа переменной слева. Число 32867 не входит в диапазон допустимых значений типа Integer, именно вследствие этого мы получаем неправильный результат. Чтобы этого не случилось, нужно преобразовать переменные к более "вместительному" типу.

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

<идентификатор типа>(переменная).Чтобы получить правильный результат, нужно

записать следующий оператор:c:=Longint(a)+Longint(b);

или:c:=a+Longint(b);

Для преобразования типов используются также следующие функции:Round (от англ. round − круглый, округлять) −

25

Page 24: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

округление числа до ближайшего целогоTrunc (от англ. truncate − урезать) − отбрасывание дробной части числа.Int (от англ. integer – целый) − целая часть вещественного числа.Frac (от англ. fraction − дробь) − дробная часть вещественного числа.Low (от англ. low − низкий) − наименьшее значение данного порядкового или перечисляемого типа.High (от англ. high − высокий, верх) − наибольшее значение данного порядкового или перечисляемого типа.

Пример 1"Вечный календарь". Известно, что если дата лежит

в диапазоне от 1582 до 4902 г., номер дня недели (номер воскресенья 0, понедельника − 1,…, субботы − 6) равен остатку от деления на 7 значения выражения [2.6m-0.2]+d+y+[y/4]+[c/4]-2c

Здесь d − номер дня в месяце (1, 2, ...); m − номер месяца в году, нумерация начинается с марта (у марта − номер 1, у апреля − номер 2, ..., у декабря − номер 10, январь и февраль считаются месяцами с номерами 11 и 12 предыдущего года); у − две младшие цифры года; с − две старшие цифры года; [х] обозначает целую часть числа х.

Вычислить количество пятниц, приходящихся на 13−е число в XX столетии.

РешениеProgram Example_67;Type month=(marth, april, may, june,

july, august, September,october, november, december, january, february);

day=1..31;year=1582..4902;week=(sunday, monday, tuesday, wednesday, thursday,

friday, saturday) ;Consth=20;

d: day=13;d_w: week= friday;

Var k:Integer; {для подсчета кол-ва пятниц}у: year; Mod_y: 0..99; int_y: 15..49;m: month;n:-50..1000;

Begink:=0;For y:=(h-1)*100 To h*100-1 Do {просмотрим все годы столетия}For m:=marth To february Do

{просмотрим все месяцы года}Begin

Mod_y:=y mod 100;{найдем две последние цифры года}int_y:=y div 100;{найдем две первые цифры года} n:=trunc(2.6*(Ord(m)+1)*0.2)+d+mod_y+

trunc(mod_y/4)+ trunc(int_y/4)-2*int_y;If n mod 7=0rd(d_w) Then Inc(k);End;Writeln('количество пятниц, приходящихся на ',d,' число в ',h,

' столетии равно ', k);End.

При решении этой задачи нам понадобилось

выполнить преобразование типов.

Пример 2Найти k−е простое число в арифметической

прогрессии 11, 21, 31, 41, 51, 61,…Решение

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

Program Example_68;Var k: Integer;

n, p, d: Longint:Begin

Writeln('введите номер числа');Readln(k);n:=0; p:=1;While n<k DoBegin

Inc(p, 10); d:=2;While (p mod d<>0) and (d<sqrt(p)) Do

Inc(d);If d>=sqrt(p) Then Inc(n);

End;Writeln(p);Readln;

End.В этом решении мы смогли записать условие

d<sqrt(p), так как типы Integer и Real совместимы.

Пример 3Вычислить сумму значений 1/n5 в прямом и

обратном порядке.Решение.

Перед вычислением четвертой степени значения целой (типа Word) переменной k ее значение присваивается вещественной переменной x. Это делается для того, чтобы избежать переполнения. Ведь диапазон значений вещественных переменных значительно больше, чем диапазон значений целых переменных типа Word.

Program Example_69;uses Crt; var x, summa, ammus: real;

k: word;begin

ClrScr;Writeln('1/n^5, 1 to 1000');{суммирование в прямом порядке}Summa:=0.0;for k:=1 to 1000 dobegin

x:=k;summa:=summa+1.0/(x*Sqr(Sqr(x)));

end;{суммирование в обратном порядке}ammus:=0.0;for k:=1000 downto 1 dobegin

x:=k;

26

Page 25: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

ammus:=ammus+1.0/(x*Sqr(Sqr(x)));end;Writeln('Прямая сумма=', summa);Writeln('Обратная сумма', ammus);Writeln('Разность=', summa-ammus);Readln;

end.

§28. ПРОЦЕДУРЫ

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

В Паскале имеются два вида подпрограмм − процедуры и функции . Их структура очень похожа на структуру основной программы.

Описание процедурыОписание процедуры начинается с заголовка, кото-

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

Procedure Имя [Список формальныхпараметров];

Описательная частьBegin

Тело процедурыEnd;

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

Фактические параметры − это параметры, кото-рые передаются процедуре при ее вызове.

Количество и типы формальных и фактических параметров должны в точности совпадать.

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

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

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

Все переменные программы делятся на глобальные и локальные. Глобальные переменные объявляются в разделе описаний основной программы. Локальные пе - ременные объявляются в процедурах и функциях. Та-ким образом, локальные переменные "живут" только во время работы подпрограммы.

Пример 1Составить программу для вычисления an: целые

числа a и n (n≥0) вводятся с клавиатуры.Решение

Составим процедуру для вычисления степени целого числа.Procedure Degree(x,у: Integer;

Var st: Longint);Var i:Integer; {описательная часть} Begin {тело процедуры}

st:=1;For i:=1 To у Do st:=st*x;

End;Первая строчка описания − это заголовок процеду-

ры, который начинается со слова Procedure. Процедура названа именем Degree. В скобках записан список формальных параметров, то есть, перечислены переменные с указанием их типа. Мы используем три параметра: первый − основание степени, то есть число, которое надо возвести в степень; второй − показатель степени, третий − результат. Первые два формальных параметра − параметры-значения, третий − параметр-переменная, и перед ним указано слово Var. Все они описаны как целые (х и у − переменные типа Integer, a st − типа Longint, так как степенная функция быстро возрастает).

После заголовка процедуры идут разделы описаний. В нашем примере имеется только раздел описания переменных, в котором описывается одна переменная i (счетчик цикла).

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

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

Вся программа для решения нашей задачи может иметь следующий вид:

Program Example_70;Var a, n: Integer;

s: Longint;Procedure Degree(x,y: Integer;

Var st: Longint);Var i:Integer;Begin

st:=1;For i:=1 To у Do st:=st*x;

End;Begin {основная программа}

Writeln('Введите два числа – основание и показатель степени');

Readln(a,n);

27

Page 26: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Degree(а,n,s); {обращение к процедуре}Writeln('Результат ',s);Readln;

End.Процедура вызывается как оператор, состоящий из

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

Пример 2Даны две целые переменные. Поменять местами их

значения.Решение

Поменять местами значения двух переменных можно двумя способами − через промежуточную переменную или без нее. Напишем процедуру, соответствующую первому способу.Procedure Swap (Var х, у:Integer);Var z: Integer;Begin

z:=x; x:=y; y:=z;End;

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

Program Example_71;Var a, b: Integer;Procedure Swap (Var x, y: Integer);Var z: Integer;Begin

z:=x; x:=y; y:=z;End;Begin

Writeln('Введите значения переменных а и b');

Readln(а, b);Swap(a, b); {обращение к процедуре}Writeln('а= ', а, ' b= ',b); {вывод новых значений} Readln;

End.Пример 3

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

Program Example_72;uses crt;Var choice: integer;Procedure Menu;Begin

Writeln('1. Преобразовать часы, минуты и секунды в секунды');

Writeln('2. Преобразовать секунды в часы,минуты и секунды');

Writeln('3. Завершить работу');Writeln;Writeln(' введите номер (1-3);

End;Procedure second_to_time;Var total_seconds: longint;

hours, minutes, seconds: longint;temp: Longint;

begin ClrScr;Writeln('Введите суммарное количество

секунд:');Readln(total_seconds);Writeln;temp:=total_seconds div 60;seconds:=total_seconds mod 60;hours:=temp div 60;minutes:=temp mod 60;Writeln;Writeln (total_seconds, ' секунд - это');Writeln;Writeln(hours, 'часов,' ,minutes,

' минут, ',seconds, ' секунд');Writeln;Writeln('для продолжения работы

нажмите <Enter>'); Readln;

end;Procedure time_to_seconds;Var total_seconds: longint;

hours, minutes, seconds: longint;Begin

ClrScr;Writeln('Введите часы: ');Readln(hours);Writeln;Writeln('Введите минуты');Readln(minutes);Writeln;Writeln('Введите секунды:');Readln(seconds);Writeln;total_seconds:=hours*3600+

+minutes*60+seconds;Writeln;Writeln(hours, ' часов,', minutes,

' минут, ', seconds, ' секунд – это ',total_seconds, ' секунд');

Writeln;Writeln('Для продолжения работы нажмите

<Enter>');Readln;

End;Begin

choice:=0While choice<>3 doBegin

ClrScr;Menu;readln(choice);case choice of

1: time_to_seconds;2: seconds_to_time;

End; {case}End; {while}

End.

§29. ФУНКЦИИ

Заголовок функции состоит из слова Function, за

28

Page 27: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

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

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

Таким образом, общий вид описания функции сле-дующий:

Function Имя[(Список формальныхпараметров)]: Тип

результата;Описательная часть

BeginТело функции, в котором обязательнодолжно быть присваивание Имя функции:=значение

End;Пример 1

Составить программу, подсчитывающую число сочетаний без повторения из n элементов по k.Число сочетаний без повторения вычисляется по

формуле:

Обозначим через n и k переменные для хранения введенных чисел; c − переменную для хранения ре-зультата.Чтобы подсчитать количество сочетаний без повто-рения, необходимо вычислить n!, (n-k)!, k!

Опишем функцию для вычисления факториала чис-ла

n(n!= 1•2•...•n).

Function factorial(n:Integer):Longint; {заголовок функции}

Var i: Integer; {описательная часть}rez: Longint;

Begin {тело функции}rez:=1;For i:=1 To n Do rez:=rez*i;factorial:=rez; {присваивание значения имени функции}

End;Первая строчка в описании функции − это ее

заголовок. Служебное слово Function (функция) указывает на то, что именем factorial названа функция. В скобках записан список формальных параметров функции, состоящий из одной переменной целого типа. Далее в заголовке указан тип значения функции. В данном примере результат функции fac-torial − длинное целое число.

За заголовком функции следует описательная часть функции, которая, как и у программы, может состоять из разделов описания переменных, констант, типов. В данном примере имеется только раздел описания пере-менных. В нем описаны переменные i (счетчик цикла) и rez (для накопления значения факториала).

Далее идет раздел операторов (тело функции). Ре-зультат присваивается имени функции, таким образом

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

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

Program Example_73;Var n, k: Integer;

a1, a2, a3, c: Longint;Function factorial (n:Integer): Longint;Var i: Integer;rez: Longint;Begin

rez:=1;For i:=1 To n Do rez:=rez*i;factorial:=rez;

End;Begin

Writeln('Ввод n и k:');Readln(n,k) ;a1:=factorial(n); {вычисление n!}a2:=factorial(k); {вычисление k!}a3:=factorial(n-k);{вычисление(n-k)!}c:=a1 div (a2*a3) ; {результат}Writeln(c);Readln;

End.

Пусть n=5, k=3. Когда в программе встречается оператор a1:=factorial(n), выполняются следующие действия:

выделяется память для переменных, описанных в функции factorial;

формальному параметру присваивается значение фактического: n:=n (n=5);

выполняется функция, вычисляется факториал числа 5;

значение функции передается в место обращения к этой функции, то есть присваивается переменной а1.

В операторах a2:=factorial(k) и a3:facto-rial(n-k) еще дважды вызывается функция fac-torial с параметрами k=3 и n-k=2. Всего в программе имеется 3 обращения к функции facto-rial, столько же раз выполняются и описанные выше действия.

Еще раз подчеркнем, что функция − это самостоя-тельная часть программы, имеющая собственные пере-менные, которым отводится отдельное место в памяти ЭВМ. Этим объясняется тот факт, что переменные с одинаковыми именами, используемые в функции и в основной программе, являются разными (в рассмотренном примере переменная n основной программы и параметр n функции). При выполнении программы машина "не путает" имена этих переменных, так как области их действия не совпадают.Это особенно важно при написании больших про-грамм.

Пример 2Написать функцию, подсчитывающую количество

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

29

Page 28: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

РешениеМы уже решали похожую задачу, только в ней не

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

пока число не станет равным нулю. При этом каждый раз счетчик увеличивается на 1 (начальное значение счетчика − 0).

Function Quantity(x: Longint): Byte;Var k: Byte;Begin

k:=0;While x <> 0 DoBegin

Inc(k) ;x:=x div 10;

End;Quantity:=k;

End;В заголовке функции указано ее имя − Quantity.

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

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

Program Example_74;Var n1, n2: Longint;

k1, k2: Byte;Function Quantity(x: Longint): Byte;Var k: Byte;Begin

k:=0;While x<>0 DoBegin

Inc(k) ;x:=x div 10;

End;Quantity:=k;

End;Begin

Writeln('Введите два числа'); Readln(n1, n2);k1:=Quantity(n1);{количество цифр первого числа}k2:=Quantity(n2); {количество цифр второго числа}If k1=k2 Then Writeln('Одинаковое количество цифр')

Else If k1>k2 Then Writeln('В первом числе цифр больше') Else

Writeln('Во втором числе цифр больше');

Readln;End.

Пример 3Составьте программу решения неравенства

bn≤a≤bn+1 относительно n при условии a≥1, b>1. Решение

Неравенство решается перебором значений n, метод решения реализован в функции largest_power, аргументами которой являются значения a и b.

program Example_75;function largest_power(a, b: longint):word;var n: word;

x: longint;begin

x:=b; n:=0;while x<=a dobegin

x:=b*x; inc(n);end; {while}largest_power:=n;

end; {function}begin

writeln('3^n<=10000<3^(n+1)');writeln('n=', largest_power (10000, 3));write('Нажмите <Enter>');readln;

end.Обратите внимание на то, как вызывается функция:

writeln('n=', largest_power(10000, 3)). Внутри выражения функция вызывается следующим образом:

имя функции (фактические параметры).

§30. Примеры рекурсивногопрограммирования

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

Можно разбить все рекурсивные задачи на 4 вида.

Задачи с рекурсивной формулировкой

Некоторые объекты являются рекурсивными по оп-ределению, поэтому рекурсивные алгоритмы их получения буквально повторяют соответствующие определения.

ПримерВычисление факториала натурального числа. Для

того чтобы вычислить N!, надо значение (N-1)! умножить на N, при этом 1!=1. В общем виде это можно записать так:

1 при N=1;N!=

N(N-1)! при N>1.Для вычисления факториала опишем функцию.

Program Example_76;Function factorial (n: Integer):

Longint;Begin

if n=1 Then factorial:=1Else factorial:=n*factorial(n-1);

End;

30

Page 29: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Рассмотрим последовательность вызовов этой функции для n=5. Первый вызов функции происходит в основной программе a:=factorial(5). Отметим, что при каждом обращении к функции будет создаваться свой набор локальных переменных (в данном случае в функции factorial имеется всего одна локальная переменная n). Для каждой локальной переменной на время работы функции выделяется память. После завершения работы функции эта память освобождается и переменные удаляются.

Так как n≠1, то управление передается на ветку Else и функции factorial присваивается значение n*factorial(n-1), то есть 5*factorial(4). Происходит второй вызов функции factorial, с параметром 4. Этот процесс повторяется до тех пор, пока значение параметра не станет равным 1. Тогда n=1, а поэтому значение функции factorial=1. Таким образом, n=1 − это условие окончания рекурсии. Управление передается в точку вызова, то есть в предыдущую функцию для n=2 facto-rial:=n*factorial(n-1), значит, factorial: =2*1, следовательно, factorial(2)=2. Возвращаемся назад, поднимаясь "вверх" по цепочке рекурсивных вызовов. Таким образом, получаем значение factorial(5)=120, это значение и присваивается переменной а.

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

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

Пример 1Сложение двух чисел.Пусть надо сложить два целых числа a и b, а

можно только прибавлять или вычитать 1. Тогда:если b=0, то a+b=a;если b>0, то a+b=(a+1)+(b-1);если b<0, то a+b=(a-1)+(b+1).

РешениеМожно дать следующее рекурсивное определение

операции сложения двух чисел:

a, если b=0;a+b= (a+1)+(b-1), если b>0;

(a-1)+(b+1), если b<0.

Опишем соответствующую функцию:

Program Example_77;Function Sum(a, b: Integer): Integer;Begin

If b=0 Then Sum:=aElse If b>0 Then Sum:=Sum(a+1, b-1)

Else Sum:=Sum(a-1, b+1);End;

Пример 2Найти НОД двух натуральных чисел.

РешениеРанее мы уже рассматривали один из способов реа-

лизации алгоритма Евклида. Рассмотрим еще один

способ.Имеются два натуральных числа a и b. Если a=b,

то НОД(a,b)=a. Если a>b, то НОД(a,b)=НОД(a-b,b).

Если a<b, то НОД(a, b)=НОД(a, b-a).Рассмотрим конкретный пример: найдем наиболь-

ший общий делитель чисел 123 и 36 (см. таблицу).

Program Example_78;Function NOD(a, b: Integer): Integer;Begin

If a=b Then NOD:=aElse If a>b Then NOD:=NOD(a-b, b)

Else NOD:=NOD(a, b-a);End;

a b Примечание

123 36 Так как a>b, a:=a-b

87 36 a:=a-b

51 36 a:=a-b

15 36 Так как b>a, b:=b-a15 21 b:=b-a

15 6 a:=a-b

9 6 a:=a-b

3 6 b:=b-a

3 3 Так как a=b, НОД:=a

Пример 3Перевести натуральное число из десятичной

системы счисления в двоичную.Решение

Переведем число 23 в двоичную систему счисления. Для этого разделим его на 2, получим целую часть и остаток от деления. Целую часть снова делим на 2 и получаем целую часть и остаток. Так делаем до тех пор, пока целая часть не станет меньше делителя (то есть пока она не станет равна 1).

23 222 11 2

1 10 5 2 1 4 2 2

1 2 10

Теперь начиная с этой единицы выписываем в обратном порядке все остатки от деления. Это и будет запись числа 23 в двоичной системе счисления:

2310=101112

Опишем соответствующую процедуру:Program Example_79;Procedure Rec(n: Integer);Begin

If n>1 Then Rec(n div 2);Write(n mod 2);

End;Покажем вызовы процедуры для числа 23. Первый

вызов процедуры производится в основной программе. Результат: 10111.

Первая цифра (1) выводится на экран из послед-него вызова процедуры Reс, следующая цифра (0) из

31

Page 30: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

предпоследнего и так далее, последняя (1) − из первого. Таким образом, вывод очередной цифры про-исходит перед выходом из очередного экземпляра про-цедуры Reс.

Задачи, которые можно решить как частный случай обобщенной

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

ПримерОпределить, является ли заданное натуральное чис-

ло простым.Решение

Данную задачу можно обобщить, например, так; определить, верно ли, что заданное натуральное число N не делится ни на одно число, большее или равное M (2≤M≤N), но меньшее N.

Соответствующая функция должна принимать зна-чение "истина" в двух случаях:

Если M=N;Если N не делится на M и функция принимает

значение "истина" для чисел М+1 и N.

Program Example_80;Function Simple(M,N: Integer): Boolean;Begin

If M=N Then Simple:=TrueElse Simple:=(N Mod M<>0)

And Simple (M+1,N);End;

Вернемся к исходной задаче. Она является частным случаем обобщенной, если M положить равным 2. Пер-вое обращение к функции будет таким: Sim-ple(2,N), где N − это данное число.

ЗаданиеИзучить работу функции в пошаговом режиме и

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

Задачи, в которых можно использовать характеристику или

свойство функции

ПримерДля заданного натурального числа N≥1 определить

натуральное число a, для которого выполняется нера-венство: 2a-1≤N≤2a.

РешениеЗаметим, что значение a зависит от N следующим

образом:1, если N=1;

a(N)=a(N div 2)+1, если N>1.

Рассмотрим пример. Пусть N=34.2a-1≤34<2a, прибавим 1 и переходим к 34 div 22a-1≤17<2a +12a-1≤8<2a +1

2a-1≤4<2a +12a-1≤2<2a +12a-1≤1<2a получим a=1А теперь возвращаемся назад, к последней единице

прибавляем все предыдущие. Таким образом, получается 6. Опишем соответствующую функцию:

Program Example_81;Function A(n: Integer): Integer;Begin

If N=1 Then A:=1Else A:=A(N div 2)+1;

End;

§31. ФАЙЛОВЫЙ ТИП ДАННЫХ

Операции для работы с файлами последовательного доступа

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

По способу организации и типу компонентов выде-ляют четыре основные разновидности структурированных типов:

регулярный тип (массивы); комбинированный тип (записи); файловый тип (файлы); множественный тип (множества).

Использование структурированных типов данных позволяет решать разнообразные и достаточно сложные задачи.

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

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

С другой стороны, файл − это одна из многих структур в программировании. Файл в таком понимании называют логическим файлом, т.е. существующим только в нашем логическом представлении при написании программы.

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

Структура логического файла − это способ восприятия файла в программе. Образно говоря, это

32

Page 31: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

"шаблон" ("окно"), через который мы смотрим на физическую структуру файла. В Паскале таким "шаблонам" соответствуют типы данных, допустимые в качестве компонент файлов.

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

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

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

Файлы классифицируются по двум признакам:По методу доступа − последовательный, прямой

доступ.По типу (логической структуре) − типизированные,

текстовые, нетипизированные.Объявление файловой переменной в разделе описа-

ния переменных имеет вид:

Var <имя файла>: File Of <тип элементов;>

Например,Var Ft: File Of Integer;

{файл, элементами которого являются целые числа}М: File Of Char;

{файл, элементами которого являются символы}Type File_Integer=File Of Integer;

File_Char=File Of Char;Var F1: File_Integer;

F2: File_Char;Так как в описании указывается тип элементов,

такие файлы называются типизированными. Все эле-менты файла пронумерованы, начиная с нуля.

С каждым файлом связан так называемый файло - вый указатель. Это неявно описанная переменная, ко-торая указывает на некоторый элемент файла.

(0) (1) … (k) (k+1) …

файловый указательВсе операции производятся с элементом, который

определен файловым указателем.

§32. Обработка файловСвязь переменной файлового типа с

файлом на диске

Для установления связи между файловой перемен-ной и файлом на диске имеется стандартная процедура Assign.Assign(<имя файловой переменной>,

'<имя файла на диске>');Например, Assign (F1,'A:INT.DAT');

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

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

Чтение из файлаПод чтением из файла понимается пересылка дан-

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

Для чтения из файла необходимо открыть файл для чтения посредством процедуры

Reset (<имя файловой переменной>);Собственно чтение данных из файла выполняется

процедуройRead (<имя файловой переменной>,

<имя переменной>);Переменная должна иметь тот же тип, что и ком-

поненты файла. Отметим, что если оператор ввода имеет вид Read(<имя переменной>), то данные вводятся с клавиатуры, а если Read (<имя файловой переменной>, <имя переменной>), то данные вводятся из файла, хранящегося на диске.

Закрытие файлаПосле того как данные из файла прочитаны, его не-

обходимо закрыть посредством процедурыClose (<имя файловой переменной>).

Общая схема чтения данных из файла, таким образом, следующая:Reset (<имя файловой переменной>);…Read (<имя файловой переменной>,

<имя переменной>);…Close (<имя файловой переменной>);

Признак конца файла

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

EOF(<имя файловой переменной>)(EOF - End Of file). Она принимает истинное значение (True), если достигнут конец файла, и ложное (False) − в противном случае.

ПримерПрочитаем из файла целые числа и выведем их на

экран:Program Example_82;Var F1: File of Integer;

n: Integer;Begin

Assign(F1, 'A:INT.DAT');{связываем файловую переменную с файлом

на диске}Reset(F1); {открываем файл для чтения}While Not EOF(F1) Do{пока не достигнут конец файла F1}

33

Page 32: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

BeginRead(F1, n); {считываем очередное число}Write(n,' '); {выводим его на экран}

End;Close(F1); {закрываем файл}Readln;

End.

Запись в файлПод записью в файл понимается вывод результатов

программы из оперативной памяти ЭВМ в файл на диске.

Для записи в файл необходимо открыть файл для записи посредством процедуры

Rewrite (<имя файловой переменной>);

Собственно запись данных в файл выполняется про-цедурой

Write (<имя файловой переменной>,<значение>);

Если оператор вывода имеет вид Write(<значение>), то данные выводятся на экран дисплея, а если Write(<имя файловой переменной>,<значение>), то данные записываются в файл. После работы с файлом его необходимо закрыть.Общая схема записи данных в файл, таким образом, следующая:

Rewrite (<имя файловой переменной>);…Write (<имя файловой переменной>,

<значение>);…Close(<имя файловой переменной>);

После выполнения процедур открытия файла для чтения или для записи (Reset или Rewrite) текущий указатель "смотрит" на первый элемент (элемент с номером 0).

§33. Прямой доступ к элементам файла

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

Установка указателя

Процедура Seek (<имя файловой переменной>, N)

устанавливает файловый указатель на N-й элемент. На-пример, Seek (F1, 3). Напомним, что элементы файла нумеруются с нуля.

Определение номера элементаФункция

FilePos (<имя файловой переменной>)возвращает номер элемента, на который "смотрит" файловый указатель.

ПримерНайти номер элемента, с которым будет

выполняться следующая операция.Решение

Воспользуемся функцией FilePos:N:=FilePos(F1).

Определение количества элементов в файле

Функция FileSize (<имя файловой переменной>)

возвращает количество элементов в файле.

Удаление и переименованиефайлов

Удаление файлов. Процедура Erase (<имя файловой переменной>)

удаляет файл на внешнем носителе, с которым связана файловая переменная.Переименование файлов. ПроцедураRename (<имя файловой переменной>,

'<новое имя на диске>') переименовывает файл, связанный с данной файловой переменной.

Пример 1Ввести с клавиатуры и записать в файл DAN1.DAT

последовательность целых чисел.Решение

Сначала свяжем файловую переменную с конкрет-ным внешним файлом при помощи процедуры As-sign. Откроем файл для записи посредством процедуры Rewrite. Признак конца последовательности чисел − ввод числа 0.

Program Example_83;Var F: File Of Integer;

n: Integer;Begin

Assign(F, 'DAN1.DAT');{Связываем файловую переменную

с файлом на диске}Rewrite(F); {Открываем файл для записи} Writeln('Конец ввода чисел - 0');Repeat {Пока не будет введен 0}

Writeln('Введите число ');Readln(n) ;{Если введено число, отличное от 0, то

записываем его в файл}If n<>0 Then Write(F, n);

Until n=0; {Если введен 0, то выходим из цикла} Close(F); {Закрываем файл}

End.Пример 2

В файле DAN1.DAT записаны целые числа (см. предыдущую задачу). Вычислить сумму элементов файла и результат вместе с исходными данными

34

Page 33: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

записать в файл DAN2.DAT.

Program Example_84;Var F1, F2: File Of Integer;

{Файловые переменные}S, N: Integer;

Begin {С файловой переменной F1 связываемфайл на диске}

Assign(F1, 'DAN1.DAT');Reset(F1); {Открываем файл F1 для чтения}Assign(F2,'DAN2.DAT') ;{С файловой переменной F2 связываем

файл на диске}Rewrite(F2) ; {Открываем файл F2 для записи}S:=0;While Not EOf (F1) Do {Проверка на конец файла F1}Begin

Read(F1, N); {Чтение элемента из файла F1}S:=S+N; {Накопление суммы}Write(F2, N); {Запись элемента в файл F2}

end;Write(F2, S); {Запись суммы элементов

в конец файла F2}Write('Результат находится

в файле DAN2.DAT')Close(F1); {Закрываем файл F1}Close(F2); {Закрываем файл F2}Readln;

End.

§34. Текстовые файлы

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

Var A: Text;

Обработка текстовых файловДля обработки текстовых файлов используются те

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

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

текстового файла>),которая устанавливает файловый указатель на первый элемент следующей строки.

Процедура Write записывает данные в текущую строку. Если надо записать данные и перейти к следу-ющей строке, то можно использовать процедуру Writeln. Если требуется только перейти для записи на новую строку, то применяется процедура

Writeln (<имя файловой переменнойтекстового файла>),

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

Так как в строках может быть разное количество символов, имеется логическая функцияЕоln (<имя файловой переменной

текстового файла>), которая принимает значение True, если достигнут конец строки.

Кроме перечисленных процедур и функций, к текс-товым файлам применяется процедура

Арреnd (<имя файловой переменной текстового файла>).

Она открывает файл для "дозаписи", помещая файловый указатель в конец файла.

Пример 1Дан текстовый файл, содержащий только целые

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

РешениеПусть в файле содержится следующая информация:

-32 16 0 8 74 5 9 13 11 -5 -86 -8 0 -125 4 3 2 1 121 2

-1 -2 -4-1 -2 4

Этот файл можно создать в среде Турбо Паскаль следующим образом:

создайте новый файл посредством команды New меню File;

запишите все числа, разделяя их пробелами, и разбейте на строки, как указано в задании;

сохраните файл, например, под именем INT1.DAT. Этот файл используется в программе, которая приведена ниже.

Program Example_85;Var F: Text;

х, k: Integer;Begin

Assign(F, 'INT1.DAT'); {Связываем файловую переменную с файлом на диске}Reset(F); {Открываем файл для чтения}While Not Eof (F) Do {Пока не достигнут конец файла}Begin

k:=0; {Счетчик элементов строки}While Not Eoln(F) Do {Пока не достигнут конец строки}Begin

Read(F, x); {Считываем очередное число}Write(х, ' ');{Выводим его на экран}

35

Page 34: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Inc(k); {Увеличиваем счетчик }End;Writeln('В строке ', k,' элементов');Readln(F); {Переходим к следующей строке файла}

End;Close(F); {Закрываем файл} Readln;

End.Пример 2

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

РешениеТак как по условию задачи каждый оператор зани-

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

Program Example_86;Var F: Text;

k1, k2, n: Integer;Ch: Char;Logic, Pp: Boolean;

Begin {С файловой переменной F связываем файл на диске}

Assign(F, 'TEST.PAS');Reset(F); {Открываем файл для чтения}n:=0; {Счетчик количества строк}Logic:=True; {Пока ошибок не было,переменная Logic имеет значение True}While Not EOf (F) Do {Пока не достигнут конец файла}Begin

Inc(n); {Увеличиваем счетчикколичества строк}

k1:=0; {Счетчик количества открывающих скобок}

k2:=0; {Счетчик количествазакрывающих скобок}

Pp:=False; {Переменная Pp предназначена для определения ошибки расстановки скобок в строке. Она принимает значение True, когда обнаруживается ошибка}While Not Eoln (F) Do {Пока не достигнут конец текущей строки файла}Begin

Read(F, Ch); {Читаем очередной символ строки. Если встретили открывающую скобку, то увеличиваем соответствующий счетчик}If Ch='(' Then Inc(k1);{Если закрывающая скобка стоит после открывающей (k1>k2), то просто увеличиваем счетчик. Иначе –устанавливаем Pp в True}If (Ch=')') Then

If (k1>k2) Then Inc(k2)Else Pp:=True;

End;{Если не все закрывающие скобки

расставлены (k1<>k2) или одна из закрывающих скобок стоит раньшеоткрывающей (Pp=True), то была ошибка расстановки}

If (k1<>k2) or Pp Then

BeginWriteln('Ошибка в ',N,' строке');Logic:=False;

End;Readln(F);{Переходим на следующую

строку файла}End;{Если значение переменной Logic осталосьистинным, то ошибок расстановки не было}If Logic Then

Writeln('Cкобки расставлены правильно');Close(F); {Закрываем файл}Readln;

End.Нетипизированные файлы

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

Var F: File.Нетипизированные файловые переменные

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

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

Для работы с нетипизированными файлами можно применять почти все процедуры и функции, что и для типизированных. Исключение составляет то, что вместо процедур Read и Write используются процедуры BlockRead и BlockWrite, а процедуры Reset и Rewrite могут иметь второй параметр типа Word, который определяет размер записи, используемый при передаче данных. Если этот параметр опущен, то размер записи принимается по умолчанию равным 128 байтам.

РЕГУЛЯРНЫЕ ТИПЫ ДАННЫХ

§35. Одномерные массивы. Работа с элементами(разбор на примерах)

Пример 1Найти сумму пяти целых чисел.

РешениеДля решения этой задачи можно описать пять

целых переменных для данных чисел и еще одну − для их суммы. Обозначим исходные числа а1, а2, а3, а4 и а5, а их сумму s. Тогда можно составить такую программу, используя функцию нахождения суммы пяти чисел:

Program Example_87;Var а1, а2, аЗ, а4, а5, s: Integers;Function Sum(х1, х2, хЗ, х4, х5: Integer):

Integer;

36

Page 35: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

BeginSum:=x1+x2+x3+x4+x5;

End;Begin

Writeln('Введите пять целых чисел');Readln(а1, а2, а3, а4, а5);{Вводим пять целых чисел}s:=Sum (a1,а2, аЗ, а4,а5); {Находим их сумму} Writeln('их сумма равна ', s);{Выводим результат на экран}Readln;

End.Пример 2

Найти сумму тридцати целых чисел.Решение

Если решать эту задачу по аналогии с предыдущей, то необходимо будет описать 30 переменных для всех исходных чисел. Это не очень удобно. Поэтому используем для решения этой задачи одномерный массив.

Одномерный массив это фиксированное количество элементов одного типа, объединенных одним именем, причем каждый элемент имеет свой уникальный номер и номера элементов идут подряд. Например, введем 30 целых чисел от 25 до 54 и объединим их общим именем А.

№ 1 2 3 … 29 30А 25 26 27 … 53 54

Имя А общее для всех элементов. Элементы массива  целые числа, их 30.

Опишем в разделе описания тип − одномерный массив, состоящий из 30 целых чисел.

Type myarray = Array[1..30] Of Integer;

Напомним, что раздел типов начинается со служебного слова Type, после него идут имя нового типа и его описание. Между именем типа и его описанием ставится знак "равно" (в разделе описания переменных между именем переменной и ее описанием ставится двоеточие). Тогда:

myarray это имя нового типа;Array служебное слово (в переводе с английско-

го означает "массив", "набор");[1..30] в квадратных скобках указывается но-

мер первого элемента, затем, после двух точек, номер последнего элемента массива; в этом примере первый элемент имеет номер 1, а последний номер 30;

Of служебное слово (в переводе с английского означает "из");

Integer тип всех элементов массива.Таким образом, одномерный массив описывается

следующим образом:Array[n1..n2] Of <тип элементов>;

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

Для того чтобы обратиться к элементу этого масси-ва, необходимо указать имя массива и в квадратных скобках номер элемента. Например, первый элемент массива А А[1], а пятый А[5] .

Program Example_88;Const n=30; {Количество элементов массива}Var A: array[1..n] Of Integer;

i,sum: Integer;Begin

Writeln('Введите ', n, ' чисел');For i:=1 To n Do {Ввод массива с клавиатуры}

Readln(a[i]); {Чтение i-гo элемента}For i:=1 To n Do {Вывод массива}

Write(a[i]: 3);{Вывод i-гo элемента}sum:=0; {Начальное значение суммы}For i:=1 To n Do sum:=sum+a[i];{К уже найденной сумме прибавляем

i-й элемент}Writeln('их сумма равна ',sum);Readln;

End.Пример 3

Составить программу нахождения суммы элементов массива.

РешениеОпишем две процедуры (формирования и вывода

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

Program Example_89;Const n=30; {Количество элементов массива}Type myarray=Array[1..n] Of Integer;Var A: myarray;

s: Integer;{Значение этой переменной s будет равно

сумме всех элементов массива}Procedure Init1(Var m: myarray);Var i: Integer; {Переменная для работы с элементами

массива}Begin

Writeln('Введите ', n, ' чисел');For i:=1 To n Do {Ввод массива с клавиатуры}Readln(m[i]); {Чтение i-гo элемента}

End;Procedure Print (m: myarray);Var i: IntegerBegin

For i:=1 To n Do {Вывод массива}Write(m[i]: 3);{Вывод i-гo элемента}Writeln;

End;Function Summa (m: myarray): Integer;Var i, sum: Integer;Begin

sum:=0; {Начальное значение суммы}For i:=1 To n Do sum:=sum+m[i];{К уже найденной сумме прибавляем

i-й элемент}summa:=sum;

End;

37

Page 36: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

BeginInit1(A); {Обращение к процедуре

формирования массива}Print(A); {Вывод массива}s:=Summa(A); {Нахождение суммы элементов}Writeln('их сумма равна ',s);{Вывод результата на экран}Readln;

End.

При решении задач часто приходится заполнять массивы (присваивать значения элементам). Рассмотрим несколько способов заполнения массивов.

Первый способ заполнения одномерного массива - это заполнение с клавиатуры (этот способ был рассмотрен выше в процедуре Init1).

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

Для получения случайных чисел практически во всех современных языках программирования имеется стандартная функция. В языке Паскаль имеется функция Random. Формулы для расчета случайного числа x различного типа в программе приведены в таблице:

Тип величины х Диапазон возможных значений

Паскаль

Вещественный 0≤x<1 x:=Random0≤x<A x:=Random*AA≤x<B x:=A+Random*(B-A)

Целый 0≤x≤A x:=Random(A+1)A≤x≤B x:=Random(B-A+1)

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

Составим программу заполнения одномерного мас-сива с помощью генератора случайных чисел. Процедура вывода уже составлена ранее.

Program Example_90;Const n=30; dd=51; {n - количество элементов

массива, dd используется в генераторе случайных чисел}

Type myarray = Array [1..n] Of Integer;Var A: myarray;Procedure Init2 (Var m: myarray);

{Процедура заполнения (инициализации)массива случайными числами}

Var : Integer;Begin

For i:=1 To n Do m [i]:=-25+Random(dd);{Функция Random выбирает случайное число из отрезка от 0 до dd-1. Очередному элементу массива будет присвоена сумма выбранного случайногочисла и -25, таким образом, массив будет заполняться случайными числами от -25

до -25+(dd-1), то есть до -26+dd}End;Procedure Print (m:myarray);{процедура вывода (распечатки) массива}…Begin

Randomize;{Инициализация генератора случайных чисел}

Init2(А);{Обращение к процедуре заполнения массива}

Print(A);{Обращение к процедуре вывода массива}Readln;

End.

Третий способ заполнения массива − чтение зна-чений элементов из файла. Можно заранее создать ти-пизированный файл одномерных массивов (например, по тридцать элементов), а затем считывать из него сразу целый массив. Но мы воспользуемся текстовым файлом, так как его создавать намного удобнее. Пусть в файле записано несколько строк, а в каждой из них по 30 целых чисел. Тогда вся программа может быть такой:

Program Example_91;Const n=30;{Количество элементов массива}Type myarray = Array[1..n] Of Integer;Var A: myarray;

F: text;Procedure Init3 (Var m:myarray);

{Процедура заполнения (инициализации)массива}

Var i: Integer;Begin

For i:=1 To n Do Read(f, m[i]){Чтение из файла очередного числа}

End;Procedure Print (m:myarray);{Процедура вывода (распечатки) массива}

…Begin{Связываем файловую переменную с файлом

на диске} Assign(F, 'путь\имя файла');Reset(F);{Открываем файл для чтения}While Not EOf (F) DoBegin {Считываем очередную строку}

Init3(А);{Обращение к процедуре заполнения массива}

Print(A); {Обращение к процедуре вывода}Readln(F);

End;Close(F); Readln;

End.Четвертый способ − описание одномерного

массива − типизированной константы:

Const digit: array[0..9] of char=

('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');

DayOfWeek: array[0..6] of String =('понедельник', 'вторник', 'среда',

'четверг', 'пятница', 'суббота');Chislo: array[0..9] of byte=(0, 1, 2, 3,

38

Page 37: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

4, 5, 6, 7, 8, 9).Элемент массива может быть любого типа, кроме

файлового. Напомним, что типизированные константы являются переменными, которым начальное значение присваивается в начале выполнения программы (см. §26).

§36. Работа с элементами массива (разбор на примерах)

При работе с элементами массива можно выделить несколько видов задач.

Нахождение суммы (или произведения) элементов

Такая задача была рассмотрена выше. Часто встречаются различные модификации этой задачи, например, требуется найти сумму элементов с заданным свойством.

ПримерНайти сумму элементов, кратных заданному числу.

РешениеИзменим функцию Sum из программы Exam-

ple_89. Будем суммировать не все элементы, а только те, которые удовлетворяют данному условию, то есть только те, которые делятся нацело на заданное число (остаток от деления на данное число равен 0).

Program Example_92;Function Sum(m: myarray): Integer;Var i, s, k: Integer;Begin

Writeln('Введите число');Readln(k);s:=0; {Начальное значение суммы} For i:=1 To n Do {Нахождение суммы}

If m[i] Mod k=0 Then s:=s+m[i];{Если элемент кратен k, то прибавляем его

к сумме}sum:=s;

End;

Остальную часть программы Example_89 можно оставить без изменений.

Нахождение номеров элементов,обладающих заданным свойством

ПримерНайти номера четных элементов.

РешениеНеобходимо просмотреть весь массив, и если

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

Program Example_93;Procedure Solve (m: myarray);Var i: Integer;Begin

For i:=1 To n Do If m[i] Mod 2=0 Then Write(i:5);

End;

Нахождение количества элементов, обладающих заданным свойством

ПримерНайти количество положительных и

отрицательных элементов в данном массиве.Решение

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

Program Example_94;Procedure Quantity(m: myarray;

Var k1, k2: Integer);Var i: Integer;Begin

k1:=0; k2:=0;For i:=1 To n Do

If m[i]>0 Then Inc(k1) Else If m[i]<0 Then Inc(k2);

End;Смотрите программу Example_89. В разделе

описания переменных Var дописать: pol, otr:

Integer;. В основной программе записать

обращение к процедуре Quantity(a,pol,otr).

Есть ли в данном массиве элементы с данным свойством, или найти первый

(последний) элемент, отвечающий заданным условиям

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

Пример 1Есть ли отрицательный элемент в массиве?

РешениеНачинаем просматривать массив с первого элемен-

та (i=1). Пока не просмотрен последний (i<=n) и не найден отрицательный (m[i]>=0), будем переходить к следующему (inc(i)). Таким образом, мы закончим просмотр в одном из двух случаев: первый − просмотрели все элементы и не нашли отрицательно-го, тогда i>n, второй − нашли нужный, при этом i<=n. Опишем функцию, значение которой истина (True), если в массиве есть отрицательный элемент, и ложь (False), если его нет.

Program Example_95;Function Controll (m: myarray): Boolean;Var i: Integer;Begin

i:=1;While (i<=n) And (m[i]>=0) Do Inc(i);Controll:=(i<=n)

End;

Пример 2Найти номер последнего отрицательного элемента

39

Page 38: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

массива.Решение

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

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

Program Example_96;Function Control2 (m: myarray): Integer;Var i: Integer;Begin

i:=n;While (i>=1) And (m[i]>=0) Do Dec(i);Control2:=i;

End.

§37. Методы работы с элементами одномерного массива

Рассмотрим еще несколько типов задач.

Изменение значений некоторых элементовПример 1

Заменить отрицательные элементы массива на их абсолютные величины.

РешениеДля решения задачи опишем процедуру. Ей будем

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

Program Example_97;Procedure Substitution1 (Var m: myarray);Var i: Integer;Begin

For i:=1 To n Do If m[i]<0 Then m[i]:=-m[i];

End;

Пример 2Прибавить к каждому элементу массива число 25.

РешениеПреобразуем предыдущую процедуру.

Program Example_98;Procedure Substitution2 (Var m: myarray);Var i: Integer;Begin

For i:=1 To n Do m[i]:=m[i]+25;End;

Пример 3Если очередной элемент массива четный, то приба-

вить к нему первый, если нечетный − прибавить последний. Первый и последний элементы не

изменять.Решение

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

Program Example_99;Procedure Substitution3 (Var m: myarray);Var i: Integer;Begin

For i:=2 To n-1 DoIf m[i] Mod 2=0 Then m[i]:=m[i]+m[1]

Else m[i]:=m[i]+m[n];End;

Создание массива

Рассмотрим два примера.Пример 1

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

РешениеПусть даны два массива − А и В, состоящие из пяти

элементов. Получим из них массив С, тоже состоящий из пяти элементов, причем первый элемент этого массива равен сумме первых элементов массивов А и В, второй − сумме вторых элементов данных массивов − и так далее.

i 1 2 3 4 5A 14 2 7 8 9B 3 6 5 12 4C 17 8 12 20 13

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

Program Example_100;Procedure Sum_Ar(a, b: myarray;

Var с: myarray);Var i: Integer;Begin

For i:=1 To n Do c[i]:=a[i]+b[i];End;

Пример 2Даны первый член арифметической прогрессии и

ее разность. Записать в массив первые n членов прог-рессии.

РешениеПусть а1 − первый член прогрессии, a k − ее

разность, тогда i−й член можно найти по следующему правилу: a[i]:=a[i-1]+k, или

a[i]:=a1+k*(i-1); если i=1, тo a[i]:=a1. Опишем процедуру, в которую передаются два параметра, а результатом является одномерный массив. Его первый элемент равен первому члену

40

Page 39: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

прогрессии, второй − второму − и так далее.

Program Example_101;Procedure Progress (a1, k: Integer;

Var a: myarray);Var i: Integer;Begin

a[1]:=a1;For i:=2 To n Do

Begina[i]:=a[i-1]+k;Write(a[i]:5);

End; End;

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

ПримерДаны два одномерных массива − А и В. Найти их

скалярное произведение.Решение

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

a[1]*b[1]+a[2]*b[2]+...+a[n-1]**b[n-1]+...+а[n]*b[n],

где n − количество элементов в массивах.

Program Example_102;Function Sp (a, b: myarray): longint;Var i: Integer;

s: Longint;Begin

s:=0;For i:=1 To n Do s:=s+a[i]*b[i];Sp:=s;

End;

§38. Удаление элементов из одномерного массива

Пример 1Удалить из массива, в котором все элементы

различны, максимальный элемент. После удаления максимального элемента массив "уплотнить", сдвинув все следующие за ним элементы влево. Последнему (самому правому) элементу массива присвоить 0.

РешениеДля того чтобы решить данную задачу, необходимо:

найти номер максимального элемента k; сдвинуть все элементы начиная с k−го на

один элемент влево; последнему элементу присвоить значение 0.

Рассмотрим решение задачи на конкретном примере. Пусть дан одномерный массив, состоящий из 10 элементов: 6, 3, 4, 7, 11, 2, 13, 8, 1, 5.

Номер максимального элемента равен 7 (k=7), то есть начиная с 7−го элемента будем сдвигать элементы на один влево: 7−му элементу присвоим значение 8−го, 8−му присвоим значение 9−го, а 9−му присвоим значение 10−го, на этом сдвиг заканчивается. Таким образом, сдвиг начинается с k−го элемента и заканчивается (n-1)−м (где n − количество элементов в массиве). После этого по-

следнему элементу присвоим 0, тогда массив примет вид:

6, 3, 4, 7, 11, 2, 8, 1, 5, 0.Примечание. При удалении элемента размерность массива не изменяется.

Составим программу для удаления максимального элемента из одномерного массива, в ней воспользуемся двумя уже знакомыми процедурами инициализации массива и вывода его на печать. Первая заполняет массив случайными числами, а вторая выводит на печать этот массив. Чтобы последний 0 не выводился на экран, мы мо-дифицируем процедуру вывода Print и будем ей передавать не только массив, но и количество элементов, которые надо вывести, начиная с первого.

Program Example_103;Const n=30; dd=51;Type myarray = Array[l..n] Of Integer;Var A: myarray;

k:Integer; {k - номер максимального элемента}

Procedure Init2 (Var m:myarray);{Процедура заполнения (инициализации)

массива случайными числами}...Procedure Print1 (n1: Integer; m: myarray);{Процедура вывода (распечатки) массива} Var i: Integer;Begin

For i:=1 To n1 Do Write(m[i]:5);Writeln;

End;Function Maximum (m: myarray): Integer;Var i, max, maxi: Integer;Begin

max:=-32768;{Минимальное значение типа Integer

равно -32 768} For i:=1 To n Do{Просмотр всех элементов массива} If m[i]>max Then{Если данный элемент больше максимальногоэлемента, найденного среди первых

i-1 элементов, то}Begin

max:=m[i];{Новое значение максимального элемента}

maxi:=i;{Номер максимального элемента в массиве} End;Maximum:=maxi;

End;Procedure Delete (k1: Integer;

Var m: myarray);Var i: Integer;Begin {Сдвиг элементов на один влево}

For i:=k1 To n-1 Do m[i]:=m[i+1];{i-му элементу присваиваем значение

(i+1)-го}m[n]:=0;{Последний элемент равен 0}

End;Begin

Randomize;{Инициализация генератора случайных

чисел}Init2(A);

41

Page 40: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

{Заполнение массива А}Print1(n, A);{Вывод заполненного массива А}k:=Maximum(A);{Поиск номера максимального элемента}Delete(k, A); {Удаление элемента с номером k}Print1(n-1, А); {Вывод нового массива А}

Readln;End.

Пример 2Решить предыдущую задачу, считая, что

максимальный элемент может встречаться несколько раз.

РешениеКогда необходимо удалять несколько элементов, то

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

For i:=В Downto A Do <тело цикла>

Значение переменной i будет уменьшаться на еди-ницу начиная от В до А.

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

Program Example_104;Const n=30; dd=51;Type myarray=Array[1..n] Of Integer;Var A: myarray;

m, k, i: Integer;{m - значение максимального элемента

k - количество удаленных элементов} Procedure Init2 (Var m:myarray);

{Процедура заполнения (инициализации)массива случайными числами}

...Procedure Print1 (n1: Integer; m: myarray);{Процедура вывода (распечатки) массива}...Function Maximum (m: myarray): Integer;Var i, max: Integer;Begin

max:=-32768;For i:=1 To n Do{Просмотр всех элементов массива}If m[i]>max Then max:=m[i];{Новое значение максимального элемента}Maximum:=max;

End;Procedure Delete (k1: Integer;

Var m: myarray);{Процедура удаления элемента с

данным номером}

...Begin

Randomize;{Инициализация генератора случайных чисел}

Init2 (А);{Заполнение массива А}Print1 (n, А);{Вывод заполненного массива А}{Поиск значения максимального элемента} m:=Maximum(A); k:=0;{Просмотр всех элементов начиная с последнего} For i:=n Downto 1 Do

If A[i]=m Then {Если данный элемент имеет

максимальное значение, то}Begin

{Удаляем элемент с номером i}Delete(i, A);Inc(k);

End;Print1(n-k, A); {Вывод нового массива А}Readln;

End.

§39. Вставка элементовв одномерный массив

Вставка элемента после элементас заданным номером

ПримерВставить число 100 после пятого элемента

массива.Решение

Пусть k − номер элемента, после которого мы дол-жны вставить элемент х (k и х будем вводить с клави-атуры). Вставка осуществляется следующим образом:

первые k элементов массива остаются без изменений;

все элементы, начиная с (k+1)−го необходимо сдвинуть вправо;

элементу с номером (k+1) присваиваем значение х.

Рассмотрим конкретный пример. Пусть дан следу-ющий одномерный массив из N (N=10) элементов:

3, -12, 5, 14, 27, -6, 1, -34, 10, -15.Надо вставить элемент со значением 100 после

пятого элемента массива. Мы получим следующий массив:

3, -12, 5, 14, 27, 100, -6, 1, -34, 10, -15.Таким образом, после вставки в массиве станет 11

элементов, и это надо учесть при описании типа myarray:Type myarray=Array[1..n+1] Of Integer;

Будем выводить массив два раза − до и после вставки нового элемента, используя уже известную процедуру Print1.

Составим теперь основную программу с использованием новой процедуры Insert1(k1, x1, m), которой передаются: k1 − номер элемента, после которого надо вставить новый элемент, x1 − значение нового элемента, m − массив. Сдвиг элементов будем начинать с конца массива.

42

Page 41: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Program Example_105;Const n=10; dd=51;Type myarray=Array[1..n+1] Of Integer;Var A: myarray;

x, k: Integer;{x - значение нового элемента, k - номер элемента,после которого вставляем} Procedure Init2(Var m: myarray);{Процедура заполнения (инициализации) массива случайными числами}...Procedure Print1(n1: Integer; m: myarray);{Процедура вывода (распечатки) массива}...Procedure Insert1(k1, x1: Integer;

Var m: myarray);Var i: Integer;Begin {Сдвиг элементов на одну позицию назад}

For i:=n Downto k1+1 Do m[i+1]:=m[i];m[k1+1]:=x1;

{Вставка элемента после k1-го}End;Begin

Init2(А);Print1(n, А); {Вывод начального массива

из n элементов}Writeln('Номер элемента, после которого

вставлять, ');Writeln('и значение нового элемента');Readln(k, x);Insert1(k, x, A);Print1(n+1,A);{Вывод массива после вставки нового элемента}Readln;

End.

Вставка элемента перед элементом с данным номером

ПримерВставить число 100 перед пятым элементом

массива.Решение

Эта задача немного отличается от предыдущей: в предыдущей мы сдвигали вправо все элементы, стоящие после k−го, то есть с (k+1)−го, а на его место записывали новый элемент, в этой − сдвигаем все элементы с k−го, а затем на его место записываем новый.

Пусть дан следующий одномерный массив из N (N=10) элементов:

3, -12, 5, 14, 27, -6, 1, 34, 10, -15.Надо вставить элемент со значением 100 перед

пятым элементом массива. Получим следующий массив:3, -12, 5, 14, 100, 27, -6, 1, 34, 10, -15.

Program Example_106;Const n=10; dd=51;Type myarray=Array[1..n+1] Of Integer;Var A: myarray;

x, k: Integer;{x - значение нового элемента, k - номер элемента, после которого вставляем}Procedure Init2(Var m:myarray);{Процедура заполнения (инициализации)

массива случайными числами}...Procedure Print1(n1: Integer; m: myarray);{Процедура вывода (распечатки) массива}...Procedure Insert2(k1, x1: Integer;

Var m: myarray);Var i: Integer;Begin {Сдвиг на одну позицию вправо}

For i:=n Downto k1 Do m[i+1]:=m[i];m[k1]:=x1; {Вставка x1 на место элемента

с номером k1}End;Begin

Init2(А);Print1(n,А); {вывод начального массива} Writeln('Номер элемента, перед которым

вставлять, ');Writeln('и значение нового элемента');Readln(k,x);Insert2(k, x, A);Print1(n+1, A); {Вывод массива после

вставки нового элемента}Readln;

End.

Вставка нескольких элементов

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

ПримерВставить данное число после всех элементов

массива, кратных 3.Решение

Первое, на что необходимо обратить внимание, - это описание массива: на сколько элементов может увеличиться массив? Максимальное количество элементов, после которых будет вставлен новый элемент, совпадает с количеством элементов массива, ведь может случиться так, что все элементы массива обладают заданным свойством. Поэтому массив может увеличиться максимум в два раза, а значит, соответствующее описание будет следующим:Type myarray=Array[1..2*n] Of Integer;

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

Удобнее просматривать массив с конца, тогда вставляемый элемент мешать не будет.Составим программу.

Program Example_107;Const n=10; dd=51;Type myarray=Array[1..2*n] Of Integer;Var A: myarray;

x, k, i: Integer;{x - значение нового элемента,

k - счетчик вставленных элементов}Procedure Init2 (Var m:myarray);{Процедура заполнения (инициализации)

массива случайными числами}...

43

Page 42: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Procedure Print1 (n1: Integer; m: myarray);{Процедура вывода (распечатки) массива}...Procedure Insert3 (k1, x1: Integer;

Var m: myarray);Var i: Integer;Begin{Сдвиг элементов на n+k - это в данный

номер последнего элемента}For i:=n+k Downto k1+1 Do

m[i+1]:=m[i];m[k1+1]:=x1;{Вставка элемента на место - после k1-го}Inc(k); {Увеличение счетчика вставленных

элементов}End;Begin

Init2(А);Print1(n, A);Writeln('Введите вставляемое число');Readln(x);k:=0;For i:=n Downto 1 Do

If A[i] Mod 3=0 Then Insert3(i, x, A);Print1(n+k,A); {Вывод массива послевставки в него всех элементов}Readln;

End.

§40. Перестановки элементов массива

Перестановка двух элементов

ПримерПоменять местами значения двух элементов с

номерами k1 и k2 (где k1 и k2 вводятся с клавиатуры).

РешениеОпишем процедуру, которой будем передавать но-

мера переставляемых элементов и массив.

Program Example_108;Procedure Swap(k1, k2: Integer;

Var m: myarray);Var x: Integer;Begin

x:=m[k1]; m[k1]:=m[k2]; m[k2]:=x;End;Примечание. Задача о перестановке двух элементов с заданными свойствами сводится к этой задаче − надо только найти их номера.

Перестановка нескольких элементов (части) массива

ПримерДан одномерный массив А, состоящий из 2n эле-

ментов. Поменять местами его половины.Решение

Пусть массив А состоит из 10 элементов, то есть n=5: 1, 12, 23, 3, 7, 13, 27, 6, 9, 11. Тогда если мы поменяем местами его половины, то получим такой массив А: 13, 27, 6, 9, 11, 1, 12, 23, 3, 7. Заметим, что мы меняем местами элементы с номерами 1 и n+1, 2 и n+2 и так далее; последняя пара − n и 2n. Легко заметить и то, что элемент с номером i меняется

местами с элементом с номером n+i. Поэтому, используя процедуру Swap из примера, можно в основной программе применить цикл:Program Example_109;...

For i:=1 To n div 2 Do Swap(i, i+n div 2, A);

§41. ДВУХМЕРНЫЕ МАССИВЫ

Описание. Работа с элементами

Двухмерные массивы можно представить в виде прямоугольной таблицы или матрицы.Рассмотрим матрицу А размерностью 2х3 (состоящую из двух строк по три элемента в каждой):

a11a12a13

A=a21a22a23

Положение каждого элемента определяется двумя числами: номером строки, в которой находится элемент, и номером столбца. Например, а12 − это элемент, стоящий в первой строке и во втором столбце.

Имеется несколько способов объявления двухмерных массивов.

Способ 1. В Паскале двухмерный массив можно описать как одномерный, элементами которого являются одномерные массивы. Например, для матрицы А, приведенной выше:

Const n=2; m=3;Type omyarray=Array[1..m] Of real;

dmyarray=Array[1..n] Of omyarray;Var v: omyarray;

a: dmyarray;В данном случае переменная v объявлена как одно-

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

Способ 2. Описание массива А можно сократить, исключив определение типа omyarray в определении типа dmyarray:

Const n=2; m=3;Type dmyarray=Array[1..n] Of Array[1..m]

Of <тип элементов>;Var a: dmyarray;

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

Const n=2; m=3;Type dmyarray=Array[1..n, 1..m]

Of <тип элементов>;Var a: dmyarray;

Если нет необходимости описывать тип, то можно просто объявить массив в разделе описания пе-ременных:

Var a: Array[1..n,1..m] Of <тип элементов>;

Рассмотренные выше методы решения задач обра-ботки одномерных массивов могут применяться и для обработки двухмерных массивов. Поскольку

44

Page 43: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

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

ПримерВ приведенном ниже примере осуществляются

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

Program Example_110;Const n=10; m=15;Type dmyarray = Array[1..n, 1..m]

Of Integer;Var A: dmyarray;Procedure Init(Var x: dmyarray);{Процедура формирования массива} Var i, j: Integer;Begin

For i=1 To n DoFor j:= 1 To m Do x[i, j]:=

-25+Random(51);End;Procedure Print(x: dmyarray);{Процедура вывода массива на экран} Var i, j: Integer;Begin

For i:=1 To n DoBegin {Вывод i-й строки массива}

For j:=1 To m Do Write(x[i, j]:5);Writeln; {Переход на начало

следующей строки}End;

End;Begin

Init(A);Writeln('Массив А:');Print(A);Readln;

End.Можно выделить несколько видов задач на

двухмерные массивы.

§42. Найти сумму элементов

Иногда необходимо найти сумму всех элементов, иногда − только некоторых, удовлетворяющих опре-деленному условию. Мы рассмотрим более сложный пример.

ПримерСформировать одномерный массив, каждый

элемент которого равен сумме отрицательных элементов соответствующей строки заданной целочисленной матрицы.

РешениеОпишем одномерный массив, размерность

которого равна количеству строк в двухмерном массиве.

Const n=10; m=15;Type omyarray=Array [1..n] Of Integer;

dmyarray=Array[1..n, 1..m] Of Integer;Var B: omyarray;

A: dmyarray;Формировать одномерный массив по заданному

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

Program Example_111;Procedure Sum(x: dmyarray;

Var y: omyarray);Var i, j: Integer;Begin

For i:=1 To n Do Begin

y[i]:=0; {Присваивание начальных значений элементов массива суммы}For j:=1 To m Do {Накопление суммы отрицательных} If x[i,j]<0 Then y[i]:=y[i]+x[i,j];

End;End;

В основной программе после вызова процедуры Sum(А, В) остается только вывести на экран одномерный массив В, в котором записаны суммы отрицательных элементов каждой строки.

§43.Нахождение количества элементовс данным свойством

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

Пример 1Найти максимальный элемент массива и его

индексы.Решение

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

45

Page 44: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

элемента с максимальным значением.

Program Example_112;Procedure Maximum(x: dmyarray;

Var max, maxi, maxj: Integer);Var i, j: Integer;Begin

max:=x[1,1]; maxi:=1; maxj:=1; {Начальные значения}

For i:=1 To n DoFor j:=1 To m Do If x[i,j]>max Then Begin {Новые значения)

max: =x[i,j];maxi:=i; maxj:=j;

End;End;

Пример 2Найти количество отрицательных элементов в каж-

дой строке.Решение

Рассмотрим несколько вариантов решения этой задачи. Можно хранить количество отрицательных элементов каждой строки в одномерном массиве соответствующей размерности.

Program Example_113;Procedure Q1(x: dmyarray; Var у: omyarray);Var i, j: Integer;Begin

For i:=1 To n DoBegin

y[i]:=0;For j:=1 To m Do

If x[i,j]<0 Then Inc (y[i]);End;

End;Можно использовать счетчик, находить количество

отрицательных элементов строки и сразу выводить найденное значение на экран.

Program Example_114;Procedure Q_2(x: dmyarray);Var i, j, k: Integer;Begin

For i:=1 To n DoBegin

k:=0;For j:=1 To m Do

If x[i,j]<0 Then Inc(k);Writeln (i,'-', k);{Вывод номера строки и количества

отрицательных элементов}End;

End;

§44. Работа с несколькими массивами

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

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

где n − размерность.Решение

Формировать матрицы будем с помощью генерато-ра случайных чисел, вычислять значения элементов результирующей матрицы С − посредством вложенных циклов. Во внутреннем цикле (по параметру k) будет накапливаться сумма, определяющая элемент с[i, j] .

Program Example_115;Const n=5;Type dmyarray=Array[1..n, 1..n] Of Integer;Var А, В, С: dmyarray;Procedure Init(Var x: dmyarray);Procedure Print (x: dmyarray);Procedure Mult(x,y: dmyarray;

Var z: dmyarray);Var k, i, j: Integer;Begin

For i:=1 To n DoFor j:=1 To n DoBegin

z[i,j]:=0;For k:=1 To n Doz[i,j] :=z[i,j]+x[i,k]*y[k,j];

End;End;Begin

Writeln('матрица A:'); Init(A); Print(A);Writeln('матрица В:'); Init(В); Print(В);Mult(А, В, С);Writeln('матрица С:'); Print(с);Readln;

End.

§45. Определить, отвечает ли заданный массив некоторым требованиям

Пример 1Определить, есть ли в данном массиве элемент,

равный 0.Решение

Опишем логическую функцию, значение которой равно "истина", если такой элемент есть, и "ложь" − в противном случае. Будем просматривать элементы массива и, если найден искомый, то присвоим функции значение True, иначе − False.

Program Example_116;Function Checkl(x: dmyarray): Boolean;Var i, j: Integer;

t: Boolean;Begin

t:=False; {Предполагаем, что искомогоэлемента в массиве нет}i:=1;While (not t) And (i<=n) DoBegin

j:=1;While (j<=m) And (x[i, j]<>0) Do

Inc(j);t:=(j<=m);

{Определяем, найден ли искомый элемент; еслипросмотрена вся строка, то значениеj=m+1 и t:=False, иначе элемент найдени t:=True}Inc(i);

46

Page 45: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

End;check1:=t;

End;Пример 2

Определить, является ли данная квадратная матрица симметричной относительно своей главной диагонали.

РешениеЕсли для всех i=1,..., n и j=1,...,n, i>j

выполняется равенство a[i, j]=a[j, i], то матрица является симметричной. Поэтому можно составить следующую функцию:

Program Example_117;Function Check2(x: dmyarray): Boolean;Var i, j: Integer;

t: Boolean;Begin

t:=True;{Предположим, что матрица симметрична}i:=2;While t And (i<n) DoBegin

j:=1;While (j<i) And (x[i,j] =x[j,i])Do

Inc(j);t:=(j=i);Inc(i);

End;Check2:=t;

End;Таким образом, если встретится хотя бы одна такая

пара, что соответствующие элементы не будут равны, то функция вернет значение "ложь" (False).

§46. Изменение значений некоторых элементов, обладающих заданным

свойствомРешение таких задач похоже на решение задач для

одномерных массивов.Пример 1

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

Program Example_118;Procedure Substitution1 (Var x: dmyarray);Var i, j: Integer;Begin

For i:=1 To n DoFor j:=1 to m Div 2 Do{рассмотрим четные столбцы матрицы}

Inc(x[i, 2*j], x[i, 1])End;

Пример 2Заменить все отрицательные элементы на противо-

положные.

Program Example_119;Procedure Substitution2 (Var x: dmyarray);Var i, j: Integer;Begin

For i:=1 To n DoFor j:=1 To m Do

x[i, j]:=abs(x[i, j]);

End;

§47. Заполнение двухмерного массивапо правилу

ПримерСоставить программу, запрашивающую

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

РешениеЗаметим, что шахматную доску удобно

представить в виде двумерного массива размером 8х8. Координаты ферзя можно задать двумя числами (номером строки и номером столбца), но в шахматах принято указывать букву и число. Буква указывает номер строки, а число − номер столбца. Поэтому не будем отступать от традиций и введем координаты именно таким образом. В программе сделаем проверку правильности ввода, и если все правильно, то переведем букву в соответствующее ей число (a-1, b-2, c-3, d-4, е-5, f-6, g-7, h-8), тогда будет удобнее работать.

Для решения задачи полезно знать следующие свойства шахматной доски. Все диагонали делятся на восходящие и нисходящие:

Каждая диагональ обладает следующими свойствами:

для элементов любой восходящей диагонали сумма номеров строки и столбца постоянна, причем для разных диагоналей − разная, то есть i+j=const1;

для элементов нисходящих диагоналей разность номеров строки и столбца тоже постоянна и для разных диагоналей разная, то есть       i-j=const2.

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

Program Example_120;Const n=8;Type dmyarray=Array[1..n,1..n] Of Integer;Var A: dmyarray;

c: Char;str, stl: Integer;

{str - номер строки, stl - номер столбца}Function Place(ch: Char): Integer;Var k: Integer;Begin

Case ch Of'a': k:=1; 'b': k:=2; 'c': k:=3; 'd': k:=4; 'e': k:=5; 'f: k:=6; 'g': k:=7; 'h': k:=8;Place:=k;

End;Procedure Init(k, l: Integer;

Var x: dmyarray);{k - номер строки, l - номер столбца, где стоит ферзь}Var i, j: Integer;Begin

For i:=1 To n DoFor j:=1 To n Do {Под боем клетки, находящиеся с клеткой, на которой стоит

47

Page 46: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

ферзь, на одной вертикали, горизонтали,восходящей или нисходящей диагонали.Клетки, находящиеся под боем, мы помечаем 1, остальные помечаем 0.}If (i=k) Or (j=1) Or (i+j=k+1)

Or (i-j=k-l)Then x[i, j]:=1 Else x[i, j]:=0;x[k, l]:=2; {На этой клетке стоит ферзь}

End;Procedure Print(x: dmyarray);Var i, j: Integer;Begin

For i:=1 To n DoBegin

For j:=1 To n DoCase x[i, j] Of0: Write (' ':3);1: Write ('*':3);2: Write ('F':3);

End;Writeln;

End;Begin

Writeln('Введите координаты ферзя');Readln(с, stl);If (c<'a') Or (c>'h') Or (stl<1)

Or (stl>n) Then Writeln('Некорректный ввод')

ElseBegin

str:=Place(с);Init(str, stl, A);Print(A);

End;Readln;

End.Можно функцию Place составить иначе:

Function Place(ch: Char): Integer;Var k: Integer;Begin

Place:=0rd(ch)-Ord('a')+1;End;

В этом случае она будет более рациональна.

Пример 2Заполнить массив А размером n×m следующим об-

разом (по "змейке");Например, при n=6 и m=8:

1 2 3 4 5 6 7 816 15 14 13 12 11 10 917 18 19 20 21 22 23 2432 31 30 29 28 27 26 2533 34 35 36 37 38 39 4048 47 46 45 44 43 42 41

РешениеДля того чтобы заполнить массив указанным об-

разом, надо вывести правило заполнения. В данном случае правило будет таким: если ряд нечетный (то есть когда номер строки − нечетное число), то А[i, j]=(i-1)*m+j, иначе (то есть когда строка четная) A[i, j]=i*m-j+1. В соответствии с этим правилом составляем процедуру заполнения массива:

Program Example_121;Procedure Fill (Var x: dmyarray);Var i, j: Integer;

BeginFor i:=1 To n DoFor j:=1 To m DoIf i Mod 2=1 Then x[i, j]:=(i-1)*m+j

Else x[i, j]:=i*m-j+1;End;

§48. Вставка и удаление элементов

Вставка строкиМы уже рассматривали операции вставки для одно-

мерных массивов. Обобщим их для двухмерных.

ПримерВставить строку из нулей после строки с номером

k.Решение

Для решения этой задачи необходимо:1. Первые k строк оставить без изменения.2. Все строки после k−й сдвинуть на одну вниз,

это лучше начать с последней строки и идти до (k+1)−й.

3. Присвоить значения элементам (k+1) строки. Кроме того, необходимо обратить внимание на

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

Program Example_122;Const n=5; m:=7;Type dmyarray=Array[1..n+1,1..m]

Of Integer;Var A: dmyarray; k:Integer;

Теперь опишем процедуру вставки:Procedure Insert(k1: Integer;

Var x: dmyarray);Var i, j: Integer;Begin

For i:=n Downto k1+1 Do For j:=1 To m Do x[i+1, j]:=x[i, j];{Элементу столбца с номером j присваиваемэлемент этого же столбца, но из предыдущей строки} For j:=1 То m Do x[k1+1, j]:=0;

End;Так как число строк меняется, то процедуру Print

надо изменить. Она должна выводить указанное количество строк, начиная с первой:Procedure Print1 (n1: Integer;

x: dmyarray);Var i, j: Integer;Begin

For i:=1 To n1 DoBegin

For j:=1 To m Do Write(x[i, j]: 4);Writeln;

End;End;

Часть основной программы будет такой:Begin

Init(A);Print(n, A);Writeln ('Введите номер строки, после

которой надо вставить новую строку');Readln(k);Insert(k, A);Print1(n+1, A);Readln;

48

Page 47: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

End.Примечания

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

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

3. Вставка новой строки перед строкой с номером k изменится только тем, что сдвигать назад надо не с (k+1)−й строки, а с k−й.

4. Если надо вставлять столбцы, то размерность массива увеличивается по столбцам, а все остальное практически не меняется: надо сдвинуть столбцы вправо и на данное место записать новый столбец.

Удаление строки

ПримерУдалить строку с номером k.

РешениеДли того чтобы удалить строку с номером k,

необходимо: Сдвинуть все строки, начиная с данной на одну

вверх. Последнюю строку "обнулить", то есть всем

элементам последней строки присвоить значение 0.

Описание массивов оставим прежним (размером nxm). Также в программе будем использовать процедуру вывода Print1 из предыдущего параграфа. Будем выводить на экран сначала все строки, а второй раз, после удаления, на одну меньше. Теперь опишем процедуру удаления строки с данным номером:

Program Example_123;Procedure Delete (k1: Integer;

Var x: dmyarray);Var i, j: Integer;Begin

For i:=k1 To n-1 DoFor j:=1 To m Do

x [i, j]:=x[i+1, j];For j:=1 To m Do x[n, j]:=0;

End;Примечания

1. Задачу удаления строки, удовлетворяющей заданному условию, можно решить этим же способом, достаточно только найти ее номер.

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

§49. Перестановка элементов массиваПерестановка двух элементов

Пример 1

Поменять местами два элемента массива А с задан-ными координатами (номерами строки и столбца).

РешениеМожно эту задачу решить несколькими способами.

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

Program Example_124;Procedure Swap1(k1, l1, k2, l2: Integer;

Var x: dmyarray);Var c: Integer;Begin

c:=x[k1, l1]; x[k1, l1]:=x[k2,l2];x[k2,l2]:=c;

End;

Второй способ. Вспомним процедуру Swap, кото-рая меняет местами значения двух целых переменных.

Program Example_125;Procedure Swap(Var x, у: Integer);Var z: Integer;Begin

z:=x; x:=y; y:=z;End;

А теперь обратимся к ней, передавая данные эле-менты: Swap(A[k1, l1], A[k2, l2]).

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

Пример 2Поменять местами столбцы с номерами l1 и l2.

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

Program Example_126;Procedure Swap2(l1, l2: Integer;

Var x: dmyarray);Var i: Integer;Begin

If (l1<1) Or (l1>m)) Or (l2<1) Or (12>m)) Then

Writeln ('Ввод неправильный')ElseFor i:=1 To m Do

Swap(x[i, l1], x[i, l2]);End;

Если применять первую процедуру Swap1, то после проверки правильности ввода данных будет такое обращение:

For i:=1 То m Do Swap1(i, l1, i, l2, x);

§50. СТРОКОВЫЙ ТИП ДАННЫХОписание

Строкой называется последовательность заданной

49

Page 48: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

длины, состоящая из символов.Строки (переменные типа String) могут быть

объявлены, например, следующим образом:

Var Str1: String[30]; Str2: String;При объявлении строковой переменной в квадрат-

ных скобках может указываться длина строки. Если длина строки не указана, то она принимается равной 255. Максимальная длина строки также равна 255. В данном случае в первой строке может содержаться максимум 30 символов, а во второй − 255. Надо заметить, что строка похожа на одномерный массив символов: она имеет определенную длину (не больше некоторого числа), к каждому символу можно обратиться по его номеру (как в массиве) – Str1[i] − это обращение к i−му элементу строки Str1.

Переменные типа String выводятся на экран по-средством стандартных процедур Write и Writeln и вводятся с помощью стандартных процедур Readln и Read. To есть вводятся и выводятся не поэлементно, как массивы, а целиком.

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

Операции со строками

В Паскале имеется два основных способа обработки переменных типа String. Первый способ предполагает обработку всей строки как единого целого, т.е. единого объекта. Кроме того (это второй способ), можно рассматривать строку как составной объект, состоящий из отдельных символов, то есть элементов типа Char, которые при обработке доступны каждый в отдельности.

СклеиваниеПод склеиванием понимается последовательное

объединение нескольких строк.Пример

Var Str1, Str2, Str3: String[20];Str1:='y Егорки';Str2:='всегда отговорки';Str3:=Str1+' '+Str2;

Строка Str3 имеет значение 'У Егорки всегда отго'. В данном примере максимальная длина строки Str3 равна 20 символам, поэтому будут взяты только первые 20 символов суммы строк, а остальные рассматриваться не будут. Паскаль позволяет выполнять операции объединения (сцепления) нескольких строк в процессе их присвоения какой-либо переменной: Str3:= 'У Егорки '+' всегда '+' отговорки'. В результате такой операции в переменной Str3 будет то же самое содержимое, что и в предыдущем примере.

Примечание. "Склеить" строки можно также при помощи функции

Concat(Str1, Str2,..., StrN).

СравнениеПаскаль позволяет выполнять операции сравнения

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

Пример

'Balkon'<'balkon'(Ord(' B' )<Ord('b'));'balkon'>'balken'(Ord('o')>0rd('e')) ;'balkon'>'balk' (длина первой строки больше);'кошка '>'кошка' (длина первой строки

больше);'кот'='кот' (равны по длине и совпадают

посимвольно).Можно использовать любые операции отношения

(>, <, =, <>, >=, =<) и их комбинации в условных операторах. Их результат − это одно из двух значений: True или False.

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

Стандартные процедуры и функции

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

УдалениеДля удаления из строки фрагмента используется

процедура Delete(Str, n, m), которая вырезает из строки Str m символов начиная с n−го, таким образом, сама строка изменяется.

ПримерStr1:='ABCDEFGH';Delete(Str1, 3, 4);Writeln(Str1);После выполнения этих операторов из строки

будут удалены 4 символа начиная с 3−го, то есть строка будет такой: Str1='ABGH'.

Вставка

Для вставки подстроки в строку используется процедура Insert(Str1, Str2, n), которая вставляет строку Str1 в строку Str2 начиная n−го символа, при этом первая строка остается такой же, как и была, а вторая получает новое значение.

ПримерStr1:='ABCDEFGH';Str2:='abcdefgh';Insert(Str1, Str2, 3);

В результате выполнения данной процедуры строка будет такой: Str2='abABCDEFGHcdefgh'. Этот же результат будет и после выполнения такой последовательности операторов:

50

Page 49: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Str2:='abcdefgh';Insert(‘ABCDEFGH’, Str2, 3);

Копирование

Функция Copy(Str, n, m) копирует m символов строки Str начиная с n−го символа, при этом исходная строка не меняется

Пример 1Str1:='ABCDEFGH';Str2:='abcdefgh';Str3:=Copy(Str1, 4, 3);Writeln(Str3);Writeln(Copy (Str2, 4, 3));Значение переменной Str3='DEF'. А на экран

будут выведены следующие строки:DEFdef

Пример 2Предскажите результат работы программы.

Program Example_127;uses crt;var a, b, c, d, e: string[15];begin

clrscr;a:='стихотворение';b:=copy(a, 1, 4);c:=copy(a, 2,4);d:=copy(a, 6, 8);e:=copy(a, 7, 3);writeln(b, ', ',c, ', ',d, ', ',e);readln;

end.Длина строки

Под длиной строки понимается фактическое (а не максимально возможное!) количество символов в строке. Это значение можно найти при помощи функции Length(Str), результат которой − целое число, равное количеству символов.

ПримерStr1:='ABCDEFGH';Str2:='мама мыла раму.';k1:=Length(Str1);k2:=Length(Str2);В результате значения целых переменных будут

равны: k1=8, k2=15.

Поиск подстрокиИмеется функция, определяющая позицию

подстроки в строке, − Pos(Str1, Str2). Результат этой функции − целое число, и оно определяет номер элемента, с которого начинается первое вхождение подстроки Str1 в строку Str2. Если Str1 не входит в Str2, то значение функции равно 0.

Пример 1Strl:='CDE'; Str2:='ABCDEFGH';kl:=Pos(Str1, Str2);k2:=Pos(Str2, Str1);Значение переменной k1 равно 3, так как строка

Str1 входит в строку Str2 с третьего символа, а значение k2 равно 0.

Пример 2k1:=Pos(' ша',' Наша Таня громко плачет.')

В этом случае значение k1 равно 3, так как функция Pos возвращает номер элемента, начиная с которого подстрока встречается первый раз.

Пример 3Program Example_128;uses crt;var a, b, c: string[100];

m, n: integer;begin

clrscr;a:='Жил-был в норе под землей хоббит';b:='был';c:='хоббит';m:=pos(b, a);n:=pos(c, a);writeln(b, '-', m); {был-5}writeln(c, '-', n); {Хоббит-27}

end.

Числа и строки

Часто возникает необходимость получить строковое представление числа и наоборот (например, получить строку '13' из числа 13). Для работы с числами и строками применяются две процедуры.

Str(N, Str1) − переводит числовое значение N в строковое и присваивает результат строке Str1, причем можно переводить как целые числа, так и вещественные.

ПримерыStr(1234, Str1) − после выполнения

Str1='1234';Str (452.567, Str1) − переводим веществен-

ное число с фиксированной запятой, результат Str1='452.567';

Str(4.52567е+2, Str1) − переводим вещественное число в экспоненциальной форме, результат Str1='4.52567e+2',

Вторая процедура выполняет обратное действие. Val(Str, N, К) − переводит строковое значение в числовое. Если данная строка действительно является записью числа (целого или вещественного), то значение К=0, а N − это искомое число, иначе К будет равно номеру первого символа, с которым процедура Val "не справилась".

Примеры

Val('1234', n, k) - n=1234, k=0;Val('234.56', n, k) - n=234.56, k=0;Val('2.3456e+2', n, k) - n=2.3456e+2, k=0;Val('12-45', n, k) k=3, так как знак "−" в записи чисел может быть только на первом месте;Val('2,567m', n, k) k=2, так как разделительным знаком между целой и дробной частями является точка, а не запятая;Val ('5.87с-5') k=5, так как символ 'с' не должен встречаться в записи вещественного или цело-го числа.

51

Page 50: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

Решение задач

Пример 1Сколько раз в данной строке встречается символ

'a'?Решение

Опишем функцию, которой будем передавать строку. Результат выполнения − целое число.

Program Example_129;Function Q_Ch(st: String): Byte;Var i, k: Byte;Begin

k:=0; {Просматриваем все символы строки,их количество равно длине строки;если очередной символ равен 'а',то увеличиваем счетчик}For i:=1 To Length(st) Do

If st[i]='a' Then Inc(k);Q_Ch:=k;

End;Пример 2

Если в строке нечетное число символов, то удалить средний.

Решение

Program Example_130;Procedure Del(Var st: String);Var k: Byte;Begin

k:=Length(st);If k Mod 2=1 Then

Delete(st, k Div 2+1,1);End;

Пример 3

Заменить все вхождения подстроки 'del' на 'Insert'.

РешениеПока такая подстрока встречается, необходимо

находить номер первого символа очередного вхождения подстроки 'del' , удалять 'del' и вставлять 'Insert'.

Program Example_131;Procedure Ins(Var st: String);Var k: Byte;Begin

While Pos ('del', st)<>0 Do Begin

k:=Pos ('del', st);Delete(st, k, Length ('del'));Insert('Insert', st, k);

End;End;

Пример 4Дана строка, состоящая из нескольких слов, между

словами один пробел, в конце строки − точка. Под-считать количество слов и вывести на экран только те из них, которые начинаются с буквы 'а' (слов не больше 30).

РешениеРазобьем предложение на отдельные слова и

каждое будем хранить как элемент массива строк.

Program Example_132;Const n=30;Type Myarray_Str=Array [1..n] Of String;Var A: Myarray_Str;

str: String[255];k: Byte;

Procedure Init(Var b: Myarray_Str);Var i: Integer;Begin

k:=1; {Пока не встретится пробел, формируем очередное слово k, прибавляя по одной букве}For i:=1 To Length(str)-1 DoIf str[i]<>' ' Then b[k]:=b[k]+str[i]Else{Если это не последний символ, то увеличиваем счетчик слов и начинаем формировать очередное слово}If i<>Length(str)-1 Then

Begin Inc(k); b[k]:=' ' End;End;Begin

Writeln('Введите предложение');Readln(str);Init(A);Writeln('Всего слов: ',k);{Просматриваем все слова, если первыйсимвол очередного слова равен букве 'а', то выводим его}For i:=1 To k Do If A[i][1]='a' Then Write(A[i],' ');Readln;

End.Пример 5

Подсчитать сумму цифр, входящих в данную строку.

Program Example_133;Function Sum(st: String): Integer;Var i, d: Byte; s,k: Integer;Begin

s:=0;For i:=1 To Length(st) DoBegin

Val(st[i], d, k);If k=0 Then s:=s+d;

End;Sum:=s;

End;Пример 6

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

Решение

Program Example_134;var s: string;begin

writeln('Введите строку текста спробелами');

readln(s);while pos(' ', s)>0 do

delete (s, pos (' ', s),1);{Пока в строке существуют два рядом стоящих пробела, удаляем один из них}if s[1]=' ' then

52

Page 51: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

delete(s, length (s), 1);if s[length(s)]= ' ' then

delete(s, length(s), 1);readln;

end.Пример 7

Дана строка символов следующего вида:p1q1p2q2p3q3...qnpn

где pi − целое неотрицательное число, а qi − знак арифметического действия из набора (+,-,*). Написать программу вычисления значения введенного выражения, предполагая, что действия выполняются согласно правилам арифметики.

РешениеПока в строке присутствуют знаки умножения, мы

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

Program Example_135;var pq, p1, p2: string;

m,n, k, l, j: word;begin

writeln('Введите арифметическоевыражение');

readln(pq);while pos('*', pq)>0 do {цикл для выполнения всех

действий умножения}begin

p1:=' ';k:=pos('*', pq);while (k>1) and (pq[k-1]

in ['0'..'9']) dobegin

k:=k-1;p1:=pq[k]+p1 {формируем число,стоящее справа от знака умножения}

end; {while}p2:=' ';l:=pos('*', pq);while (l<length(pq)) and (pq[l+1]

in ['0'.. '9']) dobegin

l:=l+1;p2:=p2+pq[l];{формируем число,стоящее справа от знака умножения}

end; {while}val(p1, n, j);if j>0 thenbegin

writeln('ошибка в выражении');halt

end; {if}val(p2, m, j);if j>0 thenbegin

writeln('ошибка в выражении);halt;

end; {if}j:=m*n;str(j, p1);delete(pq, k, l-k+1); {часть строки удаляем}

insert (p1, pq, k); {вставляем результат умнож.}

end; {while} {все умножения выполнены}while (pos('+',pq)>0) or

(pos('-',pq)>0) dobegin

p1:=' ';k:=1;while (pq[k] in ['0'.. '9']) dobegin

p1:=p1+pq[k];k:=k+1;

end; {while}p2:= ' ';l:=k;while (l<length(pq)) and (pq[l+1]

in ['0'.. '9']) dobegin

l:=l+1;p2:=p2+pq[l];

end; {while}val(p1, n, j);if j>0 thenbegin

writeln('ошибка в выражении');halt;

end; {if}val(p2, m, j);if j>0 thenbegin

writeln('ошибка в выражении');halt;

end; {if}case pq[k] of

'+': j:=n+m;'-': j:=n-m;

end; {case}str(j, p1);delete(pq, 1, l);insert(p1, pq, 1)

end; {while}{все сложения и вычитания выполнены}

val(pq, n, j);if j>0 thenbegin

writeln('ошибка в выражении');halt;

end; {if}writeln('=', pq);readln;

end.Оператор halt − стандартная процедура, которая

завершает выполнение программы и выполняет возврат в операционную систему.

Пример 8Подсчитать, сколько букв а в тексте.

Program Example_136;uses crt;var a: string;

i, s: integer;begin

clrscr;writeln('Введите текст');readln(a);s:=0;for i:=1 to length(a) dobegin

if (copy (a, i, 1)= 'a') or

53

Page 52: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

(copy(a, i, 1)= 'A') thens:=s+1;

end;writeln('В заданном тексте буква <a>

встречается ', s, ' раза');end.

Пример 9Найти сумму двух целых чисел, которые вводятся с

клавиатуры, а также сумму цифр каждого из цифр.

Program Example_137;uses crt;var a, b, c1, c2, i, k, s, sa, sb: integer;

ca, cb: string[5];begin

clrscr;s:=0; sa:=0; sb:=0;write('Задайте 1-е число'); readln(a);write('Задайте 2-е число'); readln(b);s:=a+b;str(a, ca); str(b, cb);for i:=1 to length(ca) dobegin

val(copy(ca, i, 1), c1, k);sa:=sa+c1;

end;for i:=1 to length(cb) dobegin

val(copy(cb, i, 1), c2, k);sb:=sb+c2;

end;writeln(' Сумма чисел равна ',s);writeln(' Сумма цифр 1-го числа= ', sa)writeln(' Сумма цифр 2-го числа= ', sb);readln;

end.

Пример 10Определить, каких цифр в числе больше: четных

или нечетных.

Program Example_138;uses crt;var a: string[5];

b: string[1];i, k, s, sn, x: integer;

beginclrscr;s:=0; sn:=0write('Задайте число'); readln(a);for i:=1 to length(a) dobegin

b:=copy(a, i, 1);val(b, x, k);if x mod 2=0 then s:=s+1

else sn:=sn+1;end;if s>sn then

writeln('четных цифр больше');if s<sn then

writeln('нечетных цифр больше');if s=sn then writeln('Одинаково');

end.

§51. МНОЖЕСТВЕННЫЙ ТИП ДАННЫХ

Множество в языке Паскаль представляет собой

набор различных элементов одного (базового) типа.Базовый тип − это совокупность всех возможных

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

Множества, используемые в программе, могут быть описаны либо в разделе Type:

Type <имя типа>=Set Of <тип элементов>;Var <имя множества>: <имя типа>;

либо непосредственно в разделе описания переменных Var:Var <имя множества>:

Set Of <тип элементов>;

ПримерType mnog_Char=Set Of Char;Var mn1: Set Of Char;mn2: mnog_Char;mn3: Set Of 'A'..'Z';s1: Set Of Byte;s2: Set Of 1000..1200;Здесь mn1 и mn2 − это множества символов; так

как различных символов всего 256, то тип Char можно использовать в качестве базового;

mn3 − множество больших латинских букв;s1 − множество целых чисел (от 0 до 255); так как

тип Byte содержит только целые числа от 0 до 255 (всего 256 различных чисел), его тоже можно использовать в качестве базового типа элементов;

s2 − множество целых чисел от 1000 до 1200.

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

Пример Type digit=Set Of 1..5;Var s: digit;

Переменная s может принимать значения, состоя-щие из любой совокупности целых чисел от 1 до 5:

[ ] − пустое множество;[I], [2], [3], [4], [5] − одноэлементные

множества;[1, 2], [1, 3], ..., [2, 4], [4, 5] −

двухэлементные (пара любых элементов);[1, 2, 3], [1, 2, 4],..., [3, 4, 5] −

трехэлементные (тройка элементов);[1, 2, 3, 4], [1, 2, 3, 5], [1, 2 ,

4, 5], [1, 3, 4, 5], [2, 3, 4, 5] − четырехэлементные;

[1, 2, 3, 4, 5] − полное множество (взяты

54

Page 53: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

все элементы базового типа).

Операции над множествами

Объединением двух данных множеств называется множество элементов, принадлежащих хотя бы одно-му из этих множеств. Знак операции объединения множеств в Паскале − "+".

Примеры1) ['А','F']+['В','D']=['A','F','B','D'];2) [1..3, 5, 7, 11]+[3..8, 10, 12,

15..20]=[1..8, 10..12, 15..20]Пусть S1:=[1..5, 9], a S2:=[3 .. 7, 12].

Тогда если S:=S1+S2, то S=[1..7, 9, 12].Пусть A1:=['a'..'z']; A1:=A1+['A'].

Тогда А1=['А', 'a'..'z'].

Пересечением двух множеств называется множество элементов, принадлежащих одновременно и первому, и второму множеству. Знак операции пересечения множеств в Паскале − "*".

Примеры1) ['А', 'F']*['В', 'D']=[ ], так как общих

элементов нет;2) [1..3, 5, 7, 11]*[3..8, 10, 12,

15..20]=[3, 5, 7];3) если S1:=[1..5, 9] и S2:=[3..7, 12], a

S:=SI*S2, то S=[3. .5].

Разностью двух множеств называется множество, состоящее из тех элементов первого множества, которые не являются элементами второго. Знак операции вычитания множеств − "−".

Примеры1) ['А', 'F']-['В', 'D']=['А', 'F'], так как

общих элементов нет;2) [1..3, 5, 7, 11]-[3..8, 10, 12, 15..20]

=[1, 2, 11];3) S1:=[1..5, 9]; S2:=[3..7, 12]; S:=S1-

S2; Тогда S=[1, 2, 9];4) А1:=['А'..'Z']; А1:=А1-['А']. Тогда

А1=['В'..'Z'].

Операция определения принадлежности элемента множеству

Эта логическая операция обозначается служебным словом in. Результат операции имеет значение true, если элемент входит в множество, и false в против-ном случае.

Примеры1) Выражение 5 in [3..7] имеет значение

true, так как 5[3; 7];2) выражение 'a' in ['A'..'Z'] имеет значе-

ние false, так как маленькой латинской буквы 'а' нет среди больших латинских букв.

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

проверок. Например, оператор вида:If (ch='a') or (ch='b') or (ch='x')

or (ch='y') Then... − может быть переписан в компактной и наглядной форме:

If ch in ['a', 'b', 'х', 'у'] Then...

Сравнение множеств

Для сравнения множеств используются операции отношения:

= − проверка на равенство (совпадение) двухмножеств;

<> − проверка на неравенство двух множеств;<=, < − проверка на вхождение первого множества

во второе множество;>=, > − проверка на вхождение второго множества

в первое множество.

Пример 1Составить программу выделения следующих

множеств из множества целых чисел от 1 до 30:− множества чисел, кратных 2;− множества чисел, кратных 3;− множества чисел, кратных 6;− множества чисел, кратных 2 или 3.

Вопросы для обсуждения1. Сколько множеств надо описать? Каков тип их

элементов? (Четыре множества с элементами типа Byte.)

2. Каково начальное значение множеств? (Начальное значение множеств − пустое множество.)

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

4. Как осуществить вывод сформированных множеств? (Вывод множеств производится ТОЛЬКО поэлементно, поэтому удобно составить процедуру и передавать в нее множество, элементы которого и будут выводиться на экран. Для этого в разделе типов надо создать соответствующий тип и использовать его в дальнейшем.)

Программа для решения данной задачи выглядит так:

Program Example_139;Const n = 30;Type mn=Set Of 1..n;Var n2, n3, n6, n23: mn;

{n2 - множество чисел, кратных 2, n3 - кратных 3, n6 - кратных 6, n23 - кратных 2 или 3}k: Integer;

Procedure Print(m: mn);Var i: Integer;Begin

For i:=1 To n DoIf i In m Then Write(i:3);Writeln;

End;Begin

n2:=[ ]; n3:=[ ];

55

Page 54: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

{начальные значения множеств}For k:=1 To n Do {формирование n2 и n3}Begin

{если число делится на 2, то заносим его в n2}

If k Mod 2=0 Then n2:=n2+[k];{если число делится на 3, то добавляем его в n3}If k Mod 3=0 Then n3:=n3+[k];

End;{числа, кратные 6, - это те, которыекратны и 2, и 3, поэтому это пересечениедвух первых множеств, а числа, кратные 2или 3, - это объединение этихже множеств}n6:=n2*n3; n23:=n2+n3; {вывод множеств}Writeln('числа, кратные 2');Print(n2);Writeln('числа, кратные 3');Print(n3);Writeln('числа, кратные 6');Print(n6);Writeln('числа, кратные 2 или 3');Print(n23);Readln;

End.

ЗаданиеИзменить программу так, чтобы результатом ее

работы являлось множество чисел, делящихся на 3, но не делящихся на 2.

Пример 2"Мешанина". Если взять то общее, что есть у боба с

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

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

элементов? (Четыре множества с элементами символьного типа.)

2. Как сформировать множества? (С помощью оператора присваивания: например,

s1:=['б', 'о', 'б'])3. Как сформировать искомые множества? (С

помощью операций пересечения, объединения, вычитания множеств.) Программа для решения этой задачи приведена ниже:

Program Example_140;Var y1, y2, у3, у4, х: Set of Char;

s: Char;Begin

у1:=['б', 'о', 'б']; y2:=[ 'л', 'о', 'ж', 'к', 'а'];у3:=['к', 'о', 'т']; у4:=['т', 'е', 'п', 'л', 'о'];х:=(у1*у2)+у3-у4;Writeln ('множество х'); {вывод множества х} For s:='a' То 'я' Do

If s in x Then Write (s); Writeln;{проверка: состоит ли муравей из кота}If у3<=х Then Write ('муравей состоит

из кота')Else Write('муравей не состоит

из кота');End.

Пример 3Дано натуральное число n. Составить программу,

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

Вопросы для обсуждения1. Какое множество нужно сформировать?

(Множество цифр, входящих в десятичную запись данного числа.)

2. Как сформировать это множество? (С помощью операций div и mod последовательно выделить цифры данного числа и занести их во множество.)

3. Как получить искомый результат и как его вывести?

Программа для решения этой задачи такова:

Program Example_141;Type mn=Set Of 0..9;Var s: mn;

n: Longint;k: Integer;

BeginWriteln('введите число n');Readln(n);s:=[ ]; {формирование множества цифрдесятичной записи натурального числа}While n<>0 Do

Begink:=n Mod 10;n:=n Div 10;If Not (k in s) Then s:=s+[k];

End;{вывод цифр в порядке возрастания}For k:=0 To 9 DoIf Not (k in s) Then Write(k:2);Writeln;Readln;

End.Пример 4

"Решето Эратосфена". Составить программу поиска простых чисел в промежутке [1; n]. Число n вводится с клавиатуры.

РешениеПростым называется число, которое не имеет

других делителей, кроме единицы и самого этого числа. Для решения этой задачи воспользуемся методом "решета Эратосфена", идея которого заключается в следующем: сформируем множество М, в которое поместим все числа заданного промежутка. Затем последовательно будем удалять из него элементы, кратные 2, 3, 4 и так далее, до [n/2] (целая часть числа). После такого "просеивания" в множестве М останутся только простые числа.

Примечание. Легко доказать, что можно удалять числа, кратные 2, 3, 4 и так далее, до [sqrt(n)], то есть до целой части квадратного корня числа n.

Ниже приведен вариант решения этой задачи.

Program Example_142;Var m: Set Of Byte;

i, k, n: Integer;Begin

Writeln('введите размер промежутка

56

Page 55: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

(до 255)');Readln(n);m:=[2..n]; {начальное значение} For k:=2 To n Div 2 Do {перебираем все делители } For i:=2 To n Do {если число кратно делителю и отлично от него, то удаляемего}If (i Mod k=0) And (i<>k) Then m:=m-[i];{распечатаем оставшиеся элементы}For i:=1 To n Do

If i in m Then Write(i:3);Readln;

End.Пример 5

Дан ребус:

МУХАМУХАСЛОН

РешениеКаждой букве соответствует некоторая цифра,

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

Для решения этой задачи применим метод перебора с возвратом. Используем множество S1 для хранения цифр слова МУХА, причем будем заносить в него цифры последовательно, учитывая уже внесенные цифры. Начальное значение S1 − пустое множество. После выбора всех цифр первого слова формируем соответствующее число и находим число, соответствующее слову СЛОН. Выделяем цифры СЛОНа (множество S2), и если слова состоят из разных цифр (то есть пересечение S1 и S2 пустое) и все цифры СЛОНа разные, то выводим решение на экран. Далее удаляем из множества S1 последнюю внесенную цифру и пытаемся выбрать еще одно ее значение. Таким образом, мы перебираем все возможные варианты и выводим на экран только те, которые удовлетворяют равенству.

Заметим, что букве “М” в слове МУХА может соот-ветствовать цифра от 1 до 4, а букве “А” в этом же слове не может соответствовать 0.

Ниже приводится одно из решений.

Program Example_143;Type mn=Set Of 0..9;Var m, y, x, a: 0..9; {цифры числа МУХА}

n1, n2: Integer; {числа МУХА и СЛОН}a1, a2, a3, a4: 0..9; {цифры числа СЛОН}s1, s2: mn;{для хранения цифр каждого из чисел}

Procedure Print (x,у: Integer); {вывод решения в виде ребуса}Begin

Writeln(x:5);Writeln('+');Writeln(x:5);Writeln(' _____');Writeln(y:5);

End;Begin

s1:=[ ]; s2:=[ ];

For m:=1 To 4 Do Begin

s1:=s1+[m]; {заносим первую использованную цифру}For у:=0 To 9 Do {если эта цифра небыла еще взята, то добавляем ее вомножество цифр числа МУХА и выбираемцифру для следующей буквы}If Not (у in s1) Then Begin

s1:=s1+[y];For x:=0 To 9 Do If Not (x in s1) ThenBegin

s1:=s1+[x];For a:=1 To 9 Do If Not (a in s1) ThenBegin

s1: =s1+[a];n1 :=1000*m+100*y-10*x+a;{число для слова МУХА}n2:=2*n1;{число для слова СЛОН}a1:=n2 Div 1000;{выделяем цифры СЛОНа}а2:=n2 Div 100 Mod 10;a3:=n2 Div 10 Mod 10;a4:=n2 Mod 10;s2:=[a1, a2, a3, a4];{множество цифр СЛОНа}{если слова состоят из разныхцифр и в слове СЛОН нет одинаковых букв, то выводимрешение ребуса на экран} If (s1*s2=[ ]) And

([al]*[a2]*[a3]*[a4]=[ ])Then Print(n1, n2);s1:=s1-[a];{удаляем занесенную цифру}

End;s1:=s1-[x];

End;s1:=s1-[y];

End;s1:=s1-[m];

End;Readln;

End.

§52. КОМБИНИРОВАННЫЙ ТИП ДАННЫХ (ЗАПИСИ)

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

Пример 1 Известны фамилии и оценки (в баллах) по пяти

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

В данном случае фамилия может быть представлена символьной строкой, оценки − это целые числа, а средний балл должен быть представлен вещественным (действительным) числом. В Паскале

57

Page 56: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

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

Запись − это структурированный тип, описывающий набор данных разных типов. Составляющие запись объекты называются ее полями. Каждое поле имеет уникальное (в пределах записи) имя. Чтобы описать запись, необходимо указать ее имя, имена объектов, составляющих запись, и их типы. Общий вид описания записи следующий:

Type <имя записи>=Record <поле 1>:<тип 1>;<поле 2>:<тип 2>;<поле n>:<тип n>End;

Применительно к рассматриваемой задаче запись можно описать следующим образом:

Typepupil=Recordfam: String[15]; {поле фамилии ученика}b1, b2, b3, b4, b5: 2..5;{поля баллов по дисциплинам}sb: Real{поле среднего балла}

End;Переменная типа pupil будет хранить структуру,

содержащую информацию об одном ученике.Чтобы хранить в памяти ЭВМ информацию обо

всех 25 учениках класса, необходимо ввести массив klass, представляющий массив записей:

Var klass: Array[1..25] Of pupil;Примечания1. Имена полей, составляющих запись, не должны

повторяться.2. Каждое поле записи может иметь любой тип

(кроме файлового), в частности, оно может быть снова записью.

Доступ к полям записи можно осуществить двумя способами:

С указанием имени переменной и имени поля. Например, klass[2].fam, klass[3].sb, klass[1].b4. Ввод фамилий и оценок учащихся, то есть элементов массива klass, можно записать так:For i:=1 To 25 Do Begin

Readln(klass[i].fam);Readln(klass[i].b1);Readln(klass[i].b2);Readln(klass[i].b3);Readln(klass[i].b4);Readln(klass[i].b5);

End;С использованием оператора присоединения.

Имеется возможность осуществлять доступ к полям записи таким образом, как если бы они были простыми переменными. Общий вид оператора присоединения:

With <имя записи> Do <оператор>;Внутри оператора присоединения к компонентам

записи можно обращаться только с помощью имени соответствующего поля.

Пример 2

For i:=1 To 25 Do With klass [i] Do

BeginReadln(fam);Readln (b1, b2, b3, b4, b5);

End;

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

Program Example_144;Туре

pupil=Record fam: String[15] ;b1, b2, b3, b4, b5:2..5;sb: Real;

End;Var klass: Array[1..25] Of pupil;

p: pupil;i, m: Integer;sbmax: Real;

BeginFor i:=1 To 25 Do {ввод исходных данных}With klass[i] DoBegin

Writeln ('Введите фамилию и пятьоценок');

Readln(fam);Readln(b1, b2, b3, b4, b5);

End;For i:=1 To m Do {вычисление среднего балла}

With klass[i] Do sb:=(b1+b2+b3+b4+b5)/5;

For i:=1 To 25 Do {вывод данных}With klass[i] Do

Writeln(fam:20, '-', b1:5,b2:5,b3:5,b4:5,b5:5,sb:6:3);

sbmax:=0;{поиск максимального среднего балла}For i:=1 To m Do If klass[i].sb>=sbmax Then

sbmax:=klass[i].sb;For i:=1 To m Do {печать результатов}

If klass[i].sb=sbmax ThenWith klass[i] Do Writeln(fam:20,' - ',

sb: 6:3);Readln;

End.

Пример 3Определить дату завтрашнего дня.

РешениеЧтобы определить дату завтрашнего дня, надо

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

Пусть дата вводится в формате число − месяц − год следующим образом:

1 2 1997Опишем запись для хранения даты таким образом:

Type year=1500..2000;month=1..12;

58

Page 57: 1  · Web view5) следует избегать схожих по виду имен (АХ1 и axi), подобных по написанию символов в пределах

day=1..31;data=Record у: year;m: month;d: day;

End;Заметим, что:Если дата соответствует не последнему дню меся-

ца, то год и месяц не изменяются, а число увели-чивается на 1.

Если дата соответствует последнему дню месяца, то:

а) если месяц не декабрь, то год не изменяется, месяц увеличивается на 1, а число устанавливается в 1;

б) если месяц − декабрь, то год увеличивается на 1, а месяц и число устанавливаются в 1.

Program Example_145;Type year=1500..2000;

month=1..12;day=1..31;data=Record у: year;m: month;d: day;End;

Var dat, next: data;{dat - переменная для сегодняшней даты next - переменная для определения датызавтрашнего дня}

Function Leap(yy: year ): Boolean; {функция, определяющая, високосный год или нет} Begin{год называется високосным, если его номер делится на 4, но если это год столетия, то номер столетия високосного года не делится на 4, то есть не номер года делится на 400}

Leap:=(yy Mod 4=0) And (yy Mod 400<>0);End;Function Dmonth (mm: month; yy: year): day;{функция определения количества дней

данного месяца в данном году}Begin

Case mm Of1, 3, 5, 7, 8, 10, 12: Dmonth:=31;4, 6, 9, 11: Dmonth:=30;2: If Leap (yy) Then Dmonth:=29

Else Dmonth:=28;End;

End;Procedure Tomorrow(td: data; Var nd: data);

{процедура определения завтрашней даты}Begin {если это не последний день месяца}

If td.d<>Dmonth(td.m, td.у) Then With nd Do Begin d:=td.d+1;

m:=td.m;y:=td.y;

EndElse {если это последний день месяца}If td.m=12 Then {если это декабрь}With nd Do Begin

d:=1;m:=1;y:=td.y+1;

EndElse {если это не декабрь}With nd DoBegin

d:=1;m:=td.m+1;y:=td.y;

End;End;begin

Writeln('Введите сегодняшнее число, месяц и год ');

Readln(dat.d, dat.m, dat.y);Tomorrow(dat, next);Writeln('Завтра будет ');Writeln(next.d, '.', next.m, '.',

next.y);Readln;

End.

59