Основы программирования на языке Паскаль
| Примеры описания массивов: |
|Var |
|S, BB : Array [1..40] Of Real; |
|N : Array ['A'..'Z'] Of Integer; |
|R : Array [-20..20] Of Word; |
|T : Array [1..40] Of Real; |
| Теперь переменные S, BB и T представляют собой массивы из сорока |
|вещественных чисел; массив N имеет индексы символьного типа и целочисленные|
|элементы; массив R может хранить в себе 41 число типа Word. |
| Единственным действием, которое возможно произвести с массивом целиком|
|- присваивание. Для данного примера описания впоследствии допустима |
|следующая запись: |
| S:=BB; |
| Однако, присваивать можно только массивы одинаковых типов. Даже |
|массиву T присвоить массив S нельзя, хотя, казалось бы, их описания |
|совпадают, произведены они в различных записях раздела описания. |
| Никаких других операций с массивами целиком произвести невозможно, но |
|с элементами массивов можно работать точно также, как с простыми |
|переменными соответствующего типа. Обращение к отдельному элементу массива |
|производится при помощи указания имени всего массива и в квадратных скобках|
|- индекса конкретного элемента. Например: |
|R[10] - элемент массива R с индексом 10. |
| Фундаментальное отличие компонента массива от простой переменной |
|состоит в том, что для элемента массива в квадратных скобках может стоять |
|не только непосредственное значение индекса, но и выражение, приводящее к |
|значению индексного типа. Таким образом реализуется косвенная адресация: |
|BB[15] - прямая адресация; |
|BB[K] - косвенная адресация через переменную K, значение которой будет |
|использовано в качестве индекса элемента массива BB. |
| Такая организация работы с такой структурой данных, как массив, |
|позволяет использовать цикл для заполнения, обработки и распечатки его |
|содержимого. |
| Если вы помните, с такой формой организации данных мы встречались, |
|когда изучали строковые переменные. Действительно, переменные типа String |
|очень близки по своим свойствам массивам типа Char. Отличия в следующем: |
|строковые переменные можно было вводить с клавиатуры и распечатывать на |
|экране (с обычным массивом это не проходит); длина строковой переменной |
|была ограничена 255 символами (255 B), а для размера массива критическим |
|объемом информации является 64 KB. |
| Теперь рассмотрим несколько способов заполнения массивов и вывода их |
|содержимого на экран. В основном мы будем пользоваться числовыми типами |
|компонент, но приведенные примеры будут справедливы и для других типов |
|(если они допускают указанные действия). |
|Program M1; |
|Var |
| A : Array [1..20] Of Integer; |
|Begin |
|A[1]:=7; {Заполняем массив значениями (отдельно каждый компонент)} |
|A[2]:=32; |
|A[3]:=-70; |
|.............. {Трудоемкая задача?} |
|A[20]:=56; |
|Writeln(A[1],A[2],A[3], ?,A[20]) |
|End. |
| Как бы ни был примитивен приведенный пример, он все же иллюстрирует |
|возможность непосредственного обращения к каждому элементу массива |
|отдельно. Правда, никакого преимущества массива перед несколькими простыми |
|переменными здесь не видно. Поэтому - другой способ: |
|Program M2; |
|Var |
|A : Array [1..20] Of Integer; |
|I : Integer; |
|Begin |
|For I:=1 To 20 Do {Организуем цикл с параметром I по всем возможным} |
|Readln(A[I]); {значениям индексов и вводим A[I] с клавиатуры } |
|For I:=20 Downto 1 Do {Распечатываем массив в обратном порядке} |
|Write(A[I],'VVV') |
|End. |
| Эта программа вводит с клавиатуры 20 целых чисел, а затем |
|распечатывает их в обратном порядке. Теперь попробуйте написать такую же |
|программу, но без использования структуры массива. Во сколько раз она |
|станет длиннее? Кстати, введение язык Паскаль цикла с параметром было |
|обусловлено во многом необходимостью обработки информационных |
|последовательностей, т. е. массивов. |
| Следующая программа заполняет массив значениям квадратов индексов |
|элементов: |
|Program M3; |
|Const |
|N=50; {Константа N будет содержать количество элементов массива} |
|Var |
|A : Array [1..N] Of Integer; |
|I : Integer; |
|Begin |
|For I:=1 To N Do |
|A[I]:=I*I |
|For I:=1 To N Do |
|Write(A[I],'VVV') |
|End. |
| В дальнейшем для учебных целей мы будем использовать массивы, заданные|
|с помощью генератора случайных чисел. В языке Паскаль случайные числа |
|формирует функция Random. Числа получаются дробными, равномерно |
|расположенными в интервале от 0 до 1. Выражение, дающее целое случайное |
|число в интервале [-50,50] будет выглядеть так: |
|Trunc(Random*101)-50 |
|Зададим и распечатаем случайный массив из сорока целых чисел: |
|Program M4; |
|Const |
|N=40; {Константа N будет содержать количество элементов массива} |
|Var |
|A : Array [1..N] Of Integer; |
|I : Integer; |
|Begin |
|For I:=1 To N Do |
|Begin |
|A[I]:= Trunc(Random*101)-50 |
|Write(A[I],'VVV') |
|End |
|End. |
| С обработкой линейных массивов связано множество задач. Их мы |
|рассмотрим на практических занятиях. |
| |
|Двумерные и многомерные массивы |
|Представьте себе таблицу, состоящую из нескольких строк. Каждая строка |
|состоит из нескольких ячеек. Тогда для точного определения положения ячейки|
|нам потребуется знать не одно число (как в случае таблицы линейной), а два:|
|номер строки и номер столбца. Структура данных в языке Паскаль для хранения|
|такой таблицы называется двумерным массивом. Описать такой массив можно |
|двумя способами: |
|I. |
|Var |
| A : Array [1..20] Of Array [1..30] Of Integer; |
|II. |
|Var |
| A : Array [1..20,1..30] Of Integer; |
|В обоих случаях описан двумерный массив, соответствующий таблице, состоящей|
|из 20 строк и 30 столбцов. Приведенные описания совершенно равноправны. |
|Отдельный элемент двумерного массива адресуется, естественно, двумя |
|индексами. Например, ячейка, находящаяся в 5-й строке и 6-м столбце будет |
|называться A[5][6] или A[5,6]. |
|Для иллюстрации способов работы с двумерными массивами решим задачу: |
|"Задать и распечатать массив 10X10, состоящий из целых случайных чисел в |
|интервале [1,100]. Найти сумму элементов, лежащих выше главной диагонали." |
|При отсчете, начиная с левого верхнего угла таблицы, главной будем считать |
|диагональ из левого верхнего угла таблицы в правый нижний. При этом |
|получается, что элементы, лежащие на главной диагонали будут иметь |
|одинаковые индексы, а для элементов выше главной диагонали номер столбца |
|будет всегда превышать номер строки. Договоримся также сначала указывать |
|номер строки, а затем - номер столбца. |
|Program M5; |
|Var |
|A : Array[1..10,1..10] Of Integer; |
|I, K : Byte; |
|S : Integer; |
|Begin |
|S:=0; |
|For I:=1 To 10 Do |
|Begin |
|For K:=1 To 10 Do |
|Begin |
|A[I,K]:=Trunc(Random*100)+1; |
|Write(A[I,K]:6); |
|If K>I Then S:=S+A[I,K] |
|End; |
|Writeln |
|End; |
|Writeln('Сумма элементов выше гл. диагонали равнаV',S) |
|End. |
|Если модель данных в какой-либо задаче не может свестись к линейной или |
|плоской таблице, то могут использоваться массивы произвольной размерности. |
|N-мерный массив характеризуется N индексами. Формат описания такого типа |
|данных: |
|Type |
|=Array[,,... |
|] Of ; |
|Отдельный элемент именуется так: |
| [,,...,] |
| |
|Процедуры и функции |
|При решении сложных объемных задач часто целесообразно разбивать их на |
|более простые. Метод последовательной детализации позволяет составить |
|алгоритм из действий, которые, не являясь простыми, сами представляют собой|
|достаточно самостоятельные алгоритмы. В этом случае говорят о |
|вспомогательных алгоритмах или подпрограммах. Использование подпрограмм |
|позволяет сделать основную программу более наглядной, понятной, а в случае,|
|когда одна и та же последовательность команд встречается в программе |
|несколько раз, даже более короткой и эффективной. |
|В языке Паскаль существует два вида подпрограмм: процедуры и функции, |
|определяемые программистом. Процедурой в Паскале называется именованная |
|последовательность инструкций, реализующая некоторое действие. Функция |
|отличается от процедуры тем, что она должна обязательно выработать значение|
|определенного типа. |
|Процедуры и функции, используемые в программе, должны быть соответствующим |
|образом описаны до первого их упоминания. Вызов процедуры или функции |
|производится по их имени. |
|Подпрограммы в языке Паскаль могут иметь параметры (значения, передаваемые |
|в процедуру или функцию в качестве аргументов). При описании указываются |
|так называемые формальные параметры (имена, под которыми будут фигурировать|
|передаваемые данные внутри подпрограммы) и их типы. При вызове подпрограммы|
|вместе с ее именем должны быть заданы все необходимые параметры в том |
|порядке, в котором они находятся в описании. Значения, указываемые при |
|вызове подпрограммы, называются фактическими параметрами. |
|Формат описания процедуры: |
|Procedure (:; |
|< Имя форм. параметра 2>:?); |
| |
|Begin |
| |
|End; |
|Раздел описаний может иметь такие же подразделы, как и раздел описаний |
|основной программы (описание процедур и функций - в том числе). Однако все |
|описанные здесь объекты "видимы" лишь в этой процедуре. Они здесь локальны |
|также, как и имена формальных параметров. Объекты, описанные ранее в |
|разделе описаний основной программы и не переопределенные в процедуре, |
|называются глобальными для этой подпрограммы и доступны для использования. |
|Легко заметить схожесть структуры программы целиком и любой из ее процедур.|
|Действительно, ведь и процедура и основная программа реализуют некий |
|алгоритм, просто процедура не дает решения всей задачи. Отличие в заголовке|
|и в знаке после End. |
|Формат описания функции: |
|Function (:; |
|< Имя форм. параметра 2>:?) : ; |
| |
|Begin |
| |
|End; |
|В теле функции обязательно должна быть хотя бы команда присвоения такого |
|вида: :=; |
|Указанное выражение должно приводить к значению того же типа, что и тип |
|результата функции, описанный выше. |
|Вызов процедуры представляет в программе самостоятельную инструкцию: |
|(, < Фактический параметр 2>?); |
|Типы фактических параметров должны быть такими же, что и у соответсвующих |
|им формальных. |
|Вызов функции должен входить в выражение. При вычислении значения такого |
|выражения функция будет вызвана, действия, находящиеся в ее теле, будут |
|выполнены, в выражение будет подставлено значение результата функции. |
|Приведем простейший пример использования подпрограммы. |
|Задача: "Найти максимальное из трех введенных чисел". Для решения |
|воспользуемся описанием функции, принимающей значение максимального из двух|
|чисел, которые передаются в нее в виде параметров. |
|Program Fn; |
|Var |
|A,B,C :Real; |
|Function Max(A,B:Real):Real; {Описываем функцию Max с формальными} |
|Begin {параметрами A и B, которая принимает } |
|If A>B Then Max:=A {значение максимального из них } |
|Else Max:=B {Здесь A и B - локальные переменные } |
|End; |
|Begin |
|Writeln('Введите три числа'); |
|Readln(A,B,C); |
|Writeln('Максимальным из всех является ', Max(Max(A,B),C)) |
|End. |
|Обратите внимание на краткость тела основной программы и на прозрачность |
|действий внутри функции. Формальные параметры A и B, используемые в |
|подпрограмме, не имеют никакого отношения переменным A и B, описанным в |
|основной программе. |
|Существует два способа передачи фактических параметров в подпрограмму: по |
|значению и по ссылке. В первом случае значение переменной-фактического |
|параметра при вызове подпрограммы присваивается локальной переменной, |
|являющейся формальным параметром подпрограммы. Что бы потом ни происходило |
|с локальной переменной, это никак не отразится на соответствующей |
|глобальной. Для одних задач это благо, но иногда требуется произвести в |
|подпрограмме действия над самими переменными, указанными в качестве |
|фактических параметров. На помощь приходит второй способ. Происходит |
|следующее: при обращении к подпрограмме не происходит формирования |
|локальной переменной-формального параметра. Просто на время выполнения |
|подпрограммы имя этой локальной переменной будет указывать на ту же область|
|памяти, что и имя соответствующей глобальной переменной. Если в этом случае|
|изменить локальную переменную, изменятся данные и в глобальной. |
|Передача параметров по ссылке отличается тем, что при описании подпрограммы|
|перед именем переменной-формального параметра ставится служебное слово Var.|
|Теперь использование в качестве фактических параметров выражений или |
|непосредственных значений уже не допускается - они должны быть именами |
|переменных. |
|Еще один классический пример. Задача: "Расположить в порядке неубывания три|
|целых числа". |
|Program Pr; |
|Var |
| S1,S2,S3 :Integer; |
|Procedure Swap(Var A,B: Integer);{Процедура Swap с параметрами-переменными}|
| |
|Var C : Integer; {C - независимая локальная переменная} |
|Begin |
| C:=A; A:=B; B:=C {Меняем местами содержимое A и B} |
|End; |
|Begin |
|Writeln('Введите три числа'); |
|Readln(S1,S2,S3); |
|If S1>S2 Then Swap(S1,S2); |
|If S2>S3 Then Swap(S2,S3); |
|If S1>S2 Then Swap(S1,S2); |
|Writeln('Числа в порядке неубывания:V',S1,S2,S3) |
|End. |
| |
|Работа с файлами |
|Тип-файл представляет собой последовательность компонент одного типа, |
|расположенных на внешнем устройстве (например, на диске). Элементы могут |
|быть любого типа, за исключением самого типа-файла. Число элементов в файле|
|при описании не объявляется. Работа с физическими файлами происходит через |
|так называемые файловые переменные. |
|Для задания типа-файла следует использовать зарезервированные слова File и |
|Of, после чего указать тип компонент файла. |
|Пример: |
|Type |
|N = File Of Integer; {Тип-файл целых чисел} |
|C = File Of Char; {Тип-файл символов} |
|Есть заранее определенный в Паскале тип файла с именем Text. Файлы этого |
|типа называют текстовыми. |
|Введя файловый тип, можно определить и переменные файлового типа: |
|Var |
|F1 : N; |
|F2 : C; |
|F3 : Text; |
|Тип-файл можно описать и непосредственно при введении файловых переменных: |
|Var |
| Z : File Of Word; |
|Файловые переменные имеют специфическое применение. Над ними нельзя |
|выполнять никаких операций (присваивать значение, сравнивать и т.д.). Их |
|можно использовать лишь для выполнения операций с файлами (чтение, запись и|
|т.д.). |
|Элементы файла считаются расположенными последовательно, то есть так же, |
|как элементы линейного массива. Отличие же состоит в том, что, во-первых, |
|размеры файла могут меняться, во-вторых, способ обращения к элементам |
|совсем другой: невозможно обратиться к произвольному элементу файла; |
|элементы его просматриваются только подряд от начала к концу, при этом в |
|каждый момент времени доступен только один элемент. Можно представить себе,|
|что для каждого файла существует указатель, показывающий в данный момент на|
|определенный компонент файла. После проведения операции чтения или записи |
|указатель автоматически передвигается на следующий компонент. |
|Перед тем, как осуществлять ввод-вывод, файловая переменная должна быть |
|связана с конкретным внешним файлом при помощи процедуры Assign. |
|Формат: |
| Assign(,); |
|Имя файла задается либо строковой константой, либо через переменную типа |
|Sting. Имя файла должно соответствовать правилам работающей в данный момент|
|операционной системы. Если строка имени пустая, то связь файловой |
|переменной осуществляется со стандартным устройством ввода-вывода (как |
|правило - с консолью). |
|После этого файл должен быть открыт одной из процедур: |
|Reset(); |
|Открывается существующий файл для чтения, указатель текущей компоненты |
|файла настраивается на начало файла. Если физического файла, |
|соответствующего файловой переменной не существует, то возникает ситуация |
|ошибки ввода-вывода. |
|Rewrite(); |
|Открывается новый пустой файл для записи, ему присваивается имя, заданное |
|процедурой Assign. Если файл с таким именем уже существует, то он |
|уничтожается. |
|После работы с файлом он, как правило, должен быть закрыт процедурой Close.|
| |
|Close(); |
|Это требование обязательно должно соблюдаться для файла, в который |
|производилась запись. |
|Теперь рассмотрим непосредственную организацию чтения и записи. |
|Для ввода информации из файла, открытого для чтения, используется уже |
|знакомый вам оператор Read. Правда, в его формате и использовании вы |
|заметите некоторые изменения: |
|Read(, ); |
|Происходит считывание данных из файла в переменные, имена которых указаны в|
|списке ввода. Переменные должны быть того же типа, что и компоненты файла. |
| |
|Вывод информации производит, как можно догадаться оператор Write(, ); |
|Данные из списка вывода заносятся в файл, открытый для записи. |
|Для текстовых файлов используются также операторы Readln и Writeln с |
|соответствующими дополнениями, относящимися к файловому вводу-выводу. |
|Любопытно, что вывод данных на монитор и ввод с клавиатуры в языке Паскаль |
|тоже являются действиями с файлами. Они даже имеют свои предопределенные |
|файловые переменные текстового типа: Output и Input соответственно. |
|Переменная Output всегда открыта для записи, Input - для чтения. Если не |
|указывать файловые переменные в операторах ввода-вывода (придем к формату, |
|рассмотренному в теме "Операторы ввода-вывода"), то в случае записи по |
|умолчанию выбирается файл Output, в случае чтения - Input. |
|Как вы знаете, любой файл конечен и продолжать чтение из него информации |
|можно лишь до определенного предела. Как этот предел установить? Проверить,|
|окончен ли файл, можно вызовом стандартной логической функции Eof() |
|Она вырабатывает значение True, если файл окончен, и False - в противном |
|случае. |
|Решим следующую задачу: "Написать программу, которая вводит с клавиатуры |
|список фамилий учащихся, а затем распечатывает его, кроме тех учащихся, у |
|которых фамилия начинается с буквы 'Ш'". |
|Так как заранее количество данных не известно, то для их хранения |
|используем файл. Тип элементов - строковый. |
|Program L; |
|Var |
|I,N : Integer; |
|F : File Of String; |
|S : String; |
|Begin |
|Assign(F,'Spis.lst'); {Связываем переменную F с файлом Spis.lst} |
|Writeln('Введите количество учащихся'); |
|Readln(N); {Вводим количество учащихся} |
|Rewrite(F); {Создаем файл для записи в него данных} |
|For I:=1 To N Do {Для всех учащихся} |
|Begin |
|Writeln('Введите фамилию'); |
|Readln(S); |
|Write(F,S) |
|End; |
|Close(F); |
|Reset(F); |
|Writeln; Writeln('Список учащихся:'); |
|While Not(Eof(F)) Do |
|Begin |
|Read(F,S); |
|If S[1]<>'Ш' Then |
|Writeln(S) |
|End; |
|Close(F) |
|End. |
Страницы: 1, 2, 3, 4, 5
|