Основы программирования на языке Паскаль
	
	
|=(D1*(45-2))                                   | 
|     S<>'ABC' {Значение переменной S не равно строковой константе 'ABC'}   | 
|     Приведем пример решения еще одной задачи: "Из двух чисел выбрать      | 
|наибольшее".                                                               | 
|     На первый взгляд решение очевидно, но оно не столь тривиально, как    | 
|кажется.                                                                   | 
|Program Example;                                                           | 
|Var A,B,C : Real; {A,B - для хранения аргументов, C - результат}           | 
|Begin                                                                      | 
|Writeln('Введите два числа');                                              | 
|Readln(A,B);                            {Вводим аргументы с клавиатуры}    | 
|If A>B Then C:=A Else C:=B; B                                                                         | 
|Writeln(C);                               {Выводим результат на экран}     | 
|End.                                                                       | 
|     Еще один классический пример: "По заданным коэффициентам решить       | 
|квадратное уравнение". Эта задача сложнее, поэтому перед тем как писать    | 
|программу составим алгоритм, записав его в виде блок-схемы.                | 
|Сначала вводим коэффициенты, затем вычисляем дискриминант. Теперь возникает| 
|две возможности: либо отсутствие действительных корней в случае            | 
|отрицательного дискриминанта, либо эти корни можно все-таки вычислить и    | 
|вывести на экран в случае неотрицательного дискриминанта (случай равенства | 
|дискриминанта нулю входит сюда же, корней - два, только они одинаковые J). | 
|     При записи алгоритма на языке программирования следует учесть, что в  | 
|ветви "нет" не одно действие, а три, поэтому следует применить составной   | 
|оператор. Арифметические выражения не забывайте записывать в соответствии с| 
|правилами языка Паскаль. В остальном, эта программа не сложнее предыдущей. | 
|                                                                           | 
|                                                                           | 
|                                                                           | 
|Program Sq1;                                                               | 
|Var A, B, C, D, X1, X2 : Real;                                             | 
|Begin                                                                      | 
|Writeln ('Введите коэффициенты квадратного уравнения');                    | 
|Readln (A,B,C);                                                            | 
|D:=B*B-4*A*C;                                                              | 
|If D Do ;                                        | 
|     Правда, лаконично? По-русски можно прочитать так: "Пока истинно       | 
|условие, выполнять оператор". Здесь, так же как в формате условного        | 
|оператора, подразумевается выполнение только одного оператора. Если        | 
|необходимо выполнить несколько действий, то может быть использован         | 
|составной оператор. Тогда формат оператора принимает такой вид:            | 
|While  Do                                                         | 
|Begin                                                                      | 
|;                                                             | 
|;                                                             | 
|;                                                             | 
|. . .                                                                      | 
|End;                                                                       | 
|                                                                           | 
|Цикл "ДО"                                                                  | 
|     Этот вид цикла отличается от предыдущего в основном тем, что проверка | 
|условия повторения тела цикла находится не перед ним, а после. Поэтому цикл| 
|"До" называют циклом "с постусловием", а "Пока" - "с предусловием".        | 
|     Обратите также внимание на то, что новая итерация (повторное          | 
|выполнение тела цикла) происходит не тогда, когда условие справедливо, а   | 
|как раз тогда, когда оно ложно. Поэтому цикл и получил свое название       | 
|(выполнять тело цикла до выполнения соответствующего условия).             | 
|     Интересно, что в случае, когда условие цикла изначально истинно, тело | 
|цикла все равно будет выполнено хотя бы один раз. Именно это отличие "до"  | 
|от "пока" привело к тому, что в программировании они не подменяют друг     | 
|друга, а используются для решения задач, к которым они более подходят.     | 
|     Формат цикла на языке Pascal:                                         | 
|Repeat                                                                     | 
|;                                                             | 
|;                                                             | 
|;                                                             | 
|. . .                                                                      | 
|Until ;                                                           | 
|     Читается так: "Выполнять оператор #1, оператор #2. : до выполнения    | 
|условия".                                                                  | 
|     Здесь не требуется использование составного оператора, потому, что    | 
|сами слова Repeat и Until являются операторными скобками.                  | 
|                                                                           | 
|Цикл "С параметром".                                                       | 
|     В данном случае параметром будет являться целочисленная переменная,   | 
|которая будет изменяться на единицу при каждой итерации цикла. Таким       | 
|образом, задав начальное и конечное значения для такой переменной, можно   | 
|точно установить количество выполнений тела цикла. Нарисовать блок-схему   | 
|такой структуры вы сможете сами после некоторых пояснений.                 | 
|     Форматов у этого вида цикла предусмотрено два:                        | 
|    For := To  Do ;                            | 
|    For := Downto  Do ;                        | 
|     Здесь И.П. - имя переменной-параметра, Н.З. - его начальное значение, | 
|К.З. - соответственно конечное значение параметра. В качестве начального и | 
|конечного значений                                                         | 
|     Читается данная структура так: "Для переменной (далее следует ее имя) | 
|от начального значения до конечного выполнять оператор (являющийся телом   | 
|цикла)". Иногда цикл с параметром даже называют "Для" или "For". В первом  | 
|случае параметр с каждой итерацией увеличивается на единицу, во втором -   | 
|уменьшается.                                                               | 
|     Выполняется этот цикл по следующему алгоритму:                        | 
|    1. переменной-параметру присваивается начальное значение;              | 
|    2. выполняется тело цикла;                                             | 
|    3. переменная-параметр автоматически увеличивается на 1 (в первом      | 
|случае формата);                                                           | 
|    4. если параметр превышает конечное значение, то происходит выход из   | 
|цикла, иначе - переход к пункту 2.                                         | 
|     Примечание: при использовании Downto параметр автоматически           | 
|уменьшается на 1, а выход из цикла происходит тогда, когда параметр        | 
|становится меньше конечного значения.                                      | 
|     Таким образом, в отличие от первых двух видов цикла, этот цикл        | 
|используется тогда, когда известно необходимое количество выполнений тела  | 
|цикла.                                                                     | 
|     Вообще говоря, цикл "Пока" является универсальным, то есть любая      | 
|задача, требующая использования цикла, может быть решена с применением этой| 
|структуры. Циклы "До" и "С параметром" созданы для удобства                | 
|программирования.                                                          | 
|     Пример.                                                               | 
|     Найти сумму квадратов всех натуральных чисел от 1 до 100.             | 
|     Решим эту задачу с использованием всех трех видов циклов.             | 
|I. С использованием цикла "Пока".                                          | 
|Program Ex1;                                                               | 
|Var                                                                        | 
|   A : Integer;                                                            | 
|   S : Longint;                                                            | 
|Begin                                                                      | 
|A:=1; S:=0;                                                                | 
|While A100;                                                               | 
|Writeln(S)                                                                 | 
|End.                                                                       | 
|III. С использованием цикла "С параметром".                                | 
|Program Ex3;                                                               | 
|Var                                                                        | 
|    A : Integer;                                                           | 
|    S : Longint;                                                           | 
|Begin                                                                      | 
|S:=0;                                                                      | 
|For A:=1 To 100 Do S:=S+A*A;                                               | 
|Writeln(S)                                                                 | 
|End.                                                                       | 
|     Теперь вам известны все основные алгоритмические структуры языка      | 
|Паскаль. Комбинируя их, возможно запрограммировать решение любой задачи,   | 
|конечно, если таковое существует. Тем не менее, изучение языка на этом не  | 
|закачивается, так как для написания хороших программ по утверждению        | 
|уважаемого Никлауса Вирта (за время моей работы у меня не появилось        | 
|оснований в этом сомневаться) нужны кроме алгоритмических, еще удобные     | 
|структуры данных. В рассматриваемом языке таких структур множество, для    | 
|каждого вида определены свои команды и операции. К их рассмотрению мы и    | 
|переходим.                                                                 | 
|                                                                           | 
|Строковые операции                                                         | 
|     До сих пор мы с вами рассматривали программы, реализующие алгоритмы   | 
|обработки числовых данных. Однако хоть ЭВМ изначально и были созданы только| 
|для этой цели, по мере развития аппаратной части появилась возможность     | 
|оцифровывать данные других типов, хранить их в памяти машины,              | 
|перерабатывать, выводить во внешний по отношению к компьютеру мир. Проще   | 
|всего можно было так поступить с текстовой информацией. Если не ставить    | 
|перед машиной задачу "понимания" смысла текста, то задача оцифровки        | 
|сводится к установлению правил замены символов (литер) при вводе в         | 
|компьютер на их коды и обратной замены при выводе информации на экран или  | 
|принтер. Такие правила, конечно же, были составлены. Как водится, сначала  | 
|их было множество (вспомните разнообразие таблиц кодировки), затем весь мир| 
|остановился на ASCII.                                                      | 
|     Все языки программирования высокого уровня имеют средства работы с    | 
|литерными величинами. Паскаль - не исключение. Как вам уже известно, в     | 
|стандарте языка описаны два типа переменных для литерных величин. Это -    | 
|String и Char. Напомню - переменная типа Char может содержать в себе только| 
|один единственный символ, тип String предназначен для хранения строковых   | 
|величин до 255 символов длиною. Кстати, вы знаете не все о типе String. При| 
|описании переменной этого типа вы можете сами указать максимальное число   | 
|символов, которое можно занести в нее. Конечно же, это число не должно     | 
|превышать 255. Делается это так:                                           | 
|Var                                                                        | 
|S : String[30];                                                            | 
|     Для чего это нужно?                                                   | 
|     Дело в том, что при компиляции для каждой переменной отводится свой   | 
|участок памяти. Если мы будем выделять для всех переменных типа String по  | 
|256 байт, то это приведет к тому, что при использовании достаточно большого| 
|их количества, памяти может и не хватить? Но если в переменной мы          | 
|собираемся хранить, например, фамилию пользователя, то тридцати символов   | 
|(тридцати байт) для этого вполне достаточно. Таким образом, экономится     | 
|память и увеличивается быстродействие программ.                            | 
|     Переменным строкового типа можно присваивать строковые величины       | 
|(внутри программы они заключаются в апострофы), значения выражений, которые| 
|приводят к строковым величинам. Значения можно также вводить с клавиатуры. | 
|При этом апострофы не используются. Как вам известно, в числовую переменную| 
|нельзя ввести строковую величину. Сделать наоборот - возможно, однако      | 
|число, находящееся в строковой переменной представляет собой просто        | 
|последовательность символов (цифр), поэтому в арифметических выражениях    | 
|участвовать не может.                                                      | 
|     Также, новым для вас явится то, что при использовании строковой       | 
|переменной, к каждому ее символу можно обратиться отдельно. Необходимо     | 
|только знать номер нужного символа от начала строки. Его достаточно        | 
|поставить после имени переменной типа String в квадратных скобках.         | 
|     Пример: S[5] - пятый символ строки S.                                 | 
|     С отдельным символом строки можно производить все действия, которые   | 
|можно производить с любой символьной переменной (ввод, присвоение, вывод на| 
|экран, участие в выражениях и т.д.).                                       | 
|     Обратите внимание на то, что нумерация символов в строке начинается с | 
|единицы. Внутри квадратных скобок вместо числа может находиться выражение, | 
|результатом которого является целое число. Главное чтобы символ с таким    | 
|номером в строке существовал. Но как же узнать, сколько символов в данный  | 
|момент находится в строковой переменной? Для этого существует специальная  | 
|функция, которая возвращает длину строковой переменной в символах. Это     | 
|функция Length. Ее формат: Length(S)                                       | 
|     Здесь S - либо строковая величина, либо строковая переменная.         | 
|     Приведенная далее программа выводит на экран длину введенной          | 
|пользователем строковой величины.                                          | 
|Program Str1;                                                              | 
|Var                                                                        | 
|S : String;                                                                | 
|Begin                                                                      | 
|Writeln('Введите последовательность символов');                            | 
|Readln(S);                                                                 | 
|Writeln('Вы ввели строку из ',Length(S), ' символов')                      | 
|End.                                                                       | 
|     Другой пример:                                                        | 
|Решим задачу: "Введенную строку вывести на экран по одному символу в строке| 
|экрана".                                                                   | 
|Program Str2;                                                              | 
|Var                                                                        | 
|S : String;                                                                | 
|I : Byte;                                                                  | 
|Begin                                                                      | 
|Writeln('Введите строку');                                                 | 
|Readln(S);                                                                 | 
|For I:=1 to Length(S) do {организуем цикл, начиная с первого символа}      | 
|Writeln(S[I])                   {строки, до последнего (номер последнего}  | 
|{совпадает с количеством символов строки S) }                              | 
|End.                                                                       | 
|     Какие же еще действия можно выполнять с переменными строкового типа?  | 
|     Две строковые величины можно состыковывать. Эта операция называется   | 
|конкатенацией и обозначается знаком "+".                                   | 
|     Например, результатом выполнения следующих команд:                    | 
|   R:= 'kadabra';                                                          | 
|   H:= 'abra';                                                             | 
|   S:=H+R;                                                                 | 
|в переменной S будет значение 'abrakadabra'.                               | 
|     Для конкатенации результат зависит от порядка операндов (в отличие от | 
|операции сложения). Следует помнить о том, какой максимальной длины может  | 
|быть результирующая переменная, так как в случае превышения значением      | 
|выражения числа, указанного после String в описании переменной, "лишние"   | 
|символы в переменную не попадут.                                           | 
|     Строковые величины можно сравнивать между собой. Это относится также и| 
|к строковым переменным. Но как же компьютер определяет, какая строка       | 
|больше:                                                                    | 
|та, которая длиннее?                                                       | 
|та, которая содержит больше заглавных букв?                                | 
|     На самом деле такая проверка проходит довольно сложно: компьютер      | 
|сравнивает сначала первые символы строк. Большим из двух считается тот, код| 
|которого больше (вспомните, что такое код символа). Если равны первые      | 
|символы, то так же анализируется следующая пара до тех пор, пока не будет  | 
|найдено различие. Если начало строк совпадает, а одна из них кончается     | 
|раньше, то вторая автоматически называется большей.                        | 
|     Код символа в Паскале можно определить при помощи функции Ord.        | 
|     Ее формат: Ord(C), где С - либо непосредственно указанный символ, либо| 
|переменная символьного типа, либо один символ строковой переменной. Вообще,| 
|функция Ord имеет более глубокий смысл, но об этом - позже. Есть и обратная| 
|функция, которая возвращает символ по известному коду. Это функция Chr(N), | 
|где N - выражение, приводящее к целому числу в интервале от 0 до 255       | 
|(возможные значения кода символа). Очевидно, что Chr(Ord(C))=C,            | 
|Ord(Chr(N))=N.                                                             | 
|     Следующая маленькая программа выводит на экран кодовую таблицу:       | 
|Program Str3;                                                              | 
|Var                                                                        | 
|    I : Byte;                                                              | 
|Begin                                                                      | 
|For I:=32 to 255 do                                                        | 
|Write('VV',I:4, '-',Chr(I))                                                | 
|End.                                                                       | 
|     Цикл в программе начинается с 32 потому, что символы с кодами от 0 до | 
|31 являются управляющими и не имеют соответствующего графического          | 
|представления.                                                             | 
|     Задача: "Определить, является ли введенная строка "перевертышем".     | 
|Перевертышем называется такая строка, которая одинаково читается с начала и| 
|с конца. Например, "казак" и "потоп" - перевертыши, "канат" - не           | 
|перевертыш".                                                               | 
|     Поступим следующим образом: из введенной строки сформируем другую     | 
|строку из символов первой, записанных в обратном порядке, затем сравним    | 
|первую строку со второй; если они окажутся равны, то ответ положительный,  | 
|иначе - отрицательный. Естественно, предложенный способ решения не является| 
|единственно возможным.                                                     | 
|Program Str4;                                                              | 
|Var                                                                        | 
|     S,B : String;                                                         | 
|     I : Byte;                                                             | 
|Begin                                                                      | 
|Writeln('Введите строку');                                                 | 
|Readln(S);                                                                 | 
|B:='';              {Переменной B присваиваем значение "пустая строка"}    | 
|For I:=1 to Length(S) do                                                   | 
|B:=S[I]+B;     {Конкатенация. Символы строки S пристыковываются к}         | 
|{переменной B слева. Самым левым окажется последний.}                      | 
|If B=S Then Writeln('Перевертыш') Else Writeln('Не перевертыш')            | 
|End.                                                                       | 
|     Число, записанное в строковую переменную, естественно числом не       | 
|является, но очень часто требуется его все же использовать в качестве      | 
|числа. Для этого нужно произвести преобразование типа. Перевод строкового  | 
|представления числа в числовое выполняет в Паскале оператор Val.           | 
|Его формат:                                                                | 
|Val(S,X,C);                                                                | 
|     Здесь S - строка, содержащая число, X - числовая переменная, в которую| 
|будет помещен результат, С - переменная целочисленного типа, в которую     | 
|помещается первого встреченного в S отличного от цифры символа. Если после | 
|выполнения оператора Val переменная С имеет значение 0, то это означает,   | 
|что преобразование типа прошло совершенно успешно и в строке нецифровых    | 
|символов не встретилось.                                                   | 
|     Противоположное действие осуществляет оператор Str. Формат оператора: | 
|   Str(X,S);                                                               | 
|X - число (либо арифметическое выражение), S - строковая переменная.       | 
|     В переменную S попадает строковое представление числа X. Это нужно,   | 
|например, при необходимости выводить на экран числа в графическом режиме   | 
|(будет изучено позже), так как стандартные процедуры вывода на экран там   | 
|работают только со строковыми величинами.                                  | 
|     Для иллюстрации рассмотрим такую задачу: "Найти сумму цифр введенного | 
|натурального числа". Используя только числовые переменные, решить ее можно,| 
|но предлагаемое здесь решение, по-моему, проще.                            | 
|Program Str5;                                                              | 
|Var                                                                        | 
|S : String;                                                                | 
|I,X,A,C : Integer;                                                         | 
|Begin                                                                      | 
|Writeln('Введите натуральное число');                                      | 
|Readln(S); {Число вводится в строковую переменную}                         | 
|A:=0;                                                                      | 
|For I:=1 To Length(S) Do                                                   | 
|Begin                                                                      | 
|Val(S[I],X,C); {Цифровой символ превращается в число}                      | 
|A:=A+X {Цифры суммируются}                                                 | 
|End;                                                                       | 
|Writeln('Сумма цифр равна ',A)                                             | 
|End.                                                                       | 
|     Теперь рассмотрим еще несколько действий над строками:                | 
|оператор DELETE(S,I,C) из строковой переменной S удаляет C символов,       | 
|начиная с I-того;                                                          | 
|оператор INSERT(SN,S,I) вставляет подстроку SN в строковую переменную S    | 
|перед символом с номером I;                                                | 
|функция COPY(S,I,C) возвращает подстроку строки S из C символов, начиная с | 
|символа с номером I;                                                       | 
|функция Pos(SN,S) возвращает номер символа, с которого в строке S          | 
|начинается подстрока SN (позицию первого вхождения подстроки в строку).    | 
|Если такой подстроки нет, то возвращается ноль.                            | 
|     Пример их использования:                                              | 
|"Во введенной строке заменить все вхождения подстроки 'ABC' на подстроки   | 
|'KLMNO'".                                                                  | 
|Program Str6;                                                              | 
|Var                                                                        | 
|S : String;                                                                | 
|A : Byte;                                                                  | 
|Begin                                                                      | 
|Writeln('Введите строку');                                                 | 
|Readln(S);                                                                 | 
|While Pos('ABC',S)<>0 Do                                                   | 
|Begin                                                                      | 
|A:= Pos('ABC',S);                                                          | 
|Delete(S,A,3);                                                             | 
|Insert('KLMNO',S,A)                                                        | 
|End;                                                                       | 
|Writeln(S)                                                                 | 
|End.                                                                       | 
|                                                                           | 
|Определение типов                                                          | 
|     Как было упомянуто ранее, в изучаемом языке возможно определять новые | 
|типы переменных. После определения этот тип становится доступным для       | 
|описания переменных, также как и стандартные типы.                         | 
|     Новый тип перед первым его использованием должен быть описан в        | 
|соответствующем разделе описаний. Его заголовок - служебное слово Type.    | 
|Type                                                                       | 
|     = ;                                          | 
|     Есть несколько способов описания. Иногда говорят даже о видах типов   | 
|(как бы это странно ни звучало).                                           | 
|     Итак, первым рассмотрим так называемый перечисляемый тип.             | 
|     Перечисляемый тип используется для повышения наглядности программ,    | 
|позволяя записывать в переменные этого типа названия разнообразных         | 
|объектов, исследуемых программой. Этот тип представляет собой набор        | 
|идентификаторов, с которыми могут совпадать значения параметров.           | 
|     Формат описания следующий:  = (, ,? );    | 
|     Далее можно определить любое число переменных уже описанного типа.    | 
|Обратите внимание на то, что каждый идентификатор может участвовать в      | 
|описании только одного перечисляемого типа.                                | 
|     Этим переменным можно присваивать только значения из списка,          | 
|определенного при описании типа. Эти значения не являются ни числами, ни   | 
|строковыми величинами, ни даже величинами логического типа, поэтому они не | 
|могут участвовать в арифметических, строковых, логических выражениях, а    | 
|также не могут быть выведены на экран или принтер. Величины перечисляемого | 
|типа можно сравнивать между собой, над их множеством в языке Паскаль       | 
|определены несколько функций:                                              | 
|    Ord(X) - порядковый номер значения переменной X в списке               | 
|идентификаторов.                                                           | 
|    Succ(X) - следующее значение для величины Х.                           | 
|    Pred(X) - предыдущее значение данного типа.                            | 
|     Обратите внимание на то, что для функции Ord нумерация среди значений | 
|идет, начиная от нуля. Для последнего значения нельзя применять функцию    | 
|Succ, для первого - Pred.                                                  | 
|     Переменные различных перечисляемых типов несовместимы друг с другом.  | 
|     Множество стандартных порядковых типов в языке Паскаль на самом деле  | 
|определены как перечисляемые. Это типы Char, Integer, другие. Достоинства  | 
|стандартных порядковых типов лишь в том, что над каждым из них уже         | 
|определены специфические действия. Например, тип Boolean описан так:       | 
|Type                                                                       | 
|Boolean = (False, True);                                                   | 
|     Единственное его отличие от перечисляемых типов, определяемых         | 
|программистом, состоит в том, что значения типа Boolean можно выводить на  | 
|экран. Можете проверить, Ord(False)=0.                                     | 
|     Интересно, что переменная перечисляемого типа может быть счетчиком в  | 
|цикле "с параметром".                                                      | 
|Пример:                                                                    | 
|Program T1;                                                                | 
|Type                                                                       | 
|    Colors = (Black, Blue, Green, Cyan, Red, Magenta, Brown, Yellow,       | 
|White);                                                                    | 
|Var                                                                        | 
|    C1,C2 : Colors;                                                        | 
|Begin                                                                      | 
|C1:=Green;                                                                 | 
|C2:=Red;                                                                   | 
|Writeln(Ord(C1), Ord(Succ(C2)))                                            | 
|End.                                                                       | 
|     Во время выполнения на экране появятся числа "2" и "5", что           | 
|соответствует номерам значений Green и Magenta.                            | 
|     Следующий тип, который можно определить в программе - тип-диапазон.   | 
|     Здесь не нужно перечислять все значения этого типа, потому, что       | 
|возможными для него являются значения поддиапазона уже определенного до    | 
|него любого порядкового типа (стандартного или описанного ранее            | 
|перечисляемого типа). Достаточно лишь указать начальную и конечную величину| 
|отрезка порядкового типа. Единственное условие: начальное значение не      | 
|должно превышать конечное.                                                 | 
|     Формат описания отрезочного типа:                                     | 
|Type                                                                       | 
|    =..;                                             | 
|Примеры:                                                                   | 
|Type                                                                       | 
|Age=0..150; {Целое число в интервале от 0 до 150}                          | 
|Lat='A'.. 'Z'; {Заглавные буквы латинского алфавита}                       | 
|Month=(January, February, March, April, May, June, July, August, September,| 
|October, November, December);                                              | 
|Spring=March..May; {Весенние месяцы}                                       | 
|     Есть еще одна возможность определить новый тип, о существовании       | 
|которой можно было бы и догадаться.                                        | 
|Type                                                                       | 
|    =;            | 
|Пример:                                                                    | 
|Type                                                                       | 
|    Number=Byte;                                                           | 
|                                                                           | 
|Массивы                                                                    | 
|     До сих пор мы рассматривали переменные, которые имели только одно     | 
|значение, могли содержать в себе только одну величину определенного типа.  | 
|Исключением являлись лишь строковые переменные, которые представляют собой | 
|совокупность данных символьного типа, но и при этом мы говорили о строке,  | 
|как об отдельной величине.                                                 | 
|     Вы знаете, что компьютер предназначен в основном для облегчения работы| 
|человека с большими информационными объемами. Как же, используя только     | 
|переменные известных вам типов, сохранить в памяти и обработать данные,    | 
|содержащие десяток, сотню, тысячу чисел или, к примеру, строк? А ведь такие| 
|задачи встречаются в любой области знания. Конечно, можно завести столько  | 
|переменных, сколько данных, можно даже занести в них значения, но только   | 
|представьте, какой величины будет текст такой программы, сколько времени   | 
|потребуется для его составления, как много места для возможных ошибок?     | 
|Естественно, об этом задумывались и авторы языков программирования. Поэтому| 
|во всех существующих языках имеются типы переменных, отвечающие за хранение| 
|больших массивов данных. В языке Паскаль они так и называются: "массивы".  | 
|     Массивом будем называть упорядоченную последовательность данных одного| 
|типа, объединенных под одним именем. Кстати, под это определение подходит  | 
|множество объектов из реального мира: словарь (последовательность слов),   | 
|мультфильм (последовательность картинок) и т. д. Проще всего представить   | 
|себе массив в виде таблицы, где каждая величина находится в собственной    | 
|ячейке. Положение ячейки в таблице должно однозначно определяться набором  | 
|координат (индексов). Самой простой является линейная таблица, в которой   | 
|для точного указания на элемент данных достаточно знания только одного     | 
|числа (индекса). Мы с вами пока будем заниматься только линейными          | 
|массивами, так как более сложные структуры строятся на их основе.          | 
|     Описание типа линейного массива выглядит так:                         | 
|    Type     =Array [] Of ;    | 
|     В качестве индексов могут выступать переменные любых порядковых типов.| 
|При указании диапазона начальный индекс не должен превышать конечный. Тип  | 
|элементов массива может быть любым (стандартным или описанным ранее).      | 
|     Описать переменную-массив можно и сразу (без предварительного описания| 
|типа) в разделе описания переменных:                                       | 
|    Var      : Array [] Of ;                                                                | 
|     Примеры описания массивов:                                            | 
|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 
	
	
					
							 |