Реферат: Основы программирования на языке Паскаль

Как работать с книгой

Внимательнопрочитайте соответствующий раздел теории (одну главу), разберите все примеры,чтобы вам все было понятно, при этом, если у вас есть компьютер, наберитепрограммы и запустите их на выполнение. Убедитесь в правильности полученных результатов.Для того чтобы изучить действие того или иного оператора в программе илифрагмента программы, можно «удалить» фрагмент, заключив его вкомментарные скобки { фрагмент… }. можно, наоборот, добавить в программуоператоры writeln, readln для того, чтобы посмотреть промежуточныерезультаты. Экспериментируйте – это  поможет вам в усвоении материала.

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

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

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

Помните: "небоги горшки обжигают!"

Удачивам!

 

                                                           Автор.


1.Предварительные сведения

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

Программа на языке Паскаль состоит из «заголовка» и«тела» программы, называемым блоком. В «заголовке»программы даётся имя и перечисляются её параметры (если это необходимо). Блоксостоит из шести разделов, причем любой из них, кроме последнего, может бытьпустым (т.е. отсутствовать). В определении блока разделы должны следовать втаком порядке: описание меток, определение констант, определение типов, описаниепеременных, описание процедур и функций, операторы.

 

1.1. Алфавит

Для написания программ на языке Паскаль можно применять следующиесимволы: буквы латинского алфавита a b c d...z(прописные),a b c d...z (строчные), знак подчеркивания. Прописные и строчные буквывзаимозаменяемы (эквивалентны) и используются для более рельефного написания программ;

–   цифры  0 1 2 3 4 5 6 7 8 9;

–   специальные знаки: + – * / = <> [ ]., ( ):; ^ { } $ # @;

–   составные знаки :< = > =…( * * ) (… ).

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

 

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

В первом приближении решение задачи на ЭВМ сводится: к вводунекоторых исходных данных в память машины и обработке их по заданному алгоритму;получению и выдаче пользователю результатов решения задачи в виде чисел,текстов, графиков таблиц и т.п. Алгоритм является перечнем тех действий,которые должна выполнять ЭВМ для получения результата. Ввод данных можетпроизводиться с различных устройств: с клавиатуры, канала связи, сканера (вводтекстов и рисунков), манипулятора типа «мышь”, “джойстик» и т.д.

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

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

Порядок решения задач:

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

2. Разработка алгоритма решения задачи. Здесь возможноописание алгоритма в любой удобной форме: либо в виде словесного описания свключением формул, либо в виде блок-схем, что особенно наглядно и удобно. например,блок-схема алгоритма, исследующего квадратное уравнение ax2+bx+c=0,показана на рис. 2.1.

3. Запись алгоритма с помощью средств алгоритмического языкаПаскаль (написание программы).

4. Ввод программы в ЭВМ.

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

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

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


2.Простейшие программы

 

2.1. Оператор присваивания

 

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

Замечание 1. Тип значения выражения  и тип идентификатора должнысовпадать, иначе error — ошибка.


/>  

              

 


Замечание 2. При наличии хотя бы одной ошибки программа не выполняется.

Пример. Пусть имеются ячейки памяти с именами a, b, c; ячейки таковы, что в нихмогут быть помещены величины только целого типа. достигается это описанием:  Var a, d, c:  integer, где Var — начало раздела описания переменных, a,b, c — идентификаторы. Integer означает целый, т.е. в разделе Varидентификаторы (имена) переменных определены как целые.

Работа описания: встретив такое описание, ЭВМ выдаёт триячейки памяти с именами a, b, c, причем такие, чтобы тудамогли быть помещены целые числа. Запишем оператор присваивания:       

                                      a: = c+b;

Работа оператора: машина должна иметь описаниеидентификаторов a, b, c.

кроме того, как сказано выше, в правой части оператора стоятвеличины, которым уже присвоены начальные значения. В этом случае машина извлечетиз ячейки с её содержимое и из ячейки b содержимое, произведет операциюсложения и значение результата занесёт (присвоит) в ячейку a.

 

2.2. комментарии

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

 

2.3. Программа

Напишем программу вычисления a = c+b. Программаначинается с заголовка Program – имя программы; затем идут разделыописаний (до 5) и раздел операторов, который начинается словом Begin изаканчивается END. (end с точкой, точка – конец программы). Каждоеописание и оператор заканчиваются символом ';'

       Program Prim1;     {заголовок программы}

    Var  a,b,c:integer;    {раздел описания переменных, выделение}

                                  {ячеек памяти для хранения  целых величин}

 BEGIN                         {начало раздела операторов}

c:=547;   b:=42;   {занесение в ячейки c и b начальных значений}

         a:=c+b;             {вычисление значения и выдача на}

         writeln(a);        {экран (write — писать) значения a}

                        END.     {конец программы}.

Напоминаем, что тексты, заключённые в скобки {  }, являютсякомментариями, не являются частью программы и могут быть опущены, таким образом,программа для ЭВМ имеет следующий вид:

        Program Prim1;

     Var

          a,b,c:integer;

  BEGIN

          c:=547;   b:=42;

          a:=c+b;

          writeln(a);

          readln;

                         END.  

Программа записывается в виде строк. Максимальная длинастроки 255 символов, но не стоит делать строки длиннее строки экрана – 80символов, иначе строки будут «прятаться» за пределами окна экрана,хотя строки и можно просмотреть, передвигая «окно» (рис. 2.2).


/> /> /> /> /> /> <td/> /> />

«Хорошее» расположениестрок          «Плохое» расположение строк

рис. 2.2

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

 

2.4. Простейший ввод-вывод

В программе Prim1 мы задавали исходные данные спомощью оператора присваивания, что не всегда удобно, если одну и ту жепрограмму нужно просчитывать с различными исходными данными. Для присвоения начальныхзначений можно использовать оператор readln (идентификатор,идентификатор,..., идентификатор); например, readln (c,b). встретив такойоператор, машина остановится и будет ждать, пока пользователь не наберет наклавиатуре значение с, нажмет клавишу «пробел”, наберет значение bи нажмет клавишу ENTER (ввод).значения величин c и bотобразятся на экране и после нажатия клавиши ENTER занесутся в ячейкипамяти машины с именами с и b соответственно. тогда программа Prim1примет вид:

Program Prim1a;

Var  a,b, c: integer;

BEGIN readln  (c,b);

  a: =c+b;

writeln(a);      

  readln;

           END.

Замечание1. Напомним,что машине безразлично, строчные или прописные буквы одинаковых слов end,end и end (но не для вас).

Замечание 2. Удобно ставить Readln перед END, так какпосле выполнения программы машина выдаёт на экран окно текста программы, арезультат „прячется“ за этим окном и, чтобы его посмотреть,необходимо убрать окно с программой с помощью нажатия клавиш. Если перед ENDимеется Readln, то программа не завершит работу, пока вы не нажметеклавишу ENTER, т.е. в данном случае на экран будет выведено значение а.Вы посмотрите результат и нажмете ENTER для входа в редактор языкаПаскаль.

 

2.5. Арифметические выражения

Арифметическое выражение строится из объектов: арифметических(числовых) констант; идентификаторов переменных, описанных как числовые;функций, которые возвращают в результате их вычисления; арифметических значенийэтих объектов, соединённых между собой знаками арифметических операций икруглыми скобками. В качестве констант могут применяться арифметическиеконстанты, заданные в явном виде: 5; 5.35, -7.374 Е + 01 и т.п., а также именаконстант, определённые в разделе const.

В качестве переменных используются переменные, определённые вразделе Var как byte, integer, real, и их разновидности,например, longinteger, и т.д., если им уже присвоены начальные значения.

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

Основные стандартные функции Паскаля:

Обозначения:  I – целочисленный тип; B –байтовый тип; R – вещественный тип; IBR – целочисленный, илибайтовый, или вещественный типы.

ABS (IBR) – определение абсолютной величины аргумента типа  i,b,r.

ARCTAN (IBR) – вычисление угла (в радианах),тангенс которого равен IBR.

Cos(IBR), Sin(IBR).

Exp (IBR)       –  вычисление значения eIBR.

Ln (IBR)           – натуральный логарифмIBR.Sgr (IBR)         – возведение в квадрат IBR.

Sgrt (IBR)        – вычисление корня квадратногоиз IBR.

Возведение в степень выполняется по формуле ar= exp (r *ln(a)) для положительныхa либо организуется последовательное умножение на а r раз.Дляотрицательных а возможен только второй способ.

Арифметические операции: +, , * – умножить; / – разделить;mod нахождение остатка от деления: 11 mod 5, результат1; div– целочисленное деление (дробная часть отбрасывается) 11 div 5,  результат 2.Арифметические „и“ – аnd и „или“ – orпроизводят поразрядное булевское умножение или сложение целых значенийоперандов согласно таблицам:  

         A  аnd  B                                        A  or  B

     0  аnd  0   = 0                                  0  or  0   = 0

     1  аnd  0   = 0                                  1  or  0   = 1

     0  аnd 1    = 0                                  0  or  1   = 1

     1  аnd 1    = 1                                  1  or  1   = 1

Пример: a: = 12 ;     b: = 27.

Во внутреннем коде машины, в двоично-десятичной системе,цифры представляются в десятичной системе:

         0000      = ноль

         0001      = один

         0010      =  два

         0011      =  три

         0100      = четыре

         0101      = пять

         0110      = шесть

         0111      = семь

         1000      = восемь

         1001      = девять

Тогда 12 в десятичной  системе  эквивалентно 0001 0010 двоично-десятичной   системы. напомним, что в двоично-десятичной системе каждаядесятичная цифра представлена 4-значным двоичным кодом этой цифры. В этомслучае 27 — 0010 0111.

                     А аnd  B                              А  or  B

                    00010010                            0001 0010

                    00100111                            0010 0111                      

 результат: 0000 0010          результат: 0011 0111

Результат преобразуется в десятичную форму 2 и 37 соответственно.

ХOR, исключающее „или“, производит операциюсогласно таблице

  A xor B

  1  xor  1   =  0

  1  xor  0   =  0

  0  xor  1   =  1

  0  xor 0   =  0

Результат преобразуется в десятичную форму.

Циклический сдвиг:     k  shl  N  -  сдвиг числа к влево на Nпозиций,

k  shr  N -  сдвиг числак вправо на N позиций,

 k  и  N -  целые.

Пример:      2 shl 7 =  256


0000    0000    0000   0010

/>/>/>/>/>/>/>/>/>/> 0000    0001    0000    0000

/>                                                     0 единиц

/>                                                      0двоек

/>                                                     0 четверок

/>                                                     0 восьмерок

/>                                                     0 шестнадцать

/>                                                     0 тридцать два

/>/>                                                     0 шестьдесят четыре

/>                                                     0 сто двадцать восемь

                                                      1двести пятьдесят шесть

Пояснение: в любой позиционной системе счисления на первомместе справа в числе стоит количество оснований системы счисения в степени 0,на втором месте справа – количество оснований в степени 1, на третьем местесправа – количество оснований в степени 2 и т.д. так, для десятичной системы имеем:


/>/>/>      3  2  4

/>                             количество единиц   100 * 4 = 4

/>                             количество десятков 101 * 2 = 20 

/>                             количество  сотен     102 * 3 = 300

/>                                                               сложим = 324

Для двоичной системы:

    1  0  1  1  0  0 1    

/>/>/>/>/>/>/>/>                                         количество единиц                        20 * 1 = 1

/>                                         количество двоек                           21 * 0 = 0

/>                                         количество четверок                     22 * 0 = 0

/>                                          количествовосьмерок                   23 *1 = 8

/>                                         количество шестнадцаток             24 *1 = 16

/>                                         количество тридцать вторых        25 *1 = 0

/>                                          количествошестьдесят четверок 26 * 1 =64

/>сложим =89                                                                                                                                                                                                    

т.е. десятичное 89 имеетизображение 1011001 в двоичной системе.

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

1. Запрещено  последовательное  появление  знаков  двухопераций, т.е.

A + — B – неверно, A + (-B) – верно.

2. Порядок выполнения операций: /,,div, mod, and, or, shl,shr, –, +.                  Порядок может быть нарушен круглыми скобками,так как часть выражения, заключённая в круглые скобки, выполняется в первую очередь.

3. Если операции имеют одинаковый приоритет, то онивыполняются последовательно.

4. Унарная операция имеет самый низкий приоритет, поэтому  –A*b интерпретируется как  –(A *b).

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

6. Следует помнить, что операции / и * имеют одинаковый приоритет,например, 18/2*3=27, а не 3.чтобы было 3, необходимо записать 18/(2*3).

 

2.6. Описания переменных.

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

Данные в Паскале могут быть следующих типов: 

/>/>Данные

Скалярные                                                                      Структурированные

/> /> /> /> /> /> /> /> /> /> /> /> /> /> /> /> /> /> <td/> /> <td/> /> <td/> /> <td/> /> <td/> /> <td/> /> <td/> /> /> /> /> />

                                                                          массивы               записи

/>/>Стандартные                  Определённые

/>/>/>                                        пользователем                строки               файлы

/> /> /> /> /> /> <td/> /> />

целые    логические   интервальные                             множества                          

         вещественные              перечисляемые               указатели

байтовые   символьные

Каждому типу данных могутсоответствовать константы. Количество элементов констант (цифр, букв) сильнозависит от конкретной конфигурации машины. Однако можно сказать, что для целоготипа числа максимальное значение 32767, для вещественных, как минимум, – до 7цифр мантиссы, для строковых – 255 символов и т.д.

Константы байтового типа – целые числа в диапазоне 0 –255. Целые константы – набор цифр, возможно, со знаком ¢+¢ или ¢–¢. Вещественные константымогут записываться в двух формах  –  с фиксированной точкой: 57.34; 

-256.758 и с плавающей точкой: 5.734е+01 (эквивалент57.34) и -2.56758е+02

(эквивалент -256.758).

Логических (булевских) констант всего две: TRUE иFALSE. принято, что в машинном коде TRUE=1, FALSE=0. знаковые константыпредставляют все символы алфавита плюс символы кириллицы, но не для того, чтобысимвол стал константой, его нужно заключить в апострофы: ¢А¢, ¢1¢, ¢+¢, ¢?¢ и т.д. Константы могутхраниться в ячейках памяти, определенных какими-либо именами (идентификаторами).

Идентификатор – наборбукв и цифр, первая из них – всегда буква, например А, ALP1, B2, GAMMA. Идентификаторы могут быть длиной до255 символов, однако большинство компиляторов накладывает ограничение, т.е.длина имени не должна превышать восьми символов. Идентификатор в своем составеможет содержать знак ¢_¢ (подчерк).

Переменные могут бытьописаны в разделе описания переменных Var. разделов описания может бытьдо пяти, лучше их располагать в следующем порядке: Label, Const, Type, Var, functuonиprocedure.

Если данное будетизменяться (по величине) в процессе выполнения программы, то имя этого данногоописывается в разделе Varс соответствующим атрибутом:

Байтовый тип – byte;

Целый тип – integer;

Вещественный тип – real;

Булевский тип – boolean;

Символьный тип – char и т.д.

Пример:

Var 

     kn:integer;

    S,T,Z: char;

    a,b,c: real;

    L25,L3: boolean;

    FAZA: byte;

Вэтом случае все описанные идентификаторы можно применять в программе. Работаэтого раздела будет заключаться в том, что машина выделит две ячейки памяти сименами k и n.В ячейках могут храниться только целые числа: в ячейках с именами S,T,Z– по одному символу; в ячейках a,b,c– только величины типа вещественных чисел; в L25и L3 –величины trueи FALSE, а в ячейке с именем FAZA– только числа от 0 до 255. Если попытаться, например, в ячейку Sпоместить не символ, а число, то это приведет к ошибке, т.е. правильно S:=¢A¢;или S:= ¢$¢;или S:= ¢1¢;однако неверно S:= 1 (1 – числов отличие от ¢1¢ – символа). Если в процессевыполнения программы данное не меняется, то его можно описать в разделе»Описания констант":

Const

A=36.74;   B=true;

С=¢а¢;

Здесьтоже выделяются ячейки памяти с именами А, В, С для хранения заданных величин,которые не подлежат изменению.

Допустимоописание констант-выражений:

Const

М= (32.5 + 0.64) / 3.14;

Крометого, машина «знает», чему равны константы е и π.

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

/>,гдевеличины R, а, S, L, K вводятся с клавиатуры.

Пустьk, l — целые числа, остальные – вещественные.

Program   Prim2,

    Var    k,L:integer;

 Y,R,a,S: real;                   {здесь для хранения результата y тоже}

                                                            {нужна ячейка памяти}

Beginwriteln ('введите це',        {выдача на экран текста, указанного в}

'лоеk,L, действительные'     {кавычках; обратите внимание на прави-}

'R, а,S');                            {ло переноса текста в операторе writeln:}

{еслинужно перенести текст, то ставится}        {закрывающий апостроф, затем запятая,}

{новаястрока вновь начинается с апострофа}

readln(k,L,R,a,S);

Y:= 1-l(l+sqr(r*a/k))/(exp(2)/sqr(s)*sqr(l+r*a/l));

writeln(Y);readln;

END.

Тоже самое будет, если записать программу:

Program Prim2a;

  Var   k,L: integer, R,a,S:real;

Begin   writeln ('введитецелыеk,L'); readln (k,L);

                writeln ('введитевещественныеr,S,a'); readln (R,S,a);

                writeln(l-l/(l+sqr(r*a/k))/(exp(2)/sqr(s)*sqr(l+r*a/l)),

                readln;     END.

Последнийоператор writeln вначале вычислит арифметическое выражение, а затем выведет наэкран его значение в виде числа. Если мы хотим, чтобы результат был в виде'результат Y = число', тонеобходимо последний writeln написать в следующем виде:

writeln ('результат Y=',1-l/(l+sqr(r*a/k))/exp(2)/sqr(s)*sqr(l+r*a/l));тогда машина вначале выведет текст, взятый в апостроф, т.е. «результат Yi»,а затем его значение.

 

2.7. Раздел описания типов

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

Пустьнам нужна переменная с именем season (сезон года). она может приниматьзначения winter (зима), spring (весна), summer (лето), autumn(осень), другие значения она принимать не может. Тогда нужно сделать следующееописание:

Varseason:(winter,spring,summer,autumn).

Здесьтип season задан перечислением всех констант, которые могут бытьзанесены в ячейку памяти season. Попытка занести в ячейку seasonлюбое другое значение приведет к ошибке – «несоответствие типа».

Еслипеременных данного типа будет несколько, удобнее и нагляднее вначале определитьтип в разделе Туре (описание типа), а затем в разделе Varсослаться на этот тип, и машина в Var выделит конкретные ячейки памятидля хранения данных указанного типа.

Например,необходимо определить, что Gi,G2,G3,G4 будут ячейкамипамяти, в которых могут храниться наименования газов Со,О,N,F, а в ячейках памяти Metall1, Metall2, Metall3 –наименования металлов , Со, Na, Cu, Zn,тогда можно применить описание:

VAR GI, G2, G3, G4: (CO,O,N,F);

      Metall1, Metall2, Metall3: (Fe,Co,Na,Cu,Zn).

Можноиспользовать и другое, более наглядное описание. вначале определить тип Gaz,Met, а затем на них сослаться:

Туре   Gaz=(Co,О, N, F);

        Met = (Fе,Со,Na, Cu, Zn);

Var      GI, G2, G3, G4: GAZ;

       Metall1, Metall2,Metall3,Met;

Особенноудобно применение раздела Туре, если он находится во внешнем блоке, ассылки на него идут во внутренних блоках (см. раздел «Блоки»). Тогдазначительно экономится память, поскольку она может быть практически одной и тойже в разных блоках.

Приописании переменных перечисляемого типа данные внутри скобок являютсяконстантами, которые может принимать описываемая переменная. Над данными такоготипа допустимо выполнять операции отношения и логические операции (см. далее).Например, для приведенного выше описания данного season будет истиннымвысказывание: "winter < spring".

Приработе с данными перечисляемого типа можно применять стандартные функции Succ,Рred, Ord.

Succ(аргумент) возвращает значение, следующее за элементом, указанным как аргумент.Если следующего элемента нет (закончились), то это приводит к программномупрерыванию (ошибке).

Рred(аргумент) возвращает предыдущее значение из перечня констант, из которыхсостоит данный тип.

Ord(аргумент) возвращает порядковый номер аргумента в списке констант, перечисленныхв описании в виде целого числа. Элементы пронумерованы в порядке 0,1,2,...,т.е. первый элемент имеет номер 0.

Пример:

Туреmonth = ('jan','fab','mar','apr','may','jun','jul','aug','sep','ocf','nov','dec');

      Var     a,b,c,d,c,mes: month; f,h,g: integer;

Begin            mes: =jul;

a:= Pred (mes);             {вa находится'jun'}

b:= Succ (mes);             {вb находится'aug'}

с:= Pred(pred(mes));    {в с находится 'mау'}

d:= Succ(succ(mes));   {в dнаходится 'sep'}

e:= Succ (pred(mes));    {венаходится'jul'}

f:= Ord(mes);              {в fнаходится 6}

h:= Ord (pred(mes));     {вh находится5}

g:= Ord (succ(mes));     {вg находится7}

                                                                                                          END

Интервальныйтип задается диапазоном изменения констант внутри какого-либо уже имеющегосяперечисляемого или стандартного типа, кроме вещественного (integer, byte,booban, char). Значение первой константы должно быть меньше значения второйконстанты диапазона.

Туре

Dni = 1...31;

 Litera = 'a',...,'z',

Var    Rabdni,bolndni, vuhod: dni; {могутприниматьзначения1-31}

  im,ident:litera;{могут принимать значения 'A'-'Z'}

Выходза пределы диапазона вызывает программное прерывание.

Допускаетсязадание диапазона именами констант:

Const min = 1; max = 31;

ТуреDni = min…max;

Var rabdni,boldni,vuhoddni:dni;

Дляинтервального типа также возможно применять функции Succ,Pred, Ord.

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

 

3.1. Общие положения

Досих пор мы рассматривали линейные программы, алгоритм которых можно былопредставить в виде блок-схемы (рис. 3.1)

/>                                       

Возможныслучаи, когда программа ветвится в зависимости от какого-либо условия (см. рис.3.2). Ветвление может быть двух направлений: по принципу условие верно – идтипо одной ветви, условие ложно – по другой. В этом случае применяется оператор if.возможно ветвление сразу нескольких направлений: если k=l – идти по однойветви, если k=2 – по другой, k=3 – по третьей и т.д. в этом случае удобнееприменять оператор Case.

/>


               

3.2.Оператор goto, раздел описания меток

Последовательноевыполнение операторов в программе может быть нарушено оператором перехода.Общий вид оператора: goto метка; где метка – буква, либо цифра, либонабор букв и цифр, из которых первая – всегда буква, Например, М1, LI, NK.Метка, стоящая после goto, указывает, куда нужно пойти. Достигается этотем, что если в программе находится оператор goto метка; то в этой жепрограмме обязательно имеется какой-либо оператор вида метка: оператор;который считается помеченным, и машина, встретив goto метка; не будетвыполнять оператор, записанный после оператора goto метка; а перейдет квыполнению оператора метка: оператор;

/>Иллюстрация:    

 а:= b+с;

с:= sgrt(a+exp(b));

goto M1;

z: = x+y;

writeln (z);

M1:S:= P;

/> 


Вслучае, если бы не было оператора goto М1; все операторы выполнялись быпоследовательно один за другим. здесь же после оператора с: =... стоит gotoМ1; следовательно, машина не будет выполнять z:=... и writeln...,а сразу после с: =... перейдет к выполнению оператора М: S:= Р;

Метки,применяемые в программе, должны быть описаны в разделе описания меток, которыйжелательно ставить первым среди описаний. Выглядит раздел так: Label М1, М2,L, NK; т.е. после слова Label перечисляются через запятую все метки,которые будут применяться в данном блоке (программе). Заканчивается описание символом';'.

Пример:составить программу, вычисляющую значения функции cos х, где начальное х= 0, следующее х = 0.01 и т.д.

         Program Prim3;      Label M;      Var      x:real;   BEGIN    x:=0;         M: writeln('x=',x,'cos x =',cos(x));            x:=x+0.01;

           gotoM;readln;     END.

Программабудет работать следующим образом: х присвоится значение; writelnвыведет на экран текст, который указан в первых кавычках х =, далееизвлечет из ячейки х значение и выведет его на экран; затем снова выведеттекст cos х =, затем вычислит значение cos х и выдаст его наэкран, т.е. машина выведет первую строку в виде

x= 0.0000000000Е + 00 cos х = 9.9999999999Е — 01.

Послеэтого возьмется то х, которое было извлечено из ячейки памяти х(прежнее значение х), т.е. 0.0, к нему прибавляется величина 0.01и результат снова занесется в ячейку памяти х так, что в х будет 0.01,после этого оператор goto m; передаст управление оператору, помеченномуметкой м, т.е. оператору writeln, и машина выдаст новую строку:

x= 1.0000000000Е — 02 cos х = 9.9995000041Е — 01;

–выполнит оператор

х:=x + 0.01, получит х = 0.02;

–выведет строку

x= 2.0000000000Е — 02 cos х = 9.9980000666Е – 01;

–сделает х = 0.03 и т.д., до бесконечности, так как в данном алгоритмеокончание работы не предусмотрено. Для завершения работы следует применить операторif.


3.3.Оператор if

 

Общийвид: If булевское выражение then оператор else оператор;

Работаоператора: вначале вычисляется булевское выражение, значение которого вконечном итоге может быть только TRUE или FALSE. Если булевское выражение TRUE,то выполняется оператор, следующий за словом then, а затем происходитпереход к оператору, следующему за if. Если булевское выражение false,то выполняется оператор, следующий за словом else, затем происходитпереход к оператору, следующему за оператором if.

Замечание:после оператора, следующего за then, перед else символ ';'не ставится, так как оператор if еще здесь не закончен, а ';'ставится после окончания оператора. Возможно применение сокращенного оператора if:

Ifбулевское выражение then оператор;

Здесь,если булевское выражение true, выполняется оператор, следующий за словомthen, и происходит переход к оператору, следующему за оператором if.Если булевское выражение false, то оператор if игнорируется (вообщене выполняется), а выполняется оператор, следующий за if.

Переделаем«бесконечную» программу п. 3.2. в такую, которая остановится тогда,когда х станет равным 0.1.

         Program Prim4;       Label M;      Var      x:real;

  BEGIN    x:=0;

        M: writeln('x=',x,'  cos x = ',cos(x));

           x:=x+0.01;

           if x<=0.1 then goto M; readln;

     END.

Программавыдает результаты вычислений cos(x) для х = 0.01, 0.02, 0.03 ит.д., до 0.01.

Впоследней программе булевское выражение х < = 0.1. Какие бываютбулевские выражения? Вообще говоря, булевское выражение после вычисления всегдаистинно или ложно, т.е. TRUE или FALSE. Действительно, выражение х < =0.1 может быть истинно, если х меньше или равно 0.1, и ложно– в противном случае. Вообще булевское выражение может строиться из булевскихконстант TRUE и FALSE; переменных булевского типа (в которых могут хранитьсяTRUE или FALSE); обращений к функциям, которые возвращают TRUE или FALSE иотношений, соединенных между собой булевскими операциями и круглыми скобками.

Здесьследует расшифровать, что такое отношения и булевские операции. Примеромотношения может быть приведенное выше х < = 0.01, т.е. в общем случаеотношение – это два арифметических выражения, соединенных между собойоперациями отношения. Операции отношения: = (равно), < >  (неравно), >(больше), > = (больше или равно), < (меньше), < = (меньше или равно).

Примеротношений:               а + b < = sin(c)

exp(p) > (cos(i) — a)/sgr(b).

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

Логическиеоперации – это нам уже известные. Напомним, как они работают: or (или), and(и).

Имеетсяописание Var A,B: boobean;

Or– логическое сложение, читается как «или». Результат операций –истина, если или А, или В – истина, и ложь, если А и B ложны.

Например:                А                          В                    А ог В

true                  true                    true

true                  false                   true

false                 true                    true

false                 false                   false

Замечание:данная операция аналогична арифметической OR, если TRUE заменить 1, а FALSE –0.

АND- логическое умножение, читается «и». Результат операции – истинатолько тогда, когда и А, и В – истина, в остальных случаях результат – ложь.

 А                        В                    A and B

                             true                     true                   true

          true                       false                  false

          false                      true                    false

          false                      false                  false

Крометого, удобно применять однокомпонентную операцию Not, которая вводитсяследующим образом: если А есть TRUE, то Not А есть FALSE и если А есть FALSE,то Not А есть TRUE.

Спомощью этих операций можно построить условия любой сложности. Например, пустьнеобходимо решить задачу:

 

/> 

Напишемпрограмму:

         Program Prim5;

      Var     a,x:real;

  BEGIN

            writeln('введитеа, х'); readln(a,x);

         if (a>0) and (x>0) and (x<=0.5) then

            writeln('z=',a*sqr(x)/sin(x)) else

         if (a>0) and (x>=0.5) and (x<3) then

            writeln('z=',exp(x)) else

         if (a<=0) or (x<=0) then

            writeln('z=',sqrt(a)*sqrt(x)/sin(x)) else

            writeln('z=0');

                          readln;   END.

Замечание:в последнем примере мы видим, что операторы if могут быть вложены друг вдруга. Вкладывать их можно неограниченное количество раз, причем новый ifможет начинаться как после слова then, так и после слова else.

Ещеодин пример: пусть дана область (заштрихованная на рис. 3.3). Мы вводим склавиатуры координаты точки. Машина должна определить, принадлежит ли даннаяточка этой области или нет.

Разобьемобласть рис. 3.3 на несколько простых:

1.Внутренняя часть сектора, ограниченного отрицательной частью оси OX, положительнойOY и окружностью с центром в начале координат и радиусом, равным 2.

/> /> /> /> /> /> /> /> <td/>

Рис. 3.3

 

2.Прямоугольник, ограниченный осями OX, OY и прямыми x=4, y=2.

3.Прямоугольник, ограниченный осями OX, ОУ и прямыми x=-2, y=-4.

4.Внутренняя часть сектора, ограниченного положительной частью оси OX, отрицательнойOY и окружностью с центром в начале координат и радиусом, равным 3.

5.Внутренняя часть квадрата, ограниченного прямыми линиями x=2, x=3, y=-3, y=-4.

6.Область, лежащая внутри окружности с центром x=5, y=-3 и

радиусом=1,5.

Программа:

          Program Prim6;

      Label N,K,L;

      Var x,y:real; f:char;

 BEGIN  N: writeln('введите координаты точки');

        readln(x);  writeln('x=',x);

        readln(y);  writeln('y=',y);

  if (x<=0) and (y>=0) and (sqr(x)+sqr(y)<=4)              {1-яобласть}

     or (x>=0) and (x<4) and (y>=0) and (y<=2)             {2- яобласть}

     or (x<=0) and (x>=-2) and (y<=0) and (y>=-4)        {3- яобласть}

     or (x>=0) and (y<=0) and (sqr(x)+sqr(y)<=9)         {4- яобласть}

     or (x>=2) and (x<=3) and (y<=-3) and (y>=-4)       {5- яобласть}

     or (sqr(x-5)+sqr(y+3)<=2.25)                                   {6-я область}

 thenwriteln('точка с координатами х=',x,' y=',y, 'принадлежит области')

elsewriteln('точка с координатами х=',x,' y=',y, 'не принадлежит оласти);

 L: writeln('будем ли ещё вводить координаты точки?, Y,N');readln(f);

    if (f='Y') or (f='y') then goto N else

    if (f='N') or (f='n') then goto K else

    writeln('неправильно нажали клавишу, попробуйте ещёраз'); goto L;

    K:readln;End.

/>Замечание:для того, чтобы построить область, необходим здравый смысл и элементарныезнания аналитической геометрии. Так, х>=0 определяет область (рис.3.4)

x>=0 and x<=4  определяет полосу (рис. 3.5)

/>


Вспомнив, что уравнениеокружности с центром в начале координат x2+y2=r2, имеем  x2+y2£4 (рис. 3.6),

/>


x £0 является полуплоскостью (рис. 3.7),

/>


y ³0 определяет полуплоскость (рис. 3.8),

/>


x £0 and y ³0 есть квадрант (рис. 3.9)

/>


и, наконец,

x £0 and y ³0 and sqr(x)+sqr(y)£4 есть сегмент (рис. 3.10)

/>


3.4.Оператор case (оператор выбора)

Общийвид:

Caseвыражение — селектор of

Списокконстант выбора 1: оператор 1;

Списокконстант выбора 2: оператор 2;

–– – – – – – – – – – – – – – – – – – – – – – – – –

Списокконстант выбора n оператор n;

elseоператор end;

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

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

Работаоператора. вначале вычисляется выражение-селектор, затем полученное значениесравнивается с константами выбора, и, если значение выражения-селектора совпадаетс какой-либо константой выбора, то выполняется оператор, стоящий после спискаконстант, в котором есть константа, совпадающая со значениемвыражения-селектора. если значение выражения-селектора не совпадает ни с однойиз констант выбора, то выполняется оператор, следующий за else. Elseможет в Case отсутствовать, тогда в случае несовпадения константоператор Case игнорируется.

Примеры:

1.Селектор целого типа, список констант представлены перечнем констант:

/>

Program Prim7;Var i,z:integer;BEGIN writeln('введитецелоеi'); readln(i);

  Case i of

  1,2,5:    writeln('i=',i,'  z=',i+10);

  12,16:    writeln('i=',i,'  z=',i+100);

  31,35,46: writeln('i=',i,'  z=',i+1000);

  elsewriteln('неправильнозадано i');end;

           readlnEND.

2.Селектор целого типа – список констант представлен диапазоном.

вводитсяцелое i, определить, находится ли оно в диапазоне 1-10 или 11-100, или101-1000, либо вне этих диапазонов.

ProgramPrim8;Var i:integer;BEGIN  writeln('введитецелоеi'); readln(i);   Case i of

  1..10:      writeln(' число в диапазоне1-10');

  11..100:    writeln(' число в диапазоне 11-100');

  101..1000:  writeln(' число в диапазоне 101-1000');

  else writeln(' числовнедиапазона1-1000'); end;

           readln;  END.

3.Селектор целого типа, список констант представлены перечнем констант и диапазоном:

/>

           Program Prim9;       Var i:integer;   x,m,a,b,c,d:real;  BEGIN    writeln('введитезначениеi'); readln(i);           writeln('введитезначения x,m,a,b,c,d');

          readln(x,m,a,b,c,d);

      Case i of

 1,2,4,8,11..20,24,28,30:writeln('y=',(x+1)/(sqr(x)+2)-ln(m)+2*a/b);

 31,45..55:              writeln('y=',(sqr(a)+m)/sqrt(b+m)-3*a*b/c+d);

 58,60,63..76,78,93,100: writeln('y=',sqr(x)-a*x+sqr(sin(a*x)-exp(x))

                                        /(1-ln(sqr(x)-exp(х/2))));

  elsewriteln('неправильнозадано i');end;

           readlnEND.

4.Селектор знакового типа:

           Program Prim10;       Var name:char;

 BEGIN    writeln('введитешифр');readln(name);

          Casenameof

 'S','s':writeln('факультет самолето- и вертолетостроения');

 'D','d':writeln('факультет авиадвигателестороения');

 'Y','y':writeln(' факультет систем управления');

 'L','l':writeln(' факультет летательных аппаратов');

 'R','r':writeln(' факультет радиотехнический ');

 'M','m':writeln(' факультет инженерно — менеджерский'); 'Z','z': writeln(' факультетзаочного обучения');

    else     writeln('введенный шифр не соответствует ни одному ',

                             'изфакультетов ХАИ'); end;            readln;  END.    5. Селектор перечисляемого типа:

             Program Prim11;     Var        season:(winter,spring,summer,autumn);       rez:integer;BEGIN   season:=spring;        Writeln('результатord(season)=',ord(season));           case season of           winter: writeln('winter');

          spring:  writeln('spring');

          summer:  writeln('summer');

          autumn:  writeln('autumn');

     end;   readln;

 END.


4.Циклические программы

Наиболеечасто в практике программирования встречаются циклические программы. Вциклических программах какой-либо алгоритм повторяется многократно, при этомодин из параметров изменяется. Например, описанная в п. 3.3 программа Рrim4 является классическим примером циклического алгоритма. Операторов цикла вПаскале три: for, repeat, while.

 

4.1. Оператор for

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

for– параметр цикла: = начальное значение to, конечное значение do{заголовок}; оператор; {тело цикла}. Этот оператор применяется, если начальноезначение < конечного значения;

for– параметр цикла:=начальное значение downto, конечное значение do;оператор; применяется, если начальное значение > конечного значения.

Пример:найти сумму квадратов целых чисел от 8 до 1.24.

         Program Prim12;     Var          i,s:integer;    BEGIN   s:=0;           for i:= 8 to 124 do            s:=s+sqr(i);             writeln('s=',s);              readln;

                     END.

Работапрограммы. В разделе Var выделяется ячейка памяти с именемi и s для хранения величин. Поскольку в S мы должны накапливать сумму, товначале занесем в S ноль. Затем заголовок цикла присваивает i=8. далее выполняетсятело цикла: извлекается содержимое ячейки S (а там у нас 0) и к этомусодержимому прибавляется sgr(i), т.е. i2=82. Результатприсваивается ячейке S, т.е. в S теперь 82.

Проверяется,не стал ли параметр цикла больше конечного значения параметра 128. Это непроизошло, поэтому i присваивается следующее значение равное 9 и вновьвыполняется тело цикла, т.е. S:=82+92. Можно сказать так:S присвоить тому S, которое было раньше, + следующее i2. Так какцикл еще не закончился, то i станет равным 10, а S присвоится тому S, котороебыло раньше, т.е. 82+92, и к нему прибавится еще текущееi2, т.е. 102. Этот процесс повторяется до тех пор, покапараметр цикла не станет равным 124. Тогда в последний раз 1242прибавляется к накапливаемой сумме.

Итак: выполнение цикла         значения i                  значения S

 1                                8                                         82

 2                                9                             82+92

 3                               10                          82+92+102

–– – – – – – – – – – – – – – – – – – – – – – – – – – – – –

 116                          117                  82+92+102+…+1232

 117                            124              82+92+102+…+1232+1242

Приi=125 происходит выход из цикла и переход к оператору writeln ('S=' ,S);

Эта,казалось бы, правильно написанная программа дает результат        S=-12250. Какможет получиться отрицательный результат при суммировании квадратов – заведомоположительных чисел? Такой результат мы получаем путем суммирования и занесениярезультатов в ячейку S типа integer, а в integer могут бытьпомещены числа в диапазоне -32768 +32767, поэтому после переполнения ячейкипамяти в знаковый разряд переносится 1, которая интерпретируется машиной как'-'. Чтобы этого избежать, можно описать S как longint.Тогда результат работы программы будет правильный и равен 643110.

         ProgramPrim12a;    Var          i,s:longint;

  BEGIN   s:=0;

          for i:= 8 to 124 do

             s:=s+sqr(i);

            writeln('s=',s);

             readln;                END.

Можнотакже описать S как real.          ProgramPrim12b;     Var           i:integer;  s:real;

  BEGIN   s:=0;

          for i:= 8 to 124 do

             s:=s+sqr(i);

            writeln('s=',s);

             readln;

               END.

Результатработы этой программы будет равен 6.4311000000E+05, что то же самое, что и643110, если считать, что запись 6.4311000000E+05 равносильна математическойзаписи 6,4311*10+5.

Правилаприменения оператора цикла for

1.Телоцикла — всегда один оператор. Если нужно, чтобы тело цикла состояло из несколькихоператоров, то их объединяют в один с помощью операторных скобок begin, end.

         for i:=l to n do

            Begin      S:=S+sin(x)/cos(x);

                       x=x+0.01;

                       writeln('S=' ,S)

       end.

Операторы,взятые в операторные скобки begin, end, считаются одним составным оператором.

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

3.В теле цикла параметр цикла не должен изменяться.

4.Нельзя с помощью оператора перехода goto войти в тело цикла, минуя заголовок.

5.Выйти из тела цикла в программу можно по if..goto,не дожидаясь полного перебора параметров цикла.

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

Применяемздесь в качестве параметра цикла символьную переменную, в качестве начальногозначения параметра – константу 'A', конечного – 'Z'.

         Program Prim13;

    Var

        i:char;

  BEGIN

          for i:='a' to 'z' do

            write(' ',i);

             readln;      END.

Пример:вычислить значение определенного интеграла на участке a,b для функции cos х,т.е. определить площадь, заштрихованную на рис. 4.1.


/>


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

/>


ProgramPrim14;

    Var i,n:integer;   a,b,x,h,s:real;

BEGIN writeln(' введите к-во точек разбиения nи величины а, b');

      readln(n,a,b);

      h:=(b-a)/n; s:=0; x:=a;

    for i:=1 to n do

  Begin   s:=s+(abs(cos(x))+abs(cos(x+h)))/2*h;

           x:=x+h; end;

      writeln('s=',s);

                  readln;         END.

Замечание:при вычислении S (так как функция пересекает ось OX) часть площадей может иметьотрицательное значение, поэтому мы берем abs(f(x)).

Усложнимзадачу: пусть нужно найти площадь криволинейной трапеции (интеграл), гдефункция от точки а до b sin(x), а после b до с cos(x).

        Program Prim15;

    Var i,n:integer;   a,b,c,x,h,s,fxpred,fxposl:real;

BEGIN writeln('введите к-во точек разбиения nи величины а, b, c');

      readln(n,a,b,c);

      h:=(c-a)/n; s:=0; x:=a;

    for i:=1 to n do

  Begin

  { определимся, по какой из функций считать стороны трапеций }

  if (x>=a) and (x<=b) then fxpred:=abs(sin(x)) else

        fxpred:=abs(cos(x));

  if (x+h>=a) and (x+h<=b) then fxposl:= abs(sin(x+h)) else

        fxposl:=abs(cos(x+h));

        s:=s+(fxpred+fxposl)/2*h;

        x:=x+h; end;

      writeln('s=',s);

                   readln;        END.

Впоследних двух программах мы заменяем площадь криволинейной трапеции (интеграл)суммой трапеций. При этом нам неизвестно, какую ошибку мы допустим; знаем, чточем больше точек разбиения, тем точнее будет результат. Поставим задачу: совершенноточно знать, что мы посчитаем интеграл с точностью не менее заданной, например,что разность между площадью криволинейной трапеции и суммой прямоугольных трапецийбудет не больше Е = 0.01. Для этого нам нужно посчитать результат для количестваточек, например 10, затем – 100. Сравнить величины площадей, и, если ихразность будет меньше Е, то можно с уверенностью сказать, что площадь дляразбиения на 100 интервалов будет найдена с точностью не менее Е. Если разностьмежду расчетами на 10 и 100 интервалов больше Е, то следует разбить областьинтегрирования на 1000 интервалов и сравнить сумму для 100 интервалов с суммойдля 1000 интервалов, и если их разница будет меньше Е, то за результат принятьплощадь, посчитанную для 1000 разбиений и т.д. рано или поздно мы получимискомый результат. Сравнения сумм площадей трапеций будем производить с помощьюоператора if.

Пустьфункция будет cos(x). Напишемпрограмму:

    Program Prim16;

    Label NAH,KON;

    Var i,n:integer;   a,b,x,h,spred,spos,e:real;

BEGIN writeln('введите точность е и границы a, b');

      readln(e,a,b);    spred:=9.9e+10; h:=0;n:=10;

  NAH:  spos:=0;  h:=(b-a)/n;  x:=a;

        for i:=1 to n do

   Begin spos:=spos+(abs(cos(x))+abs(cos(x+h)))/2*h;

        x:=x+h;  end;

    if abs(spos-spred)<=e then Begin

       writeln('s=',spos,'  n=',n); goto KON; end

       else spred:=spos; n:=n*10; x:=a; goto nah;

  KONreadlnEND.

Работапрограммы: for i: = i to n do, в первый раз оператор

Spоs:= spos+(abs(cos(x))+abs(cos(x+h)))/2*h

посчитаетзначение интеграла для 10 точек разбиения. Затем if сравнит полученноезначение spos с 9.9Е+10. Конечно,разница между этими величинами не будет меньше е, тогда мы забудем число9.9Е+10, так как присвоим spred: = spоs, чтобы при следующем выполнении ifсравнивать предыдущее и последующее значения интеграла. После этого увеличимколичество точек разбиения n:= n*10 и вернемся на начало вычисления spos,т.е. интеграла для 100 интервалов goto nach. После нового вычисления sposсравним 100 интервалов для 10 интервалов spred. Если разность между нимине меньше Е, то забудем значение s для 10 интервалов и занесем в spredзначение для 100 интервалов. Затем вычислим значение интеграла для разбиения1000 и результат занесем в spos, сравним spred и  spos ит.д.

 

4.2. Оператор repeat.Общий вид

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

repeat

оператор;

оператор;

 – – – – – – – –

  оператор until булевское выражение;

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

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

Замечания:1.Тело оператора repeat выполняется по меньшей мере один раз. Оператор repeatеще называют циклом с послеусловием.

2.Перед until ';' не ставится.

Пример:найти сумму четных чисел в интервале от 0 до 100.

        Program Prim17;

    Var i,s:integer;

 BEGIN   i:=0;    s:=0;

    repeat

    i:=i+2; s:=s+i

     until i>100;

      writeln('s=',s);

       readln;   END.

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

/>

ПустьU = 220, R = 100, L = 0.57, С = 3.2*10-3, Fначальное=10;F будем менять с шагом 0.5. Печататьвсе результаты. Результаты, когда i>3, нас не интересуют.

        ProgramPrim18;

   Var i,r,f,l,c,u:real;

 BEGIN   writeln(' введите значения u r l c');

         readln(u,r,l,c);

       f:=50;

   repeat i:=u/sqrt(sqr(r)+sqr(2*pi*f*l-1/(2*pi*f*c)));

          f:=f-1;

          writeln('f=',f,'  i=',i)

          until i>3;

                    readln;  END.

 

4.3. Оператор While

ОператорWhile цикла с предусловием.

While– булевскоевыражение; do – тело цикла.

Работаоператора. Вначале вычисляется булевское выражение, и если оно истинно, товыполняется тело цикла; если оно ложно, то происходит выход из цикла.

Телоцикла – один оператор, как правило, составной. Мы должны позаботиться о том,чтобы булевское выражение в теле цикла на каком-то этапе стало ложным, иначецикл никогда не закончится. Цикл можно сделать умышленно бесконечным, написав: whiletrue do оператор;

Мыбудем применять эту конфигурацию при написании программ обработки файлов.

Пример:найти сумму четных чисел в интервале от 0 до 100.

        Program Prim19;

   Var i,s:integer;

 BEGIN   i:=0; s:=0;

   while i<100 do

      Begin  i:=i+2;   s:=s+i; end;

          writeln('s=',s);

              readln;  END.

Пример:в цепи переменного тока найти ток в зависимости от его частоты.

/>

        Program Prim20;

   Var i,r,f,l,c,u:real;

 BEGIN   writeln('введите значения u,r,l,c');

         readln(u,r,l,c);

       f:=50;

   while i<3 do

       Begin   i:=u/sqrt(sqr(r)+sqr(2*pi*f*l-1/(2*pi*f*c)));

               f:=f-1;

               writeln('f=',f,'  i=',i); end;

               writeln('i>3, i=',i);

                    readln;  END.

 

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

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

         Program Prim21;

    Var

        i,j:integer;

  BEGIN

          for i:=1 to 5 do

     Begin       writeln;

          for j:=20 to 23 do

            write('i=',i,' j=',j);

     end;

             readln;      END.

Дляциклаfor i:=1 to 5 do теломциклаявляется

beginfor j:=20 to 23 do

write(' i= ', i, ' ,  j = ', j);

 writeln;    

 end;

Назовемэтот цикл внешним. Кроме того, имеется внутренний цикл

forj:= 20 to23 doстелом write('i= ', i, j=', j);

Работапрограммы. Вначале машина встречает внешний цикл и начинает его выполнять:присваивает i=l, затем переходит к его телу, а здесь встречает внутренний цикли присваивает j значение 20, после чего выполняет тело внутреннего цикла, т.е.выводит на экран i=l, j=20. Так как внутренний цикл еще не окончен, то машинапродолжает его выполнять, т.е. присваивает j значение 21 и добавляет к уже выведеннойстроке i=l, j=21.

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

i=1, j=20 i= 1, j=21.

Машинапродолжит выполнение внутреннего цикла, и, когда он закончится (выполнится дляj = 20.21.22.23), на экране будет строка

i= 1 j = 20 i =l  j = 21 i = 1  j = 22  i = 1  j = 23.

Внутреннийцикл закончится, однако тело внешнего цикла еще не закончилось, поэтомувыполняется оператор writeln, который переводит курсор на новую строку.После этого тело внешнего цикла закончится, но сам цикл отработал только для i= 1. Поэтому внешний цикл продолжит работу, присвоив i: =2 и вновь начаввыполнение своего тела. Встретив внутренний цикл j:=1, на экран с новой строкивыведется: i=2, j=20, затем j:=2 и к этой строке добавится i=2, j=21 и т.д.,пока не закончится внутренний цикл.

Такимобразом, внешний цикл, изменяя i от 1 до 5, заставит каждый раз выполнятьсяполностью внутренний цикл, и в результате работы программы на экране появится:

i=l,j=20      i=1, j=21     i=1, j=22     i=1, j=23

i=2,j=20     i=2, j=21     i=2, j=22     i=2, j=23

i=3,j=20     i=3, j=21     i=3, j=22     i=3, j=23

i=4,j=20     i=4, j=21     i=4, j=22     i=4, j=23

i=5,j=20     i=5, j=21     i=5, j=22     i=5, j=23

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

for i:=l to 100 do

  for j:=l to 100 do

    for k:=l to 100 do

   writeln (i, j, k);

даетстолбик цифр:

111

112

113

114

–– – – –

121

122

123

124

–– – – –

211

212

213

–– – – –

 100100100,

чтосоставляет 1000000 строчек.

Пример:найти rez = f (х1) + f (х2 )+… .+f (x6),

где/>

f(x)считать с точностью не менее e=0.01;

х1=0.1,затем xn=xn-l+0.2, пока х не станет равным 1.1.

Намнужно вычислить rez. Поскольку это будет сумма, то вначале положим rez=0, затемвычислим f(х1) с нужной точностью и добавим к rez, и т.д., то есть:

Rez: = 0; x:=0.l;

for i:=l to 6 do

Begin  Rez:=Rez+f(x);

x:=x+0.2;

end;

Теперьв данную программу нужно «вставить» вычисленные f(x) с необходимойточностью. Для этого найдем сумму, составляющую f(x) для n элементов, затем –для n+l элемента, сравним их по модулю и, когда разность между ними будетменьше Е, сумму для n+l элемента ряда примем за более точную и добавим к Rez.При вычислении f(x) количество членов ряда, которые нам придется суммировать,не известны, поэтому придется применять цикл типа repeat или while.Кроме того, в элементы ряда входит 2n! Факториал подсчитывается по схеме 1! =1, 21 = 1*2; з! =1*2*3и т.д., т.е. например, 8! = 1*2*3*4*5*6*7*8.Далее, при подсчете следующего значения ряда, можно величину 2n! найти посхеме: fak: = fak*(n-l)*n.Ряд у нас знакопеременный, т.е. меняется '+', '–' перед каждым членом ряда.Меняем знак с помощью схемы znak: = znak*(-1).Если исходный знак = +l, то в ячейке znak будет храниться то +l, то -1.

Сучетом сказанного выше f(x) с нужной точностью вычисляется:

fxpred: = 0; fxpos: =l, n: = 2; znak: = 1; fak: = 1;

while Abs(fxpos – fxpred) > = 0.01 do

Begin fxpred: = fxpos: znak: = znak*(-1);fak: = fak*(n-l)*n;

     fxpos: = fxpos+znak*exp(n*in(x))/fak;

     n: = n+2;

    end;

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

       Program Prim22;

    Var n,fak,i,znak:longint;

        rez,x,fxpred,fxpos:real;

 BEGIN  rez:=0; x:=0.1;      writeln;

        for i:= 1 to 6 do

     Begin fxpred:=0; fxpos:=1; n:=2;znak:=1; fak:=1;

           whileabs(fxpos-fxpred)>=0.001 do

        Begin znak:=znak*(-1);fak:=fak*(n-1)*n;

              fxpred:=fxpos;

             fxpos:=fxpos+znak*exp(n*ln(x))/fak; n:=n+2;

        end;  writeln('x=',x*180/pi,'(ја ¤) cos(x)=',fxpos);

              x:=x+0.2; rez:=rez+fxpos;end;

           writeln('rez=',rez);

                     readln;              END.


5.Ввод – вывод

 

5.1. Общие положения

Ввод-выводвыполняется с помощью операторов read, readln – читать и write,writeln – писать. Читать и писать определяется по отношению к оперативнойпамяти (ОП). Так, read, readln – читать, т. е. вводить с внешнегоустройства (файла) и заносить данные в ОП, write, writeln – писать, т.е.выводить данные из ОП на внешний файл (устройство). Файл состоит из компонент,структура которых определяется при его создании.

Внешнимиустройствами (файлами) могут быть: экран монитора, клавиатура, память на гибкихдисках, память на жестком или лазерном дисках, линии связи и т.п. В операторахввода-вывода указывается имя файла, с которым будет производиться ввод-вывод,этот файл считается логическим. Кроме того, есть понятие физического файла. Физическийфайл – это устройство, Например, гибкий магнитный диск, жесткий диск и т. д.Логический файл имеет имя, которое можно указывать в операторах ввода-вывода.

 

5. 2. Ввод

Вводпроизводится с помощью операторов read или readln.

Форматоператоров: read (FV, х1, х2, ..., хn);

или   readln (FV, х1, х2, ..., хn);

гдеFV — имя файла, с которого считывается информация, а х1, х2и т.д. – ячейки памяти, в которые заносится информация, считываемая с файла. ЕслиFV отсутствует, то чтение производится с клавиатуры. Файл представляетсобой как бы ленту с компонентами (рис 5.1):

/>


Компонентаможет быть данным любого типа (см. с.9). Оператор readln начинаетсчитывание с начала новой компоненты, а read может начинать не с начала.Если прежнее чтение закончилось внутри компоненты, то следующий readбудет читать с того места, на котором закончилось предыдущее чтение (рис. 5.2).

/>


Вданном случае файл организован на каком-либо носителе (например на диске) исостоит из компонент, в каждой находится по три данных. Если для чтения изфайлов применить операторы read (a,b);read (c,d); то в памяти будет а=3.2, b=8.6,c=0.2, d=7.01;если – операторы readln (a,b);readln (c,d), то в памяти а=3.2, b=8.6,c=7.01, d=8.3.

Замечание.При чтении данных с клавиатуры необходимо всегда использовать операторы readln(х1, х2, ..., хn); (без указанияимени файла).

 

5. 3. Вывод

Выводпроизводится с помощью операторов write или writeln.

Форматоператоров: write (FV, x1,x2, ..., xn);

                                   writeln (FV, x1, x2, ..., xn);

Работа оператора: в файл с именем FV выводится информация изячеек оперативной памяти x1, x2, ..., xn. Если FV отсутствует, вывод производится на экран монитора.При этом оператор write начинает вывод в то место компоненты файла, гдебыл закончен прежний вывод, а оператор writeln начнет вывод с началановой компоненты. Проиллюстрируем работу этих операторов на примере выводаданных на экран монитора.

Имеется фрагмент программы (напомним, что текст в скобках { }является комментарием и машиной не воспринимается);

  Var  a, b, c, d: integer;

Begin   a: = 25; b: = 38; c: = 126; d: = 256;

  writeln (a, b, c, d);                 {результат2538126256}

  writeln (a, b); writeln (c, d);  {результат2538 }  

                                                      {126256 }

   writeln (' a=', a, ' b= ', b);     {результатa=25 b=38}

  {символы в апострофах   выводятся какстроковая константа}

  write (a, b, c, d);                    {результат2538126256}

  write (a, b); write (c, d);        {результат2538126256}

  write (' a= ', a, '   b= ', b);    

  write ('   c=', c, '   d= ',d);     {результат a=25   b=38   c=126    d=256 }

 

5. 4. Некоторые возможностиввода-вывода

Оператор Readln; (без скобок, имени файла и спискаячеек памяти) вызовет остановку машины. Продолжение выполнения программыпроизойдет после нажатия кнопки Enter. Это очень удобно при просмотрекаких-либо промежуточных результатов, например:

writeln ('a=  ', a); Readln;

Машина выведет а=… и остановится, после нажатия кнопки Enterвыполнение программы продолжится.

Оператор writeln; вызовет переход к новой компоненте,в случае вывода на экран – к новой строке экрана. Рассмотрим фрагмент программы:

  Var  i, k; integer;

Begin  i: = 126; k: = 1997;

  writeln ('i= ', i, '   k= ', k);   {результатi=126   k=1997}

   writeln (i: 3, k: 6);                {результат 126    1997}

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

{данное «прижимается» в поле к правому краю 1997}

  writeln (i: 7, k: 8);                    {результат    ....126....1997}

Пример:

ProgramPrim23;Var r,pl:real;BEGIN      writeln('введите радиус шара'); readln(r);     pl:=4*pi*sqr(r);writeln('____________________________________________________');writeln('!площадь шара рад.r=',r:14,' =',pl:14,'!');writeln('____________________________________________________');

readln;END.

Врезультате на экран выведется информация:

— — - — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -- — — — — — — — — —

! площадьшара радиусом  R=хххххххххххххх  =  ххххххххххххххх  !

— — - — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — - — — — — — — — — -

Здесьххххххххххххх — изображения чисел.

Спомощью такого приема строятся различные таблицы.

Привыводе величины Real в операторах write и writeln отводится поле шириной 18символов для вывода данных с «плавающей точкой» в следующем формате… х.ххххххххххЕ*хх;здесь х – цифры, * – знак, который может быть '+' или '-', '.' – десятичнаяточка, отделяющая целую часть от дробной. Перед целой частью, в случае отрицательногоданного, может стоять знак минус.

Такимобразом:

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

R = 715.432                  writeln (R);               7.1543200000E+02

R = -1.919e+01            writeln (R);              -1.9190000000E+01

R =-567.986                 writeln (R);              -5.6798600000E+02

Напоминаем:Е+02 означает 102,а 7.1543200000Е+02 равносильно математической записи 7.15432*102.

Ширинуполя вывода можно указывать для данных любого типа, например:

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

R = 511.04               writeln (R: 22);                     ......5.1104000000E+02

ch = 'x'                            writeln (ch:3);                       ..x

ch = '!'                             writeln (ch: 2, ch: 4,ch: 3);   .!...!..!

strin = 'Day  N'               writeln (strin: 8);                   ...Dau.N

S = 'RDD'                       writeln (S: 5, S: 5);               ..RDD..RDD

Дляданных типа Real можно еще указывать кроме ширины поля также количество цифрпосле десятичной точки.

Выводданных с «фиксированной точкой».

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

R = 511.04                 writeln (R: 8: 4);                511.0400

R = -46.78                  writeln (R: 7: 2);               .-46.78

R = -46.78                  writeln (R: 9: 4);               .-46.7800

R = -46.78                  writeln (R: 12: 3);              .....-46.780

Program Prim24;

Var r1,r2:real;

BEGIN    r1:=-46.78; r2:=-46.78;

      writeln('r1=',r1:12:3,'  r2=',r2:9:4);

      writeln('_______________________________');

    readln; END.


6.Массивы

 

6. 1. Описание массивов

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

Массивы могут быть одномерные:

вектор a1, a2, a3, a4,a5, ...an, т. е. линейка величин -  -  -  -  -  -  -  -  -  -  -  - 

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

a11 a12 … a1n ,   т. е. матрицу величин или прямоугольник величин

a21 a22 … a2n              ----    ----    ----      

— — — — — — — — — -            ----     ----    ----

am1 am2 … amn           ----     ----   ----

Трехмерный массив – трехмерная матрица или параллелепипед величин,состоящий из набора двухмерных матриц (рис.6.1).

/>


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

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

Прямое описание Var – идентификатор, идентификатор, …,идентификатор:

array– [границы индекса, границы индекса, …, границы индекса] of – базовыйтип.

Описаниечерез TYPE:

 TYPE  – имя типа=array [границы индекса, границы индекса, … ., границы индекса] ofбазовый тип;

Var –идентификатор, идентификатор,..., идентификатор: имя типа;

Пример: описать двумерные массивы с количеством элементов 4строки по 5 элементов в каждой строке (5 столбцов),

базовыйтип real, массивов три: а, b, c.

Прямоеописание:

     Var a, b, c: array [1… 4, 1… 5] of real;

через TYPE:

       TYPE mas=array [1… 4, 1… 5] of real;

       Var a, b, c: mas;

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

      Const  a1=4; a2=6;

       Var mas y1: array [1… a1, 1… a2] of integer;

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

Например, описана ma: array [1… 12] of integer; выделено 12 ячеек  памяти   для хранения целых данных типа integer с именами

ma [1], ma [2], ma [3], ит.д., ma [12].

Пример:

         TYPE  klass = ( K1, K2, K3, K4);

                    znak = array [1… 255] ofchar;

        Var m1: znak;  {описан массив с именем M1 типа znak для хранения данных}

{типаchar  в  количестве 255 шт. M1[1], M1[2],…, M1[255]}

M2:array [1...60] of integer     {прямое описание, описан массив сименем}       

{M2для хранения   целых  величин. всего }

                                                      {ячеек 60.M2[1],…, M2[60] }

M3: array [1… 8] of klass;  {описан массив М3, выделено 8ячеек памяти М3[1],… ,  M3[8],}

         {в каждой из которых могут храниться только величины из}                    

{klass,т. е. туда могут быть занесены только K1, K2, K3, K4}

Пример:

                      ProgramPrim25;

    Var i:integer;  s:real;

        a:array[1..10] of real;

  BEGIN

     for i:=1 to 10 do

      Begin writeln('введите значение величины a[',i,']');

 readln(a[i]);end;            { вводэлементовмассива}

    s:=0;

     for i:=1 to 10 do

      s:=s+a[i];        {нахождениесуммыэлементова[i]}

    writeln('s=',s);   readln;

                                END.

Здесь мы проиллюстрировали работу с одномерным массивом. Конечно,данную программу легче представить в следующем виде:

          ProgramPrim25a;

    Var i:integer;  s,a:real;

  BEGIN

      s:=0;

     for i:=1 to 10 do

      begin writeln('введите значение величины a[',i,']');

     readln(a);         { ввод по одному а (без массива)}

                   { имитация ввода элементов массива }

     s:=s+a;

   writeln('s=',s); end;

      readln;                                END.

Никаких массивов здесь не применять. На примере prim25 мычетко проследим два момента: занесение данных в массив (первый цикл) и обработкаданных в массиве (второй цикл).

Пример: дана квадратная матрица. Вывести на экран элементы ееглавной диагонали (элементы главной диагонали перечеркнуты)

/>    a11   a12   a13   a14

    a21   a22    a23   a24

    a31   a32    a33   a34

    a41   a42    a43   a44

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

           Program Prim26;

    Var i,j,k:integer;

        a:array[1..4,1..4] of integer;

        b:array[1..4] of integer;

  BEGIN

     for i:=1 to 4 do

     for j:=1 to 4 do

      Begin   writeln('введитеa[',i,',',j,']');

      readln(a[i,j])   end;  {ввод элементов массива а закончен }

     k:=1;                        { устанавливаем индекс для занесенияb[1] }

     for i:=1 to 4 do

     for j:=1 to 4 do

    if i=j then Begin b[k]:=a[i,j]; k:=k+1; end;

{отыскиваем и заносим в b[1] a[1,1]}

                             {меняем k и заносим в b[2] a[2,2] и т.д.}

    writeln('на главной диагонали лежат злементы:');

    writeln('a[1,1]=',b[1],'a[2,2]=',b[2],' a[3,3]=',b[3],' a[4,4]=',b[4]);

      readln;

                                END.

Вэтой программе машина запросит ввод 16 элементов матрицы А, найдет элементыглавной диагонали, занесет их в массив B и напечатает результат в следующем виде:

на главной диагонали лежат элементы:

A[1,1]= число     A[2,2] = число     A[3,3] = число     A[4,4] =число

                      ProgramPrim26a;    Var i,j,k:integer;        a:array[1..4,1..4] of integer;       b:array[1..4] of integer;  BEGIN     for i:=1 to 4 do

     for j:=1 to 4 do

      Begin writeln('ввестиa[',i,',',j,']');

      readln(a[i,j]);end;       { ввести массив а }

                                       { вывести элементы массива а }

    for i:=1 to 4 do  Beginwriteln;            { перевестикурсорнановуюстроку}

        for j:=1 to 4 do

     write(a[i,j],' ');      { вывести элементы в одну строку}

 end;

     k:=1;

     for i:=1 to 4 do

     for j:=1 to 4 do

    if i=j then Begin b[k]:=a[i,j];k:=k+1; end;

                             {отыскиваеми заносим в b[1] a[1,1]}

                            {меняем k и заносим в b[2] a[2,2] и т.д.}

   writeln('  на главной диагонали лежат элементы:');

   writeln('a[1,1]=',b[1],' a[2,2]=',b[2],'a[3,3]=',b[3],' a[4,4]=',b[4]);

      readln;

                               END.

Эта программа отличается от предыдущей тем, что она вначалевводит массив А, затем его распечатывает в виде

   a11   a12    a13  a14

    a21   a22    a23   a24

    a31   a32    a33   a34

    a41   a42    a43   a44

апосле выводит результаты в том же виде, что и программа Prim26, т.е.

          Program Prim26b;

    Var i,j,k,n:integer;

        a:array[1..40,1..40] of integer;

        b:array[1..40] of integer;

  BEGIN   writeln('введите размерностьмассива');

          readln(n);

     for i:=1 to n do

     for j:=1 to n do

      Begin writeln('введитеa[',i,',',j,']');

      readln(a[i,j]); end;

                             { вывести элементы массива а }

     fori:=1 tondo

  Begin writeln;            {перевести курсор на новую строку}

        for j:=1 to n do

     write(a [i,j],'  ');      {вывестиэлементыводнустроку}

  end;

     k:=1;

     for i:=1 to n do

     for j:=1 to n do

    if i=j then Begin b[k]:=a[i, j]; k:=k+1; end;

                             {отыскиваем изаносим в b[1] a[1,1]}

                             {меняем k и заносим в b[2] a[2,2] и т.д.}

    writeln('  на главной диагонали лежат элементы:');

    for k:=1 to n do

    write('  a[',k,',',k,']=',b[k]);

      readln;

                                END.

Этапрограмма работает так же, как и предыдущая, но с массивами и с переменнымиизмерениями.

Величина входного массива может быть до 40 строк и 40столбцов. Чтобы это обеспечить, в разделе Var описываем массив a:array [1..40,1..40] of integer; а затем в программе вводим по запросу n,которое будет определять, с матрицей какой величины мы будем работать конкретно(n должно быть в диапазоне 1-40). Далее все циклы программы работают от1 до n, т.е. машина решит задачу для массива введенной размерности n.

           Program Prim27;

    Var i,j,k,n:integer;

        a:array[1..40,1..40] of integer;

        b:array[1..40] of integer;

  BEGIN   writeln('ввестиn'); readln(n);

     for i:=1 to n do

     for j:=1 to n do

      Begin writeln('ввестиa[',i,',',j,']');

      readln(a[i,j]); end;

                             { вывести элементымассива а }

     fori:=1 tondo

  Begin writeln;            {перевести курсор на новую строку}

        for j:=1 to n do

     write(a[i,j],' ');      {вывестиэлементыводнустроку}

  end;

     k:=1;

     for i:=1 to n do

     for j:=1 to n do

    if i+j-1=n then Begin b[k]:=a[i,j]; k:=k+1; end;

{отыскиваем и заносим в b[1] a[1,1]}

                                                {меняем k и заносим вb[2] a[2,2] и т.д.}

    writeln;

    writeln('  на дополнительной диагонали лежат элементы:');

    for k:=1 to n do

 write(b[k],'  ');

      readln;

                                END.

ПрограммаPrim 27 работает аналогично программе Prim 26b, однако выводитэлементы, лежащие на дополнительной диагонали.

        Program Prim28;

    Var i,j,min,m,n,k:integer;

        a:array[1..20,1..10] of integer;

        b:array[1..10] of integer;

  BEGIN   writeln('ввестиm,n'); readln(m,n);

     for i:=1 to mdo                {m – количествострок  }

     for j:=1 to n do                {n – количествостолбцов}

      Begin writeln('ввестиa[', i ,', ', j,']');

      readln(a[i, j]); end;

                             { вывести элементымассива а }

     fori:=1 tomdo

  Begin writeln;

          for j:=1 to n do

     write(a[i,j],'  ');  end;

  min:=32767; {максимальное integer, чтобы в последующемсравнивать}

{и заносить в min все элементы a[i,j], которые меньше min}

     for i:=1 to m do

     for j:=1 to n do

   if a[i, j]<min then Begin min:=a[i, j]; k:=i;  end;

  writeln(' строка, содержащая наименьшийэлемент');

    for j:=1 to n do

    write(' a[', k ,',', j ,']=',a[k, j]);

      readln;                       END.

Программа Prim 28 находит в массиве строку размером до20х10, содержащую наименьший элемент.

  Program Prim29;

  Var i,j:integer; a:array[1..5, 1..7] of integer;

                   b:array[1..7] of integer;

                   c:array[1..5] of integer;

   BEGIN for i:=1 to 5 do

         for j:=1 to 7 do

      begin writeln('введитеa[',i,',',j,'] элементматрицыа');

            readln(a[i,j]); end;

         for j:=1 to 7 do

      begin writeln('введитеb[',j,'] элементвектораb');

            readln(b[j]); end;

    for i:=1 to 5 do      {начало перемножения матрицы на вектор}

  begin c[i]:=0;

    for j:=1 to 7 do

     c[i]:=c[i]+ a[i,j]*b[j]; end;

{конец перемножения матрицы на вектор}

     writeln('распечаткамассиваа');

       for i:=1 to 5do

          begin writeln;  {начать новуюстроку}

       for j:=1 to 7 do

       write(' ',a[i,j]); end;       writeln;

      writeln('распечаткамассиваb');

          for j:=1 to 7do

     write('  ',b[j]);               writeln;

     writeln('результирующиймассивс');

          for i:=1 to 5do

     write('  ',c[i]);

             readln;    END.

Программа вводит матрицу А размером 5х7 и вектор размером 7 элементов,затем их перемножает по правилу Сi =Сi + a[i,j]*b[j] и выводит пять элементов массиваС.

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

  Program Prim29a;

  Var i,j,n,m:integer; a:array[1..50,1..70] of integer;

                   b:array[1..70] of integer;

                   c:array[1..50] of integer;

   BEGIN  writeln('ввести количество строки столбцов');

          readln(n,m);

        for i:=1 to n do

        for j:=1 to m do

      begin writeln('ввестиa[',i,',',j,'] элементматрицыа');

            readln(a[i,j]); end;

         for j:=1 to m do

      begin writeln('ввестиb[',j,'] элементвектораb');

            readln(b[j]); end;

    for i:=1 to n do       {начало перемножения матрицы на вектор}

  begin c[i]:=0;

    for j:=1 to m do

     c[i]:=c[i]+ a[i,j]*b[j]; end;

                           {конец перемноженияматрицы на вектор}

     writeln('распечаткамассиваа');

       for i:=1 to ndo

          Begin writeln;         {начатьновую строку}

       for j:=1 to m do

write('',a[i,j]); end;       writeln;

     writeln('распечаткамассиваb');

         forj:=1 to m do

    write('  ',b[j]);               writeln;

     writeln('результирующиймассивс');

         fori:=1 to n do

    write('  ',c[i]);

            readln;    END.

Программа Prim 29aтоже перемножает матрицу на вектор. Здесь матрица может иметь размеры до 50х70,соответственно вектор B может иметь размер до 70, а вектор С – размер до 50элементов.


7.Подпрограммы

 

7.1. Общие положения

/>В практике программирования часто встречаютсяситуации, когда одну и ту же группу операторов необходимо выполнить в различныхместах программы, неважно, что при этом по-разному будут называться исходные данныеи результаты работы этих операторов. Важно, что эти группы операторов выполняютодну и ту же работу. Например, в различных местах программы необходимовычислить корни квадратного уравнения, причем в одном месте это будет уравнениеax2+bx+c=0, в другом  – sz2+tz+p=0, в третьем – ky2+ly+n=0 и т.д. В этом случаеалгоритм вычисления корней уравнения в программе можно писать один раз в видеподпрограммы, а использовать его многократно. Блок-схема такой программы безприменения подпрограммы изображена на рис. 7.1.

/>Блок-схема алгоритма сиспользованием подпрограммы изображена на рис. 7.2.

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

Функции применяют тогда, когда результат работы подпрограммыодин. Обращение к функции может записываться в выражениях, например: (а+b)/cos(x).Здесь cos(x) есть обращение к подпрограмме типа «функция»,правда, стандартной, а не написанной пользователем. Встретив имя cos, машинас входной величиной x обращается к подпрограмме, вычисляет с помощьюряда функцию cos(x) (см. программу в подразд. 4.4.), и результат этойработы в виде значения функции возвращается в арифметическое выражение.     Функция может иметь несколько входных параметров, но всегда один результат.Процедура также может иметь несколько входных параметров, но несколькорезультатов. Несколько – это 0, или 1, или 2, или 3 и т.д. результатов.Обращение к процедуре состоит из отдельного оператора. Например, обращение кпроцедуре, вычисляющей корни квадратного уравнения, может иметь вид:    root(a, b, c, x1, x2);

Подпрограммы, как функции, так и процедуры могут быть стандартными,например sin(x), cos(x), sqrt(x), succ(y), ord(y) и т.п.; библиотечными,которые становятся доступными при подключении модулей и библиотек (см. далее),а также определены пользователем, т.е. написаны программистом для решения своейзадачи.

 

7.2. Подпрограммы-функции,определенные пользователем

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

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

/>f1(x)=x+256.4; f2(y)=y+256.4; f3(z)=z+256.4;

          Program Prim30;

  Var

        x,y,z,f1,f2,f3:real;

  function f(x:real):real;        {заголовокфункции;}

                                  { f – имя функции, это же и имя}

                            {результата, х – формальный параметр}

   Begin f:=(x+256.4); end;      {тело функции}

 BEGIN                           {начало основной программы}

      writeln('ввести x,y,z'); readln(x,y,z);

  f1:=f(x); {обращение к подпрограмме f с фактическим параметром x}

  f2:=f(y); {обращение к подпрограмме f с фактическим параметром y}

  f3:=f(z); {обращение к подпрограмме f с фактическим параметром z}

         writeln(f1:20,f2:20,f3:20);readln;   END.

 Написатьпрограмму, вычисляющую G:

/>

Оформим вычисления /> в видеподпрограммы-функции:

     ProgramPrim31;

    Var    h,x,y,z,g:real;

  function f(a,b:real):real; {входныеформальныепараметрыa,b}

     Begin

        f:=sqr(ln(a)+sin(b))/(cos(a)*exp(b));

                             end;

 BEGIN writeln ('введите положительные h,x,y,z');

       readln(h,x,y,z);

   if (x>=1) and (x<3)  then writeln('g=',h+f(x,y))else;

   if (x>=3) and (x<5)  thenwriteln('g=',sqrt(h)+f(z,x)) else;

   if (x>=5) and (x<=9) thenwriteln('g=',sqr(h)+f(y,z)) else;

                             writeln('g=0');

             readln;   END.

В этой программе описание формулы начинается словом function,имя функции f, результат вычисления функции типа real. Телофункции заключено в операторные скобки begin, end; a, bназываются формальными параметрами. В данной функции нам не понадобилисьразделы описаний.

При выполнении основной программы, которая начинается begin,встречается выражение f(x, y). Встретив такое выражение, машина по имениf определяет, что это обращение к функции. затем машина проверяет совпадениеколичества и типа фактических параметров (x, y) с формальными (a, b).При их совпадении в тело функции вместо формальных параметров подставляютсяфактические и тело выполняется, полученный результат используется привычислении выражения, стоящего в операторе writeln.

Составитьпрограмму вычисления при условии, что а<b:

/>

Если a и b не укладываются в заданные пределы, нужно сообщитьоб этом пользователю и спросить, будут ли другие диапазоны — ответ: «Y,N». Если заданы не те буквы (y, n), повторить вопрос.

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

/>  оформим в виде функции f1;

/>  – в виде f2;

sin(x)+f1  – в виде f3;

cos(x)+f1 – в виде f4;

cos(x)-f2  – в виде f5;

вычисления />  по методу трапеций сточностью 0.1 oформим в виде подпрограммы-функции f6.

   Program Prim32;        label NAH,P;

       Var   b,a,z:real;

             lit:char;

          function f1(x:real):real;

            Begin f1:=exp(x/10)+sqrt(x/(x+3)); end;

          function f2(x:real):real;

            Begin f2:=sqrt(sqr(x)/(3*x+10)); end;

          function f3(x:real):real;

            Begin f3:=sin(x)+f1(x); end;

          function f4(x:real):real;

            Begin f4:=cos(x)+f1(x); end;

          function f5(x:real):real;

            Begin   f5:=cos(x)-f2(x); end;

      function f6(a,b:real):real;

          label K,N1,K1,KC,T;

          Var  h,s1,s,x:real;  i,n:integer;

      Begin

            s1:=9.999e+10; n:=10;

    N1:     h:=(b-a)/n; s:=0; x:=a;

          for i:=1 to n do

       Begin  if a>b then goto t else

        if (0<=a)and(b<5)    then Begin s:=s+(f3(x)+f3(x+h))/2*h;

                          goto kc; end      else

        if (5<=a)and(b<10)   then Begin s:=s+(f4(x)+f4(x+h))/2*h;

                          goto kc; end      else

        if (10<=a)and(b<=16) then Begin s:=s+(f5(x)+f5(x+h))/2*h;

                          goto kc; end      else  goto t;

 KC:    x:=x+h; end;

        if abs(s-s1)<0.1 then goto k

          else   Begin s1:=s; n:=n*10; goto n1; end;

 Kf6:=s;gotok1;

 T:  writeln('пределы интегрирования не соответствуют условию');

     f6:=-9999999999.;

 K1: end;

 BEGIN

 NAH:  writeln('введитезначенияa,b');

       readln(a,b); z:=f6(a,b);

     if z=-9999999999. then goto p;

       writeln('z=',z);

    P:  readln;

      writeln(' будем еще вычислять z?, если«да» ',

              'то нажмите клавишу «y», если нет, то любую клавишу ');

      readln(lit);

    if (lit='Y') or (lit='y') then goto NAH;

                             END.

 

7.3. Подпрограммы-процедуры

Описаниепроцедуры:

Procedure имя (входные формальные параметры:тип;

Var выходные формальные параметры: тип);

описания(если они есть)

begin операторы

end;

Пустьнеобходимо найти корни квадратных уравнений

ax2+bx+c=0,

ky2+my+d=0,

sz2+tz+p=0,

гдекоэффициенты a, b, c вводятся по запросу. количество уравнений не ограничено.результаты вычислений выводить на экран (в основную программу не возвращать),см. рис. 2.1.

 ProgramPrim33;

          label K,NAH;

          Var  let:char; a,b,c:real;

  procedure root(a,b,c:real); {процедура не имеет выходныхпараметров}

           labelK;

            Var d,x1d,x1m,x2d,x2m:real;

        Begin       ifa=0 thenBegin

           writeln('уравнение первой степени, корень один');

             x1d:=-c/b;writeln('x=',x1d); goto K; end

                    else d:=b*b-4*a*c;

          if d>=0 then Begin

        writeln('уравнение второй степени, корни действительные');

            x1d:=(-b-sqrt(d))/(2*a);

             x2d:=(-b+sqrt(d))/(2*a);

             writeln('x1d=',x1d,'  x2d=',x2d); goto K; end

          else writeln('уравнение второй степени, корни комплексные');

              x1d:=-b/(2*a);            x2d:=x1d;

                  x1m:=-sqrt(-d)/(2*a);      x2m:=-x1m;

            writeln('z1=',x1d,' ',x1m,' i;');

            writeln('z2=',x2d,' ',x2m,' i;');

    K: end;

  BEGIN NAH: writeln('введитеa,b,c'); readln(a,b,c);root(a,b,c);

        writeln('будет еще уравнение? если «да», нажмитеклавишу«Y»',

                'если «нет», нажмите любую клавишу');

       read(let);

    if (let='Y') or (let='y') then goto nah else goto K;

  K: END.

Найтиx, y, z — корни системы уравнений:

/>

Какизвестно из линейной алгебры ,      />

где   />

Раскрытиеопределителя  />

+

    />/>/>/>/>

  />/>/>производится посхеме:    />т.е. />

впроцедуре a,b,c,d– входные данные, x,y,z– результаты.

   Program Prim34;

     label N,K;

     Type  w=array[1..3] of integer;

      Var a,b,c,d:w;       x,y,z:real;   let:char;

  function det(a:w;b:w;c:w):real;

     Begin det:=a[1]*b[2]*c[3]+b[1]*c[2]*a[3]+c[1]*a[2]*b[3]

            -c[1]*b[2]*a[3]-a[1]*c[2]*b[3]-b[1]*a[2]*c[3]; end;

  procedure ur(a,b,c,d:w; Var x,y,z:real);

       Var d0:real;

      Begin   d0:=det(a,b,c);

         if d0=0 then Begin writeln('det=0 решениянет');

                      let:='0'; Exit; end  else        {EXIT– выход из процедуры}

              x:=det(d,b,c)/d0;

              y:=det(a,d,c)/d0;

              z:=det(a,b,d)/d0;     let:='1';   end;

 BEGIN N: writeln('введитеa1,b1,c1,d1'); readln(a[1],b[1],c[1],d[1]);

          writeln('введитеa2,b2,c2,d2'); readln(a[2],b[2],c[2],d[2]);

          writeln('введитеa3,b3,c3,d3'); readln(a[3],b[3],c[3],d[3]);

          ur(a,b,c,d,x,y,z);

      if let='0' then goto K else

        writeln('                    /',a[1],'x+',b[1],'y+',c[1],'z=',d[1]);

        writeln('система i  ',a[2],'x+',b[2],'y+',c[2],'z=',d[2]);

        writeln('                  \ ',a[3],'x+',b[3],'y+',c[3],'z=',d[3]);

        writeln('имеет решение: x=',x,'  y=',y,'  z=',z);

  K: writeln('Будет ещё ур-е? да - «Y», нет – любая клавиша ');

    read(let);

    if (let='Y') or (let='y') then goto N;

  END.

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

Задача1. Массив один и состоит из 7 элементов.

Задача2. Массивов два, размерность первого – 7 элементов, второго – 5.

Задача3. Количество массивов не ограничено, количество элементов в массивахпроизвольное, но не более 70.

 Program Prim35;  {массив1 исостоитиз7 элементов}          label j;          Type mas=array[1..7] of real;          Var n,k,i,no:integer;

              a:mas;

              s:real;   ch:char;

   procedure prmas(a:mas;n:integer; Var s:real; Var k,no:integer);

           Var i:integer;

       Begin   s:=0; k:=0; no:=0;

           for i:=1 to n do Begin

   if a[i]>=0 then  s:=s+a[i]  else Begin k:=i; no:=no+1;

                      end; end; end;

 BEGIN

          for i:=1 to 7 do  Begin

         writeln('ввести значениеa[',i,']');

       readln(a[i]);  end;

        prmas(a,7,s,k,no);

 j:     writeln('сумма положительных элементов =',s);

        writeln('последний отрицательный элемент имеетN=' no);

        writeln('количество отрицательных элементов =', k);

         readln;

 END.

 Program Prim36; { массива2, размерностьпервогомассива7, второго– 5}          label j;          Type mas=array[1..7] of real;          Var k,no,y:integer;               s:real;   ch:char;    procedure prmas(n:integer;var s:real; var k,no:integer);

           Var i:integer; a:mas;

     Begin for i:=1 to n do Begin

           writeln('введите ',i,' значениеэлемента массива');

           readln(a[i]);  end;

            s:=0; k:=0; no:=0;

           for i:=1 to n do begin

   if a[i]>=0 then  s:=s+a[i]  else begin k:=i; no:=no+1;

                     end; end; end;

 BEGIN  prmas(7,s,k,no); y:=0;

 j:     writeln('сумма положительных элементов =',s);

        writeln('последний отрицательный элемент имеетN=', no);

        writeln('количество отрицательных элементов =', k); y:=y+1;

         if  y=1 then Begin prmas(5,s,k,no); gotoj; end

         else readln;

 END.

Program Prim37; { массивыспеременнымиизмерениями,количество   массивовнеограничено}         Type mas=array[1..70] of real;          Var n,k,i,no,kol,r,j:integer;               a,b:mas;               s:real;  ch:char;    procedure prmas(n:integer; var s:real; vark,no:integer);            var i:integer; a:mas;

       begin  for i:=1 to n do begin

               writeln('введите',i,'  значение элемента массива ', j);

               readln(a[i]); end;

        s:=0; k:=0; no:=0;

           for i:=1 to n do Begin

   if a[i]>=0 then  s:=s+a[i]  else Begin k:=i; no:=no+1;

                      end; end; end;

 BEGIN

         writeln('задайтеколичествомассивов');readln(kol);

      for j:=1 to kol do Begin

         writeln('задайте размерность массива', j); readln(r);

        prmas(r,s,k,no);

         writeln('сумма положительных элементов =',s);

        writeln(' последний отрицательный элемент имеет N=', no);

        writeln(' количество отрицательных элементов =', k); end;

        readln;

 END.

 

7.4. Локальные и глобальныеописания объектов

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

Programимя программы (возможны опции); {опции не обязательны}

Label…;{раздел описания меток}

Const…;{раздел описания констант}

Туре…;{раздел определения типов}

Var…;{раздел описания переменных}

Function…; Procedure …; {раздел описания функций и процедур}

BEGIN… END. {раздел операторов}.

Функциии процедуры, в свою очередь, также являются блоками:

Procedureимя (список входных формальных параметров);

Var (список выходных формальныхпараметров);

Label …;

Const …;

Туре…;

Var ...;

function …;

procedure …;

разделыописаний

begin… end;{телопроцедуры}

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

Какодин из вариантов, возможна следующая структура программы:

         Program Prim38;           { началоблока 1}    label N,M;    Const k=5.6;  Type d=array[1..10] of integer;   Var b,c:real;  i,j:integer;  z,y:d;

 functionf(f,b,c:real):real;       { началоблока 2}

        begin f:=1; end;           {конецблока 2}

 procedureproc(f,b,c:real; Var x,y,z:real); { началоблока 3}

       label K,L;

       var d,w,s:real;

    function fp(a,b:real):real;    { началоблока 4}

               begin fp:=1; end;    {телоfp, конецблока4}

 begin x:=1; y:=1; z:=1; end;      {телоproc, конецблока3}

     BEGINb:=1; END.     {тело основной программы, конец блока 1}

Такимобразом, программа состоит из четырех блоков. Все имена меток, констант, типов,переменных, функции f и Рrосизвестны в блоке 1, поскольку они даны в его описании. Считается, что ониописаны здесь локально.

Вблоке 2 – function – описаний нет, поэтому своих собственных объектовэтот блок не имеет. Формальные параметры не в счет, поскольку они служат толькодля описания алгоритма вычисления результата с именем f в функции f,а ячейки памяти для b, с, f здесь не выделяются. Однако в этом блоке можноиспользовать все объекты, которые описаны в блоке 1, так как блок 2 являетсясоставляющей частью блока 1. Иногда говорят, что имена объектов блока 1 описаныглобально для блока 2.

Аналогичнаяситуация и с блоком 3 – Procedure Рrос.Для нее все объекты блока 1 являются глобальными, т.е. доступны. Кроме того, вблоке 3 имеются свои описанные здесь объекты – метки К, L, переменные d,W, 8, функция fp, которые могут быть использованы тольков блоке 3 и не известны в блоках 1 и 2.

Какследствие возможно применение одинаковых имен в различных блоках (см. имя d).В блоке 1 d – массив. В блоке 3 (в Рrос)имеется свое d, которое является собственным в блоке 3 и представляетсобой не массив, а ячейку памяти типа real.


8.Строковые данные

 

8.1. Общие замечания

Строка– это последовательность символов длиной 0-255. Для описания данных строковоготипа используется слово string, за которым могут следовать в квадратныхскобках цифры, определяющие количество символов в строке. Если цифры вквадратных скобках и сами скобки отсутствуют, то для данной ячейки памяти будетвыделяться максимально возможная длина: 256 байт для хранения 265 символов.Символьные константы (которые могут храниться) имеют вид совокупности символов,заключенных в апострофы.

Пример:'a, b, с — символы'.

Примерыописаний:

Varа, b, с: string [70];

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

Например,возможны операторы:

а:= 'улица Садовая';

b:= улица Чкалова, 17, хаи';

с:= г. Харьков – большой город';

возможнопредварительное описание типа:

Туреa=string[70];

Varb, с: а;

 

8.2. Строковые выражения

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

Операциясцепления, знак операции '+'.

'Дом'+'номер'+'43' дает результирующую строку 'Домномер 43'.

Операцииотношения: =, < >, >, <, >=, <=.

Операцииотношения выполняются раньше операции сцепления, т.е. имеют более высокий приоритет.

Сравнениямежду строками производятся посимвольно, слева направо, до первогонесовпадающего символа. Та строка считается больше, в которой первыйнесовпадающий символ имеет больший код по таблице кодов. Результаты сравнения –True или False.

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

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

Допускаетсяпри записи выражений строкового типа применять данные, описанные с атрибутом char.В этом случае эти данные интерпретируются как string [ 1]. К отдельным символамданного строкового типа можно обратиться по номеру этого символа в строке(аналогично индексу в массивах). В нулевом байте хранится длина строки.

       ProgramPrim39;    varst1,st2:string[30]; BEGINst1:='отдел№ 256'; writeln(st1);       {на экране «отдел № 256»}        st2:=st1[10]; writeln(st2);                         {на экране «5»}          writeln(ord(st1[0]));                               {на экране «11»}

            readln; END.

Еслибы вvar было указано string[10], то writeln(st1), вывел бы результат«отдел № 25»

 

8.3. Стандартные процедуры ифункции для обработки строк

 

8.3.1. Процедуры обработкистрок

Delete(st, Poz, N) – удаление N символов из строки сименем st, начиная с позиции Poz.

st:='река_Волга';Delete (st, 1, 5);

Результат'Волга'.

insert(stl, st2, poz); – вставка строки stl в строку st2,начиная с позиции Poz.

st1:= 'Дом_25_'

st2:=' На_улице_живет_петух_';

insert (stl,st2, 10);

Результат:«На_улице_дом 25_живет_петух»;

str(IBR, st); преобразует число IBR (типа integer, byteили Real) и помещает результат в строку st. Возможно после IBRуказать ширину поля. Если ширины поля не хватает, оно автоматически расширяетсядо нужной величины.

str(1500:6, stl); даст результат '_1500';

str(4.8е+03:10, stl); – результат '_ 4.800E+03';

str(-46854:3, stl); – результат '-46854'.

Val(st, IBR, Cod); процедура преобразует значение st ввеличину целочисленного или вещественного типа и помещает результат в IBR.Значение st должно содержать символьное изображение числа и не содержатьсимволов, не присущих изображению чисел (например, пробелов перед цифрами),букв и т.п. Cod — целочисленная переменная индуцирующая ошибку. ЕслиCod=0, преобразование произведено без ошибки, если Cod=5, то ошибка при преобразовании– 5 символов.

ПрограммаProgram Prim 40; иллюстрирует работу вышеописанных процедур:

       Program Prim40;     varst1,st2:string[30];

 BEGIN st1:=' река Волга ';

       delete(st1,1,5);  writeln(st1);

       st1:='дом25 '; st2:='наулицеживетпетух';

       insert(st1,st2,10);    writeln(st2);

       str(1500:6,st1); writeln(st1);

       str(4.8e+03:10,st1); writeln(st1);

       str(-46854:3,st1); writeln(st1);

            readln;END.

 

8.3.2. Функции обработки строк

Сору(st, Poz, N) выделяет из st подстроку длиной Nсимволов, начиная с позиции Poz.

stl:='absdefg'; writeln (Сору(stl, 2, 3));

результатbсd

Const(stl, st2,..., stn) выполняет сцепление строк stl… stn.Длина суммарной строки не должна превышать 255 символов.

Length(st)определяет длину строки, результат – integer.

Pos(stl, st2) обнаруживает первое появление строки stl встроке st2. Результат – целое число, определяющее номер позиции, вкоторой находится первый символ подстроки st1. Если st1 несодержится в строке st2, то результат равен 0.

UpCase(ch)преобразует строчную букву в прописную.

Параметри результат имеют литерный тип.

ch:=a';UpCase (ch) имеет результат 'A'.

ProgramPrim 41, Prim 42, Prim 43 иллюстрируют работу вышеописанныхфункций.

       Program Prim41;     varst1,st2:string[30];  s:char;  BEGIN st1:='отдел№ 256';        writeln(copy(st1,7,5));        st2:='находитсявНИИ5';

       writeln(concat(st1,st2));

       writeln(length(st2));

       st2:='n 256';

       writeln(pos(st2,st1));

       s:='a';

       writeln(upcase(s));

            readln;END.

      Program Prim42;   {программа удаляет все пробелы в строке, стоящие в строкеслева, если они имеются}

        Var  str:string[255];          { Var str: string; будетработатьтакже}      function del(stroka:string):string;

        Var dlina:byte;

     Begin  dlina:=Ord(stroka[0]);

            while ((dlina>0)and(copy(stroka,1,1)=' '))do

            delete(stroka,1,1);

            del:=stroka;

     end;

     BEGIN  writeln('введитестроку');

            readln(str);

            writeln(del(str));  readln;

     END.

            Program Prim43;   { Даны три исходные строки A,B,C.В строке А определить первую бук } { ву; Затем заменить первую букву строки Асо строчной на заглавную; } { объединить в одну строку A,B,C; Определить длиныстрок A,B,C} { и в результирующей строке вставить '-' между составляющими ее}{строками. В результирующей строке найти номер позиции, в которой } { буква«а» встречается первый раз; определить длину результирующей } {строки. После каждого действия печатать результаты. }      VarA,B,C:string[14];str:string[50];ch:string[1];         d1,d2,d3:integer;

  Begin A:='электронная';B:='вычислительная';C:='машина';         ch:=copy(A,1,1);            writeln(ch);

         delete(A,1,1);               writeln(A);

         writeln(upcase(ch[1]));

         insert(upcase(ch[1]),A,1);   writeln(A);

         str:=concat(A,B,C);          writeln(str);

         d1:=length(A); d2:=length(B); d3:=length(C);

         writeln('длиныстрок' ,d1:6,d2:6,d3:6);          insert('-',str,d1+1); insert('-',str,d1+d2+2);

                               writeln(str);

         writeln('первый раз буква «а»стоит в результирующей строке',                   'в позиции ',pos('а',str));          writeln('общая длинастроки  =',length(str));

         readln;   END.


9.Записи

Ранеемы рассматривали структурированные данные, состоящие из компонент одного типа(массивы). Однако на практике часто необходимо иметь под одним именем совокупностьданных различного типа. Например, информация о студенте может состоять изданных: фамилия, имя, отчество (тип string), домашний адрес (тип string),пол (тип char), номер группы (тип integer), номер комнатыпроживания в общежитии (тип integer), изучаемые предметы (тип, массивстрок) и т.д.

Дляобъединения разнотипных данных под одним именем и возможности последующей ихобработки в языке Pascal предусмотрен тип данных запись.

Записьпоименованный структурированный тип данных, состоящий из фиксированногоколичества различных компонент. Определение (описание) данного типа«запись» начинается атрибутом record и заканчивается end.

Междуrecord и end заключается список компонент записи, называемыхполями, с указанием их имен и типа каждого поля. Туре имятипа=record         идентификатор поля: тип компоненты;          идентификаторполя: тип компоненты;

        end;

Varидентификатор: имя типа;Возможнои «прямое» описание записи, без предварительного описания типа. Пример описаниязаписи с помощью предварительного задания типа:Туре Car=record      Nomer:integer; {номер}      Marka: string [20]; {марка автомобиля}     FIO:string [40], {ф.и.о. владельца}      adres: string [60]; {адрес владельца}end;VarM, V: Car;Либо «прямое» описание:Var М, V: Record      Nomer: integer;       Marka: string [20];

FIO:string [40];      adres: string [60]; end;     Идентификаторполя должен быть уникален только в пределах записи, однако во избежание ошибоклучше его делать уникальным в пределах программы.

Объемпамяти, выделяемый в разделе Var, для хранения записи складывается изобъемов памяти – суммы длин полей.       Значения полей записи могутиспользоваться в выражениях, при этом в них должны указываться составные(уточненные) имена, так как имена полей в различных записях могут совпадать.Например, чтобы получить доступ к полям записи Саr,необходимо пользоваться именами М. FIO,М. NOMER для записи М, а для записи V — именами V. FIO,V. NOMER. Эти имена можно использовать везде, гдеприменяются обычные имена, например, в операторах присваивания:

М.Nomer:=1678;

V. Nomer:=3789;

М.Marka:'газ–24';

V.Marka:='Таврия';

Воператорах ввода-вывода:

writeln(м. marka);

Допускаетсяприменение операторов присваивания к записям в целом, если они имеют одинаковыеструктуры. Так, для приведенного выше описания записей М и V допустимоM:=V;

Послевыполнения этого оператора значения полей записи V станут равными значениямполей записи М.

Вряде задач удобно пользоваться следующими массивами записей:

ТуреPerson=record

     FIO: string [30];

     Prof: string [30); end;

          Var List: array [1..50] of Person;

Здесьмассив List будет состоять из 50 записей типа Person.

Самазапись может иметь поля любого известного нам типа, в том числе и массивного.Допускается, чтобы поле записи само было записью. Обращение к полям записи спомощью составных имен имеет несколько громоздкий вид, что особенно неудобнопри использовании мнемонических идентификаторов длиной более 5 символов. Дляоблегчения этой ситуации в языке Pascal есть оператор with, которыйимеет следующий формат:

withимя переменной типа запись do

begin···················· end.

Одинраз указав в операторе with переменную типа запись, затем – в пределахbegin… end, стоящих после with, можно работать с именами полейэтой записи как с обычными переменными, т.е. без указания перед именем поляимени записи. Например:

безприменения оператора with:

М.NOM:=5543;

M.MARKA:='гa3-24';

М.FIO:='Петров П.П.';

М.Adres:='ул.Чкалова, 7, кв.32';

end;

Составитьпрограмму учета успеваемости студентов курса, состоящего из шести групп до 30студентов в каждой группе. Каждый студент сдавал экзамены по пяти дисциплинам:высшая математика, основы информатики, философия, история Украины, архитектураЭВМ. По каждому предмету можно получить оценки 2, 3, 4, 5. Каждый экзамен можносдавать до трех раз. Произвести анализ: если у студента имеется три двойки поодному предмету или три непересданные двойки по трем предметам, то он долженбыть отчислен; если студент все двойки пересдал, то его нужно поругать.

              Program Prim44;

     label u,w;

     type mo=array[1..5,1..3] of 0..5;

          st=record

             namb:integer;

            fio:string[20];

             o:mo; end;

     var

         gr:array[1..6,1..30] of st;

         i,j,k,l,kol_dvoek,v,kgr,n:integer;

          md:mo; ch:char;

         predmet:string;    kst:array[1..6] of byte;

    procedurerea_ocenki(fio:string;Var oc:mo);

      LabelM1,M2,M3,M4;

      Var i:integer;

        begin

            for i:=1 to 5do

           Begin

              case i of

            1:predmet:='основыинформатики';

            2:predmet:='высшейматематике';

            3:predmet:='философии';

            4:predmet:='архитектуреЭВМ';

            5:predmet:='историиУкраины';  end;

              writeln('введитеоценкустудента  ',fio,' no',predmet);

   M1: readln(oc[i,1]);

           if(oc[i,1]<2) or (oc[i,1]>5) then

        Begin writeln('введите правильнооценку'); goto M1; end;

         if oc[i,1]>2 then Beginoc[i,2]:=0; oc[i,3]:=0; goto M4; end else

   M2: writeln('введите вторую оценкустудента ',fio,' по ',predmet);

       readln(oc[i,2]);

           if(oc[i,2]<2) or (oc[i,2]>5) then

        Begin writeln('введите правильнооценку'); goto M2; end;

         if oc[i,2]>2 then beginoc[i,3]:=0; goto M4; end else

   M3: Writeln('введите третью оценкустудента ',fio,' по ',predmet);

       readln(oc[i,3]);

           if(oc[i,3]<2) or (oc[i,3]>5) then

        begin writeln('введите правильнооценку'); goto M3; end;

           M4: endend;

   BEGIN                      {начало блока ввода оценок студентов}

       writeln('при вводе оценкинабираются: 5, если экзамен');

       writeln('сдан на 5 и, еслибыли пересдачи, то 2,2,3 ');

   z:    writeln('до первой положительнойоценки');

   writeln('задайте количество групп,не более 6 ');

   readln(kgr);

            for i:=1 to kgr do      {установка индекса группы }

  begin  case i of                  {определяем группу по i}

         1:n:=610;

         2:n:=611;

         3:n:=612;

         4:n:=613;

         5:n:=614;

         6:n:=615;

           else writeln('неправильнозадано количество групп'); goto 2; end; end;

        writeln('задайте количествостудентов в группе ',n);

        readln(kst[i]);

            for j:=1 to kst[i] do  {установка номера студента iв группе }

   begin   with gr[i,j] do         {работать без составных имен }

   begin  namb:=n; writeln('введитефамилию',j,' студента гр. ',namb);

            readln(fio);

            for k:=1 to 5do           { обнуляеммассивоценок}

            for l:=1 to 3do

            o[k,l]:=0;

            writeln('введите оценки студентов',fio);

            rea_ocenki(fio,o);end;end;end;

                               { конецввода оценок студентов }

{ отображение на экране введенияоценок }

       for i:=1 to kgr do

       for j:=1 to kst[i]do

    Begin with gr[i,j] do

  Begin     for k:=1 to 5do

   write(o[k,1],o[k,2],o[k,3],' '); writeln; end; end;

{ конец вывода на экран оценок  }

                      { начало блокаанализа успеваемости студентов }

            for i:=1 to kgr do          { индексгруппы}

            for j:=1 tokst[i] do          { номерстудента }

    Begin   kol_dvoek:=0; v:=0;      { работать без составныхимен }

            with gr[i,j] do

    Begin

           for k:=1 to 5do            { номерпредмета }

    Begin

   { итак, анализируем состояниеуспеваемости студента, информация }

   { о котором хранится в записиgr[i,j]; так как мы работаем под уп-}

   {равлением оператора  withgr[i,j], то можно пользоваться не }

   { составными именами полей }

         case k of                  {определить название предмета j }

          1:predmet:='основы информатики';

          2:predmet:='высшая математика ';

          3:predmet:='философия';

          4:predmet:='архитектураЭВМ';

          5:predmet:='историяУкраины'; end;

    if o[k,1]=2 then ifo[k,2]=2 then if o[k,3]=2 then begin

  writeln('студент ',fio,' группы ',namb,' подлежит отчислению так как');

    writeln('имеет три двойки попредмету ',predmet);

    v:=1; readln; goto w;end                       { на новый предмет }

    else Beginkol_dvoek:=kol_dvoek+2; goto w; end

    else Beginkol_dvoek:=kol_dvoek+1; goto w; end;

  w:   end;

    if v=1 then gotou                             { кновомустуденту}

        else ifkol_dvoek=0 then goto u

    else Begin

    writeln('студент ',fio,' группы',namb,' является разгильдяем так как');

    writeln('имеет в зимнюю сессию',kol_dvoek,' двоек и является');

    writeln('кандидатом на отчислениев весеннем семестре');

      readln;  end; end;

   u: end;  END.

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

9.1.Комплексные данные

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

      Program Prim45;

   Type  complex=record

         deistv:real; mnim:real; 

end;

    Var   a,b,c:complex;

       BEGIN

          a.deistv:=6.3;

          a.mnim:=1.9;    END.


 

/> /> /> /> /> /> /> /> <td/>

Рис. 9.1

   

9.2.Запись с вариантами

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

ТУРЕ

        zap=record

                описание безвариантных полей;

        Case имя поля: тип имени поля of

            список констант выбора: (поле,… тип);…

            список констант выбора: (поле,… тип);

end;

Пример:

Туреzap=record

Nomer:byte;                       {фиксированные поля}

Articul: integer;

Case Flag: boolean of      {вариантныеполя}

      TRUE: (cena l: integer);

      FALSE: (cena 2; real);

end;

Var P, Si Zap;

полеCena l доступно только тогда, когда Flag=TRUE

полеCena 2 доступно только тогда, когда Flag=FALSE

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

-         всеимена полей должны отличаться друг от друга, даже если они встречаются вразличных вариантах;

-         записьможет иметь только одну вариантную часть, причем вариантная часть должнаразмещаться в конце её;

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

списокконстант выбора: ( );

        ProgramPrim46;

   Type zap=record

             nomer:byte;

             artikul:integer;

          case flag:boolean of

             true:(cena1:integer);

             false:(cena2:real); end;

   Var h,s:zap;

 BEGIN  with h do

   Begin nomer:=1; artikul:=2345; flag:=true; cena1:=25;

     writeln('nomer=',nomer,' artikul=',artikul,' cena1=',cena1);

         flag:=false; cena2:=3.2;

     writeln('cena2 ',cena2);

      end; readln;END.


10.Файлы

 

10.1. Общие замечания

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

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

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

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

Каждыйфайл имеет свое имя, которое зарегистрировано в соответствующей директории(оглавлении).

Определениефайлового типа строится по такой схеме:

Туреимя типа=file of тип компонент;

Varидентификатор,.., идентификатор: имя типа;

Например:

Туреzap=record

Nom: integer;

FIO: string [20];

oklad: real; end;

Ft=file of zap;

Var a, b, с:Ft;

Описанытри файла с именами а, bтипа Ft. Компонентами файлов служат записи типа zap. Другимисловами, файл схематично можно представить в виде «ленты» компонент, каждая изкоторых является записью типа zap. Доступ к компонентам файла может бытьпоследовательным и прямым. Последовательный доступ – это когда для обращения к n-йкомпоненте необходимо «посмотреть» n-1компонент; прямой доступ – обращение к компоненте идет прямо по «ключу» (номерукомпоненты), без «просмотра» предыдущих компонент.

Приработе с файлом «внимание» машины сосредоточено на компоненте, определеннойуказателем файла (этой компонентой будет работать машина при следующем обращениик файлу).

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

Каждыйдиск, содержащий файлы, имеет оглавление, в которое помещается информация о егоимени, расширении, времени и дате его создания, о местонахождении на физическомносителе (например, на диске С или D).

Дляпоиска файла необходимо указать диск, каталог, подкаталог, имя файла, егорасширения.

Например:C:\TURBO\Prim\Prim46.pas.

Здесьфайл Prim 46.pas находится в подкаталоге Prim каталога TURBOдиска С.

 

10.2. Стандартные процедуры ифункции для работы с файлами

Далеепримем обозначения: FV — имя файловой переменной или просто имя файла, str — строковое выражение, Р — имя структурной компоненты файла, n — целое выражение.

Assigи (FV, str); – процедура присвоения имени файла.

Имяфайла, которое является значением str, присваивается переменнойфайлового типа FV. Далее все действия над этой переменной будут эквивалентныдействиям над файлом, определенным именем str. Например: Assign(books, 'c:\bibl.dos'); позволяет работать не с именем 'c:\bibl.dos',которое может быть достаточно длинным (если имеются каталоги и подкаталоги), ас именем books.

Rewrite(FV); – процедура создания нового файла с именем FVна диске. Имя файла должно быть предварительно определено процедурой Assign.Если на диске уже был файл с таким именем, то он уничтожается. Указатель файлаустанавливается в первую позицию с номером 0. Файл еще не содержит ни однойкомпоненты, а только подготовлен к загрузке.

Reset(FV); – процедура открытия (разрешение работать с файломименем FV) уже имеющегося файла. Указатель устанавливается на начало файла,в позицию с номером 0.

Read(FV, Р); – процедура чтения компоненты файла, на которую установленуказатель, ее содержимое помещено в область памяти с именем Р.

Write(FV, Р); – процедура записи информации из области памяти Рв файл FV и компоненту, на которую установлен указатель.

Seek(FV, n);– процедура установки указателей на компоненту с номером n.

Flush (FV);– очищение буфера сектора. Выполнение процедуры приводит к выталкиваниюсодержимого внутреннего буфера (области памяти) в файл.

Close(FV); – процедура закрытия файла, при этом записываетсямаркер конца файла. После работы с файлом его необходимо обязательно закрыть.

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

Rename(FV, str); – процедура переименования файла. Файлу FVприсваивается имя str.

Truncate(FV); – процедура уничтожения всех компонент файла, начинаяс места текущего положения указателя и подготовки файла к записи.

Eof(FV)– функция проверки маркера конца файла. Значение функции равно True,если указатель файла находится за последней компонентой, и False – впротивном случае.

Filepos(FV)– функция определения положения указателя.

Filesize(FV)– функция определения длины файла. Функция возвращает целочисленное значение,равное количеству компонент файла: если File Size (FV) = 0, тофайл пуст.

Loresult(FV)– функция проверки результата последней операции ввода- вывода на наличиеошибок. Если ошибка обнаружена, возвращается код ошибки, если нет, то код = 0.

 

10. 3. Стандартные файлы

 

Con: – консоль (клавиатураили экран дисплея). Турбо-Паскаль устанавливает различия между этимиустройствами по направлению передачи данных: чтение данных возможно только склавиатуры, а запись — только на экран. Ввод с клавиатуры буферизуется: символыпо мере нажатия клавиш помещаются в буфер, содержимое которого передается в ЭВМтолько после нажатия клавиши ENTER, поскольку вводимые и буферизированныесимволы отображаются на экране. Conприменяется «по умолчанию» для ввода с помощью операторов READ и Readlnи для вывода на экран – операторов write и writeln, если неуказано имя файла FV.

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

Trm: – терминал,предназначенный для ввода с клавиатуры и вывода на экран без редактирования.

Kbd:– клавиатура, используемая только для ввода с клавиатуры, при вводе информацияне отображается на экран.

PRN:– построчно печатающее устройство (принтер), используемое только для вывода.

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

Usr:– устройство пользователя, применяемое при написании собственных драйверов дляорганизации нестандартного ввода-вывода.

10.4.Файлы последовательного доступа, созданные пользователем

Работас файлом последовательного доступа предполагает его создание, обработку икорректировку. Для создания файла последовательного доступа необходимо:

-         объявитьфайловую переменную;

-         «привязать»файл к физическому носителю информации (присвоить файлу имя). (Assign);

-         открытьновый файл (Rewrite);

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

-         записатьв файл компоненту (Write);

-         повторитьп. 4, 5 необходимое количество раз;

-         закрытьсозданный файл (Close).

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

-         присвоитьфайлу имя (Assign);

-         открытьуже существующий файл (Reset);

-         считатьтекущую компоненту из файла в рабочую область памяти (как правило, типа записьсо структурой компоненты), (Read);

-         выполнитьобработку информации (например, вывести на экран поля записи);

-         закрытьфайл (Close).

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

1.Расширение файла за счет внесения новых компонент.

2.Полная замена содержимого компоненты.

3.Замена каких-либо полей отдельных компонент.

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

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

Длязаписи новых компонент в конце имеющегося файла необходимо:

-         присвоитьфайлу имя (Assign);

-         открытьуже существующий файл (Reset);

-         установитьуказатель файла за последней компонентой (Seek (FV, File sise (FV)):

-         создатьв специально выделенной области памяти (как правило записи) новую компоненту;

-         записатьновую компоненту в файл (write);

-         закрытьфайл (Close).

Пример.Организовать последовательный файл с именем PRIM bibl.dos в подкаталоге Primкаталога TURBO на диске С, т.е. C:\TURBO\bibl.dos.Компонента должна иметь структуру: индекс книги, порядковый номер экземпляра,фамилию, инициалы первых трех авторов (если их несколько), название книги. Блоксоздания файла оформить в виде процедуры с именем org. Блок доступа ккомпонентам файла оформить в виде процедуры с именем obr., а блоккорректировки – в виде процедуры с именем Rash.

            Program Prim47;

    type books=record              {базоваязапись}

           nomer:integer;

           avtor:string[16];

           nazv:string[30];

           index:integer;     end;

      var bf:file of books;       { описатьфайловуюпеременную}

           rb:books;              { участок памяти со структурой }

                                  { компонентыфайла}

   procedure org;

        begin  assign(bf,'C:\TURBO\PRIM\bibl.dos');

               Rewrite(bf);

         with rb do          { работать с записью rb без уточненных имен }

         while True do

        begin   writeln('ввестиномеркниги');

                   readln(nomer);

             ifnomer=9999then {9999 – признак окончания ввода данных}

              Begin  close(bf);  Exit end;

                   writeln('ввестиимяавтора');

                   readln(avtor);

                   writeln('ввестиназвание книги');

                  readln(nazv);

                  writeln('ввести значение индекса');

                  readln(index);

                  write(bf,rb); { записать компоненту из rb в файл }

       end; end;

    procedure Obr;

       Begin  Assign(bf,'C:\TURBO\PRIM\bibl.dos');

             Reset(bf);

             with rb do

             while not Eof(bf) do{ выйтиизцикла,когдазакончитсяфайл}

         begin read(bf,rb);

            writeln(nomer:5,avtor:16,Nazv:10,index:6); { выводнаэкран}

        end; Close(bf);  end;

    procedure Rash;

       begin Assign(bf,'C:\TURBO\PRIM\bibl.dos');

             Reset(bf);

            Seek(bf,Filesize(bf)); { установить указатель на конец файла }

            with rb do

             while True do

         begin writeln('ввестиномер');         readln(nomer);

             if nomer=9999 then beginClose(bf);Exit end;

             writeln('ввестиимяавтора');      readln(avtor);

             writeln('ввестиназвание книги');   readln(nazv);

            writeln('ввести значение индекса'); readln(index);

            write(bf,rb); end;end;

    BEGIN                              {основнаяпрограмма}

             Org; Obr; Rash; Obr; readln;

    END.

Присоздании больших программ их части удобно создавать в виде отдельных файлов(объектов), которые затем с помощью директивы компилятора {$i...} можно объединитьв одну программу. Это удобно еще и тем, что несколько программистов могутсоздавать различные программы, что в несколько раз может ускорить процесс ихсоздания.

Создадимту же программу, что и Prim 47, только пообъектно, тогда процедуру Orgзапишем в C:\TURBO\Org1.pas, процедуру Obr – в C:\TURBO\Orb1.pas,процедуру Rash – в C:\TURBO\Rash1.pas, а вызывающую (основную программу– в C:\TURBO\Prim. 48, в которой предусмотрим подключение объектов –процедур Org, Obr, Rash к основной программе через директивы компилятора$i.

  procedure Org1;

     begin

       assign(bf,'C:\TURBO\bibl.dos');

               Rewrite(bf);

          with rb do

          while True do

        begin  writeln('ввестиномер книги');

                  readln(nomer);

                   if nomer=9999 then

               begin  close(bf);  Exit;

               end;

                  writeln('ввести имя автора');

                  readln(avtor);

                  writeln('ввести название книги');

                  readln(nazv);

                  writeln('ввести название индекса');

                  readln(index);

                   write(bf,rb);

         end;

    end;

  procedure Obr1;

    begin 

             Assign(bf,'C:\TURBO\bibl.dos');

             Reset(bf);

     with rb do

             while not eof(bf) do

        Begin read(bf,rb);

             writeln(nomer:5,avtor:16,Nazv:10,index:6);

        end;

             Close(bf);

          writeln('нажмитеenter'); readln;

    end;

procedure Rash1;

       begin Assign(bf,'C:\TURBO\bibl.dos');

             Reset(bf);

             Seek(bf,Filesize(bf));

             with rb do

             while True do

        begin writeln('введитеномер');readln(nomer);

             if nomer=9999 then beginClose(bf);exit end;

             writeln('введитеимяавтора');      readln(avtor);

             writeln('введитеназвание книги');   readln(nazv);

            writeln('введите значение индекса'); readln(index);

            write(bf,rb);

        end;end;

Работупостроим в режиме меню.

Program Prim48;

     label M;

     type books=record     

           nomer:integer;

           avtor:string[16];

           nazv:string[30];

           index:integer;     end;

      Var  bf:file of books;

           rb:books;  regim:byte;

      {$i C:\TURBO\Org1.pas}

      {$i C:\TURBO\Obr1.pas}

      {$i C:\TURBO\Rash1.pas}

   BEGIN 

      M: writeln('введите режим работы');

          writeln('1 – создание, 2 – обработка',

                  '3 – расширение, 4 – выход');

          readln(regim);

           case regim of

        1:Org1;

        2:Obr1;

        3:Rash1;

        4:Exit;  else writeln('неправильнозаданрежим');end;

                gotoM;              

   END.

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

Program Prim49;

      label M1,M2 ;

    type books=record     

           nomer:integer;

           avtor:string[16];

           nazv:string[30];

           index:integer;     end;

      Var  bf:file of books;

           rb:books;  regim:byte;si:char; fl:string;

      {$i C:\TURBO\Org.pas}

      {$i C:\TURBO\Obr.pas}

      {$i C:\TURBO\Rash.pas}

   BEGIN

         M1: writeln('где будет храниться файл? диск:\каталог\имя'),

             readln(fl);

         M2: writeln('введите режим работы');

             writeln('1 – создание, 2 – обработка',

                  '3 – расширение, 4 – выход');

             readln(regim);

           case regim of

        1:Org;

        2:Obr;

        3:Rash;

        4:begin writeln('будемещёработатьсфайлами? — «Y»');

                writeln('иликонец работы – любая клавиша');

               readln(si);

                if (si='Y')or(si='y')then goto M1 else HALT; end;

          elsebegin writeln('неправильно задан режим');

               goto M2; end; end; goto M2;

    END.

Procedure Org2;

     begin

       assign(bf, fl);

               Rewrite(bf);

          with rb do

          while True do

        begin  writeln('введитеномер книги');

                  readln(nomer);

                   if nomer=9999 then

               begin  close(bf);  Exitend;

                   writeln('введитеимяавтора');

                   readln(avtor);

                   writeln('введитеназвание книги');

                  readln(nazv);

                  writeln('введите значение индекса');

                  readln(index);

                  write(bf,rb);

        end; end;

Procedure Obr2;

    begin 

             Assign(bf, fl);

             Reset(bf);

     with rb do

             while not Eof(bf) do

        begin read(bf, rb);

            writeln(nomer:5,avtor:16,Nazv:10,index:6);

        end; Close(bf);

end;

Procedure Rash2;

       begin assign(bf, fl);

             Reset(bf);

             Seek(bf,Filesize(bf));

             with rb do

             while True do

        begin writeln('введитеномер');readln(nomer);

             if nomer=9999 then beginClose(bf);Exit end;

             writeln('введитеимяавтора');      readln(avtor);

             writeln('введитеназвание книги');   readln(nazv);

            writeln('введите значение индекса'); readln(index);

            write(bf,rb);

        end;end;

 

10.5. Файлы произвольного доступа

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

Организоватьфайл произвольного доступа можно двумя способами:

1.        Создатьпоследовательный файл и обращаться к компонентам по порядковому номеру, трактуяпоследовательный файл как файл прямого доступа.

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

Пример.Форматировать файл произвольного доступа из 20 компонент c:\turbo\bibl.dos.Структура компонент такая же, как и в Prim 47–49. Оформим алгоритм в виде процедурыform, запишем ее в c:\turbo\form.pas.

Procedureform;

Beginwriteln('дайтеимя форматизируемому файлу');

readln(filname);

assign(booksfile, filname);

rewrite(booksfile);

          with recbooks do

 Beginwriteln('насколькозаписейформатироватьфайл?');

readln(razmer);

 for i:=l to razmer do

Begin nomer:=i; avtor:=' '; index:=0;nazv:=' ';

write ( books file, recbooks)

end; end; writeln(фopматизация',razmer,' записьвыполнена');

           close(booksflle);end;

Напишемпроцедуру загрузки (procedure zagruz), которая будет заменять поляфиктивных записей реальными значениями, и запишем ее в c:\turbo\zagruz.pas;

  procedure zagruz;      Begin writeln('дать имя загружаемого по ключу файла');

             readln(filname);

             assign(booksfile,filname);  reset(booksfile);

             writeln('сколько записей будете вводить?');readln(k);

             with recbooks do

       Begin for i:=1 to k do

       Begin writeln('введитеномер');  readln(nomer);

             writeln('введитеимяавтора');     readln(avtor);

             writeln('введите название книги');  readln(nazv);

             writeln('введитеиндекс');         readln(index);

         seek(booksfile,nomer-1);    { номера компонент начинаются с 0 }

             write(booksfile,recbooks); end; end;

             close(booksfile);end;

Оформитьпроцедуру прямого доступа по ключу к компонентам файла и выдачу их на экранмонитора, записать ее в C:\TURBO\OBRAB.PAS;

Procedure Obrab;

     Begin writeln('дайтеимяфайла'); readln(filname);

           assign(booksfile,filname); reset(booksfile);

           while true do

       Begin writeln('укажитеключобрабатываемойзаписи');readln(k);

           if k=9999 then Beginclose(booksfile); exit; end;

           seek(booksfile,k-1);

           with recbooks do Beginread(booksfile,recbooks);

          writeln(nomer:5,avtor:16,nazv:15,index:4);

           end;end;end;

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

1.        Заменавсех полей компоненты.

2.        Расширениефайла в пределах отформатированного пространства.

всеэто делает процедура Кооr,записанная в c:\turbo\koor.pas.

  Procedure Koor;   

 Var  nevavtor:string[16];nevnazv:string[30]; nevindex:integer;   

Begin writeln('дайтеимяфайла');readln(filname);   

      assign(booksfile,filname);reset(booksfile);    

     withrecbooksdo

  Begin writeln('сколько записей будете корректировать?'); readln(k);

         for i:=1 to k do

  Begin writeln('дайтеномеркорректируемойзаписи');readln(k1);

        nevavtor:=' '; nevnazv:=' ';nevindex:=0;

        writeln('введитеимяавтора');     readln(nevavtor);

        writeln('введите название книги');  readln(nevnazv);

        writeln('введитеиндекс');         readln(nevindex);

        avtor:=nevavtor; nazv:=nevnazv;  index:=nevindex;

      seek(booksfile,k1-1);  write(booksfile,recbooks);

   end; end; close(booksfile); end;

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

             Program Prim50;

      Type books=record

           nomer:integer;       avtor:string[16];

           nazv:string[30];      index:integer;    end;

      Var  booksfile:file of books;

           recbooks:books;      razmer,k,k1,i,reg:integer;

           filname:string[12];

          {$i c:\turbo\form.pas}

          {$i c:\turbo\zagruz.pas}

          {$i c:\turbo\obrab.pas}

          {$i c:\turbo\koor.pas}

   Begin      while true do

        Begin writeln('укажитережим');

              writeln('1:форматизация');

             writeln('2: загрузка по ключу');

             writeln('3: обработка по ключу');

             writeln('4: корректировка');

             writeln('5: выход из программы');

             readln(reg);

              case reg of 1:form;2:zagruz; 3:obrab; 4:koor; 5:halt;

   end;

end;

 end.

10.6.Текстовые файлы

Компонентамитекстовых файлов являются строки. Длина строки – 0-255 символов. Каждая строказавершается маркером строки, а файл – маркером конца файла. Для описанияфайловых переменных текстового типа используется зарезервированное слово text.

Var instrl, instr2: text;

dokulnent: text;

Дляработы с текстовыми файлами используются упомянутые выше функции и процедуры assign,rewrite,reset,close,read,readln,write,writeln,seekeof,однако имеются и специфические функции и процедуры:

Append(fv)– открыть текстовый файл и установить указатель на маркер конца файла.

Eoln(fv)– возвратить true, если указатель файла достиг маркера конца строки, впротивном случае, возвратить значения false.

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

Seekeof(fv)– возвращает true, если указатель файла находится на маркере конца файла.

Организациятекстового файла производится по схеме:

1)объявляется файловая переменная текстового типа;

2)присваивается файлу имя (assign);

3)открывается файл (rewrite);

4)подготавливается строка — компонента для записи в файл;

5)записывается строка — компонента в файл (writeln);

6)повторяются п. 4, 5 столько раз, сколько нужно;

7)закрывается файл.

Доступк компонентам текстового файла:

1)присвоить файлу имя (assign);

2)открыть файл для чтения (reset);

3)прочитать компоненту-строку (readln);

4)обработать компоненту-строку (например вывести на экран);

5)повторить п. 3, 4 столько раз, сколько нужно.

6)закрыть файл (close);

Расширениетекстового файла производится путем добавления в конец файла компонент-строк:

1)присвоить имя файлу (assign);

2)установить маркер на конец файла (append);

3)подготовить строку для записи;

4)записать строку (writeln);

5)повторить нужное количество раз п. 3, 4.

6)закрыть файл (close).

Замечание.При записи файлов прямого и последовательного доступа, созданных пользователем,содержимое компонент упаковывается, и поэтому посмотреть их в vc или nc по f3или f4 нельзя, а текстовый файл не упаковывается, и его можно просмотреть.

 proceduresozdt;

  Begin  writeln('дайте имя создаваемому текстовому файлу');

         readln(filename);

        assign(stro,filename);    rewrite(stro);

          while true do

    Begin  writeln('напишитесодержимоестроки');

           readln(s); if s='zzz'then     {'zzz' – признакокончанияввода}

      Begin  close(stro); exit; end;

          writeln(stro,s); end;end;  

     procedure obrt;

  Begin writeln('дайтеимяобрабатываемогофайла');

; readln(filename);

        assign(stro,filename); reset(stro);

        repeat readln(stro,s);  writeln(s);

              until seekeof(stro); close(stro); exit; end;

     procedure rasht;

 Beginwriteln('укажитеимякорректируемогофайла');readln(filename);

         assign(stro,filename);   append(stro);

         while true do

   Begin writeln('введитестроку'); readln(s);

         if s='zzz' then Begin close(stro); exit; end;

         writeln(stro,s);  end; end;

       Program Prim51;

    Type  dlina=string[60];

    Var   stro:text;   s:dlina;   reg:char;   filename:string[12];

       {$i c:\turbo\sozdt.pas}

       {$i c:\turbo\obrt.pas}

       {$i c:\turbo\rasht.pas}

   Begin    while true do

    Begin   writeln('укажитережим');

      writeln('1: создание, 2: вывод на экран, 3:расширение, 4: выход');

      readln(reg);

         case reg of '1': sozdt;

                     '2': obrt;

                     '3': rasht;

                    '4': halt  else writeln('повторитеномеррежима');

      end;end;end.


11.Использование библиотеки CRT

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

 

11.1. Программирование клавиатуры

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

Функцияkeypressed возвращает значение типа boolean,указывающее состояние буфера клавиатуры: false означает, что буфер пуст,а true – что в буфере есть хотя бы один символ, еще не прочитанныйпрограммой.

В      реализуется так называемый асинхронный буферизованный ввод с клавиатуры.По мере нажатия на клавиши соответствующие коды помещаются в особый буфер,откуда они могут быть затем прочитаны программой. Стандартная длина буферарассчитана на хранение до 16 кодов символов. Если программа достаточно долго необращается к клавиатуре, а пользователь нажимает клавиши, буфер может оказатьсяпереполненным. В этот момент раздается звуковой сигнал и «лишние» кодытеряются. Чтение из буфера обеспечивается процедурами read/rеadln ифункцией ReadKey. обращение к функции keypressed не задерживаетисполнения программы: функция немедленно анализирует буфер и возвращает то илииное значение, не дожидаясь нажатия клавиши.

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

UsesCRT;

Var

с;char;

Begin

    while Keypressed do

c:== ReadKey;

.… .

end.

Прииспользовании процедуры ReadKey следует учесть, что в клавиатурный буферпомещаются так называемые расширенные коды нажатых клавиш. Если нажимается любаяалфавитно-цифровая клавиша, расширенный код совпадает с ASCII-кодомсоответствующего символа. Например, если нажимается клавиша с латинской буквой«а» (в нижнем регистре), функция ReadKey возвращает значение chr(97),а если – «а» (в верхнем регистре) – значение chr(65). При нажатиифункциональных клавиш F1...F10(клавиш управления курсором), клавиш Ins,Home, Del, End, PgUp, PgDn в буфер помещается двухбайтоваяпоследовательность: сначала символ #0, а затем расширенный код клавиши.Таким образом, значение #0, возвращаемое функцией ReadKey, используетсяисключительно для того, чтобы указать программе на генерацию расширенного кода.Получив это значение, программа должна еще раз обратиться к функции, чтобыпрочитать расширенный код клавиши.

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

UsesCRT;

Var с:char;

Begin

   repeat

c:= ReadKey;

if c< >#0 then

             writeln (ord(c))

else

writeln ('0', ord (ReadKey):8)

  until c=#27 {27 –расширенный код клавиши esc}

end.

Есливы воспользуетесь этой программой, то обнаружите, что нажатие на некоторыеклавиши игнорируется функцией ReadKey. Это прежде всего так называемыесдвиговые клавиши – Shift, Ctrl, Alt. Сдвиговые клавиши в MS-DOS обычноиспользуются для переключения регистров клавиатуры и нажимаются в сочетании сдругими клавишами. Именно таким способом, например, различается ввод прописныхи строчных букв. Кроме того, функция игнорирует переключающие клавиши CapsLock, NumLock, ScrollLock.

втаблице приведены расширенные коды клавиш, возвращаемые функцией ord(ReadKey).


Расширенные коды клавиш

Таблица

Код

Клавиша или комбинация клавиш

Код

Клавиша или комбинация клавиш

первый байт

второй байт

первый байт

второй байт

Алфавитно-цифровые клавиши 8 – backspace (забой) 9 – tab (табуляция) 13 – enter 32 – пробел 33 – ! 34 – « 35 – # 36 – $ 37 – % 38 – & 39 – " 40 – ( 41 – ) 42 – * 43 – + 44 – , 45 – – 46 – . 47 – / 48...57 – 0...9 58 – : 59 – ; 60 – <  61 – = 52 – >  63 – ? 64 – @ 65...90 – A...Z 91 – [ 92 – / 93 – ] 94 – ^ 95 –

_

96 – " 97...122 – a...z 123 – { 124 – ?? 125 – } 126 – ~ 128...159 – A… Я 160...175 – а… п 224...239 – р… я Управляющие клавиши и их сочетания со сдвиговыми 3 Ctrl–2 15 Shift – Tab 16...25 Alt–Q...Alt–P (верхний ряд букв) 30...38 Alt–A...Alt–L (средний ряд букв) 44...50 Alt–Z...Alt–M (нижний ряд букв)

59...68

72

F1...F10

курсор вверх

71 Home 75 курсор влево 73 PgUp 79 End 77 курсор вправо 81 PgDn 80 курсор вниз 83 Del /> /> /> /> /> /> /> /> /> /> /> /> /> окончаниетаблицы

код

клавиша или комбинация клавиш

код

клавиша или комбинация клавиш

первый байт

второй байт

первый байт

второй байт

82 Ins 94...103 Ctrl–F1...Ctrl–F10 84...93 Shift–F1… Shift–F10 114 Ctrl– PrtScr 104...113 Alt–F1...Alt–F10 116 Ctrl – курсор вправо 115 Ctrl – курсор влево 118 Ctrl – PgDn 117 Ctrl – End 120...131 alt–1...alt– = (верхний ряд клавиш) 119 Ctrl – Home 132 Ctrl – PgUp

 

11.2. Текстовый вывод на экран

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

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

ProcedureTextMode(mode:word);

Здесьmode – код текстового режима. в качестве значения этого выражения могутиспользоваться следующие константы, определенные в модуле CRT:

const

bw40=0;{черно-белый режим 40*25}

co40=l;{цветной режим 40*25}

bw80=2,{черно-белый режим 80*25}

co80=3;{цветной режим 80*25}

mono=7;{используется с mda}

Font8*8=256;{используется для загружаемого шрифта в режиме 80*43 или 80*50 с адаптерами EGAили VGA}

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

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

  user CRT;

procedureprint (s: string), {вывести сообщение s и ждать инициативы пользователя}

Begin

writeln(s), {вывести сообщение}

writeln('нажать клавишу enter...');

readln{ждем нажатия клавиши enter}

end;{print}

Var

lm:word, {начальный режим экрана}

Begin

lm:=LastMode;{запомнить начальный режим работы дисплея}

TextMode (со40);

print ('режим40*25');

TextMode (co8o);

print ('режим80*25');

TextMode (co40+font8*8);

print ('режимco40+font8*8');

TextMode(co80+font8*8);

print('режим co80+font8*8'), {восстановить исходный режим работы:}  

TextMode(lm)

end.

ПроцедураTextColor определяет цвет выводимых символов. заголовокпроцедуры:

ProcedureTextColor(color:byte);

ПроцедураTextBackGround определяет цвет фона. заголовок процедуры:

ProcedureTextBackGround(color:byte);

Единственнымпараметром обращения к этим процедурам должно быть выражение типа byte, задающеекод нужного цвета. Этот код удобно определять с помощью следующих мнемоническихконстант, объявленных в модуле CRT:

const

black=0;{черный}

blue=l;{темно-синий}

green=2;{темно-зеленый}

суаn=3;{ бирюзовый}

red=4;{красный}

magenta=8;{фиолетовый}

brown=6;{коричневый}

lightgray=7;{светло-серый}

darkgray=8;{темно-серый}

   lightblue=9;{синий}

   lightgreen=10;{светло-зеленый}

lightcyan=11;{светло-бирюзовый}

lightred=12;{розовый}

lightmagenta=13;{малиновый}

yellow=14;{желтый}

white=15;{белый}

blink=128;{мерцание символа}

Следующаяпрограмма иллюстрирует цветовые возможности Турбо-Паскаля.

uses CRT,

const

col: array [1..15] of string [16] =

('темно-синий','темно-зеленый','бирюзовый','красный','фиолетовый','коричневый','светло-серый','темно-серый','синий','зеленый','светло-бирюзовый','розовый','малиновый','желтый','белый');

Var

k: byte,

Begin

for k:=l to 15 do

Begin{выводим 15 сообщений различными цветами}

textcolor (k),

writeln ("цвет",k, "-", col [k] )

end;

textcolor (white+blink); {белыемигающиесимволы}

writeln(«мерцание символов»);

{восстанавливаемстандартный цвет}

textcolor(lightgray),

writeln

end.

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

TextColor(lightgray);

Делов том, что все цветовые определения предварительно заносятся в специальнуюпеременную TextAttr модуля CRT и используются для настройкиадаптера только при обращении к процедурам write/writeln.

ПроцедураClrScr очищает экран или окно (см. нижепроцедуру window). после обращения к ней экран (окно) заполняется цветомфона и курсор устанавливается в его левый верхний угол. например:

uses CRT;

Var

с:char

Begin

textbackground (red);

clrscr; {заполняемэкранкраснымцветом}

writeln ("нажмителюбуюклавишу...");

с:=ReadKey, {ждемнажатиялюбойклавиши}

textbackground (black);

clrscr {восстанавливаемчерныйфонэкрана}

end.

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

ProcedureWindow(xi, yi,х2, y2: byte);

Здесьx1...y2 – координаты левого верхнего (х1, y1) и правого нижнего (х2,y2) углов окна. Они задаются в координатах экрана, причем левый верхнийугол экрана имеет координаты (1,1), горизонтальная координата увеличиваетсяслева направо, а вертикальная – сверху вниз.

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

uses CRT;

Var

     k: integer;

Begin{создать левое окно – желтые символы на синем фоне:}

textbackground (blue);

window (5, 2, 35, 17);

textcolor (yellow);

for k:= i to 100 do

write ("нажатьклавишуenter… ");

      readln, {ждемнажатияenter}

      clrscr; {очищаемокно}

{создатьправое окно – белые символы на красном фоне:}

textbackground (red);

textcolor (white);

window (40, 2, 70, 17);

for k:= i to 100 do

write ("нажатьклавишуenter… ");

     readln;

    TextMode (Co8o) {сбросить все установки}

end.

Обращениек процедуре Window игнорируется, если какая-либо из координат выходит заграницы экрана или если нарушается одно из условий: Х2>Х1 или Y2>Y1. Каждоеновое обращение к Window отменяет предыдущее определение окна. Границы текущегоокна запоминаются в двух глобальных переменных модулях CRT: переменная WindMinтипа Word хранит X1 и Y1 (Х1 – в младшем байте), а переменная того же типаWindMax – Х2 и Y2 (Х2 – в младшем байте). При желании вы можете изменять их нужнымобразом без обращения к Window. например, вместо оператора

Window(40, 2, 70,17);

можнобыло бы использовать два оператора:

WindMin:=39+(lshl8);WindMax:=69+(16 shl8);

(вотличие от обращения к Window,координаты, хранящиеся в переменных WindMinи WindMax, соответствуют началу отсчета 0, 0).

ПроцедураGotoXY переводит курсор в нужное место экранаили текущего окна. Заголовок процедуры:

ProcedureGotoXY(Х, Y: Byte);

ЗдесьX, Y — новые координаты курсора. Координаты задаются относительно границ экрана(окна), т.е. оператор

GotoXY(1,1);

Операторуказывает, перевести курсор в левый верхний угол экрана (или окна, если к этомумоменту на экране определено окно). Обращение к процедуре игнорируется, еслиновые координаты выходят за границы экрана (окна).

ФункцииWhereX и WhereY. С помощью этихфункций типа Byte можно определить текущие координаты курсора: WhereXвозвращает его горизонтальную, а WhereY – вертикальную координаты.

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

ProgramPrim52;

    Uses CRT;      {подключить библиотеку (модуль) CRT}

Const           { константы, определяющие графические символы }

                { необходимые для вычерчивания рамки окна }

     lu=#218;                     { левый верхний угол рамки }

ru=#191;                    { правый верхний угол рамки }

         ld=#192;                     { левый нижний угол рамки }

         rd=#217;                     { правый нижний угол рамки }

         h=#196;                     { горизонтальная черта }

         v=#179;                     { вертикальная черта }

                { координаты окна: }

x1=14;y1=5;                 { верхний левый угол }

         x2=66; y2=20;                { нижний правый угол }

Vark:integer;

BeginClrScr;                     { очиститъ экран}

     textmode(co80);              { сброситъ все установки }

     textbackground(lightcyan);   { фон окна светло-бирюзовый }

     textcolor(yellow);           { цвет текстов в окне желтый }

     window(x1,y1,x2,y2);         { открытъ окно с координатами }

     ClrScr;

                                  { рисуем рамку вокруг окна}

Write(lu);                  { левый верхний угол }

  for k:=x1+1 to x2-1 do

     write(h);                    { верхнююгоризонтальную черту }

     write(ru);                   { правый верхний угол }

  for k:=y1+1 to y2-1 do          { рисуем вертикальные линии }

           { посимвольно слева и справа и построчно за счет цикла} 

BeginGotoXY(1,k-y1+1);           { курсор на левую границу }

      write(v);                   { вывести вертикальную черточку }

      GotoXY(x2-x1+1,whereY);     { курсор на правую границу }

      write(v);                   { вывести вертикальную черточку }

                 { перейти на новую строку, пока не кончится цикл }

 end;

      write(ld);                  { левый нижний угол }

      Window(x1,y1,x2,y2+1);

       GotoXY(2,y2-y1+1);          {kypcop внижнийлевыйугол+1}

{нового окна, без учета рамки }

  for k:=x1+1 to x2-1 do write(h);{ нижнююгоризонтальную черту}

      write(rd);                  { нижний правый угол}

TextBackground(LightCyan);

      GotoXY(2,2);                { курсор в левый верхний угол}

                                  {нового окна без учета рамки}

       readln;

     end.

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

ПроцедураClrEOL стирает часть строки от текущегоположения курсора до правой границы окна (экрана). Положение курсора неменяется.

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

ПроцедураInsLine вставляет строку: строка с курсором ивсе строки ниже ее сдвигаются вниз на одну строку; строка, вышедшая за нижнююграницу окна (экрана), безвозвратно теряется; текущее положение курсора неменяется.

ПроцедурыLowVideo,NormVideoиHighVideo.Спомощью этих процедур без параметров можно устанавливать соответственнопониженную, нормальную и повышенную яркости символов. Например:

UsesCRT;

begin

LowVideo;

                   Writeln('пониженная яркость');

                   NormVideo;

                   Writeln('нормальная яркость');

                   HighVideo;

                   Writeln('повышенная яркость')

end.

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

ПроцедураAssign CRTсвязывает текстовую файловую переменную F с экраном с помощью непосредственногообращения к видеопамяти (т.е. к памяти, используемой адаптером для созданияизображения на экране). В результате вывод в такой текстовый файлосуществляется значительно  быстрее (в 3...5 раз), чем если бы этот файл былсвязан с экраном стандартной процедурой Assign. Заголовок процедуры: ProcedureAssign CRT (F: Text);

Вследующей программе измеряется скорость вывода на экран с помощью стандартнойфайловой процедуры и непосредственного обращения к видеопамяти. Вначалефайловая переменная F связывается «медленной» процедурой Assignсо стандартным устройством CON (т.е. с экраном) и подсчитываетсяколичество N циклов вывода некоторого текста за 5*55=275миллисекунд системных часов. Затем файловая переменная связывается с экраном спомощью процедуры быстрого доступа Assign CRT и точно так же подсчитываетсяколичество N2 циклов вывода. В конце программы счетчики NI и N2выводятся на экран.

Показаниясистемных часов хранятся в оперативной памяти компьютера в виде четырехбайтногослова по адресу [$0040:$006С] и наращиваются на единицу каждые 55 миллисекунд.

Uses CRT;

var

                   F: Text;

                   t: Longint; {начало отсчета времени}

                   N1,N2: Word; {счетчик вывода}

const

                   txt= 'Text';

begin

                   {-----стандартныйвывод в файл------}

                   Assign (F, “CON”);

                   Rewrite (F);

                   N1:=0; {готовимсчетчиквывода}

                   ClrScr; {очищаемэкран}

                   {запоминаем начальный момент:}

                   t:= Meml[$0040:$006C];

                   {ждемначало нового 55-миллисекундного интервала, чтобы исключить погрешность вопределении времени:}

                   while Meml [$0040:$006C]=tdo;

                   {цикл вывода за 5 интервалов}

                   whileMeml[$0040:$006C]<t+6 do

                             begin

                                      inc (N1);

                                      Write (F, txt)

                             end;

                   Close(F);

          {выводс помощью быстрой процедуры прямого доступа к экрану}

                   AssignCRT (F);

                   Rewrite (F);

                   N2:=0;

                   ClrScr;

                   t:= Meml [$0040:$006C];

                   while Meml [$0040:$006]=t do;

                   while Meml [$0040:$006]<t+6 do

          begin

                             inc (N2);

                             Write (F, txt)

                   end;

                   Close (F);

                   {печатаемрезультат}

                   ClrScr;

                   Writeln (N1, N2:10)

end.

Следует учесть, что вывод на экран обычным образом, безиспользования файловой переменной (например, оператором Write (txt)),также осуществляется   с помощью непосредственного доступа к видеопамяти, поэтомуценность процедуры AssignCRT весьма сомнительна. Прямой доступ квидеопамяти регулируется глобальной логической переменной DirectVideo модуляCRT: если эта переменная имеет значение True, доступ разрешен,если False — доступ к экрану осуществляется с помощью относительно медленныхсредств операционной системы MS—DOS. По умолчанию переменная DirectVideo имеетзначение True.

 

11.3. Программирование звуковогогенератора

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

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

Процедура Sound заставляет динамик звучать с нужной частотой. заголовок процедурыProcedure Sound (F: Word); здесь F – выражениетипа Word, определяющее частоту звука в герцах. После обращения кпроцедуре включается динамик, и управление немедленно возвращается в основнуюпрограмму, в то время как динамик будет звучать впредь до вызова процедуры NoSound.

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

Процедура Delay oбеспечивает задержку работы программы на заданный интервалвремени. Заголовок процедуры: ProcedureDelay(T: Word);

Здесь Т — выражение типа Word, определяющееинтервал времени (в  миллисекундах), в течение которого задерживаетсявыполнение следующего оператора программы.

Для генерации звукового сигнала обычно используется вызов описанныхпроцедур по схеме Sound—Delay—NoSound. следующая программа заставит пквоспроизвести простую музыкальную гамму. Используемый в ней массив F содержитчастоты всех полутонов в первой октаве от «до» о «си». При переходе от однойоктавы к соседней, частоты изменяются в два раза.

Uses CRT;

const

                   F: array [1..12] of Real =

                             (130.8, 138.6, 146.8, 155.6, 164.8,174.6, 185.0, 196.0, 207.7,

                              220.0, 233.1, 246.9); {массив частот 1-й октавы}

                   Temp= 100; {темп исполнения}

var

                   k, n: integer;

begin

                   {восходящаягамма}

                   for k:=0 to 3 do

                             for n:=1 to 12 do

                                      Begin

                                                Sound (Round(F[n]*(1 shl k)));

                                                Delay (Temp);

                                                NoSound

                                      end;

                   {нисходящаягамма}

                   for k:=3 downto 0 do

                             for n:=12 downto 1 do

                                      begin

                                                Sound (Round(F[n]*(1 shl k)));

                                                Delay (Temp);

                                                NoSound

                                      end

end.

Вследующей программе перемножается матрица на вектор,основу которой составляет ранее рассмотренные Program Prim 29 i Prim 29а.Здесь максимальные размеры матрицы – 10*10 элементов типа byte.Ввод информации производится в окне светло-бирюзового цвета, вывод результатов– в окне малинового цвета, цвет букв – желтый.

Программав начале работы издает звуки частотой от 130 до 2130 Гц, затем при вводевеличины a – частотой 2000 Гц, b –1500 Гц длительностью n=100 мс. В конце работы программа издает звуки от 2130до 130 Гц. Программа использует подпрограмму Wind, написанную на основе Prim52.

 Program Prim53;  Uses CRT;  vari,j,n,m,k,l:integer; a:array[1..50,1..70] of byte;                  b:array[1..10] of byte;

                  c:array[1..10] of longint;

                  cv:byte;

     {$i C:\TURBO\ wind.pas}

 BEGIN

      Clrscr;                     {очиститьэкран}

  cv:=11;                         {цвет11, светло-бирюзовый}

 wind(1,1,50,7);                { открыть окно, обращения к процедуре}

      Sound(330);                 { включить звук, частотой 330 гц }      Delay(1000);                { задержать на 1000 миллисекунд }      NoSound;                    { выключить звук }

      writeln ('ввести количество строк и столбцов');

      GotoXY(2,3); l:=4;          {l устанавливает курсор по y}

       readln(n,m);

       for i:=1 to n do

       for j:=1 to m do

     begin GotoXY(2,l);

     writeln(' введите a[',i,',',j,'] элемент матрицы а');

     GotoXY(34,l);            { перевести курсор в конец текста:}

                              {ввести  a[i,j] – элемент матрицы'}

     ClrEol;                { удалить конец строки до границы окна}

     readln(a[i,j]);          { ввести очередное а в конце текста }

      end;

      L:=L+1;{}

        for j:=1 to m do

     begin GotoXY(2,l);

        writeln(ввестиb[',j,'] элементвектора b');

     GotoXY(33,l);

      ClrEol;

      readln(b[j]); end;

  cv:=5;                       { фиолетовый цвет длянового окна }

  wind(20,2,80,18); GotoXY(2,2);l:=3;

   for i:=1 to n do       { начало перемножения матрицы на векторы }

 begin c[i]:=0;

   for j:=1 to m do

    c[i]:=c[i]+ a[i,j]*b[j]; end;

                          { конец перемножения матрицы на вектор }

     writeln(' распечатка массива а ');

      for i:=1 to n do

         begin  GotoXY(2,l); l:=l+1;      { начатьновуюстроку}

      for j:=1 to m do

      write(a[i,j]:5); end;

    GotoXY(2,l); l:=l+1;     writeln('распечаткамассива  b');

    GotoXY(2,l);

      for j:=1 to m do

      write(' ',b[j]);    L:=L+1;

    GotoXY(2,L); L:=L+1;  writeln('результирующий массивс');

    GotoXY(2,L);

      for i:=1 to n do

      write(' ',c[i]);

    readln;     END.


12.Графика в Паскале

/> 

12.1. Инициализация графическогорежима

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

Program имя;

Uses Graph;

var

          grDriver, grMode, errCode: integer;

begin

          grDriver:=Detect;{определение номера, установленного в системе драйвера}

          initGraph(grDriver, grMode,''); {инициализация графического режима}

          iferrCode= grOKthen

          begin{ режим открыт и можно работать}

endelse

begin{графический режим не удалось открыть, проанализируйте                   содержание  переменной errCode}

end.

Замечание.Две кавычки в initGraphправомочны только тогда, когда графическая программа находится в том жекаталоге, что и библиотека Graph. В противном случае в кавычках долженстоять путь – указание, где находится библиотека Graph.


12.2.Процедуры и функции библиотеки Graph

ФункцииGetMaxX и GetMaxY возвращают значения типа Word, содержащиемаксимальные координаты, соответственно, X и Y относительно левого верхнегоугла в пикселах (точках).

Различныемониторы имеют различную разрешающую способность, например: VGA — 640´480точек, IBM 8514Hi — 1024´768 точек.

ФункцииGetX и GetY возвращают текущие координаты указателя. Процедура SetViewPort(Х1, Y1, Х2, Y2, Clipon);устанавливает прямоугольное окно на графическом экране, X1, Y1 — координаты левого верхнего угла; Х2, Y2 — координаты нижнего правогоугла окна.

Есливыражение Clipon имеет значение trueи элементы изображения не помещаются в окне, то они отсекаются, если – false,то отсечка игнорируется.

ПроцедураMoveTo (Х, Y); устанавливает новое текущее положениеуказателя.

ПроцедураMoveRel (Ox, Dy); устанавливает приращения новых координатуказателя относительно старых.

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

ПроцедураPutPixel (Х, Y, Color); выводит на экран точку Colorцвета. Процедура LineTo (Х, Y); вычерчивает линию от текущего положенияуказателя до точки Х, Y.

ПроцедураSetLineStyle (Туре,Pattern, Thick);

ГдеТуре – тип линии. Pattern – образец линии. Thick – толщиналинии.

Типлинии:

0– сплошная,

1– точечная,

2– штрихпунктирная,

3–…

4– узор линии определяет пользователь параметром pattern.

Thick=l– толщина линии в 1 пиксел.

Thick=2– толщина линии в 3 пиксела.

ПроцедураRectangle (Х1, Y1, Х2, Y2); вычерчивает прямоугольник с использованиемтекущего цвета и текущего стиля линий.

ПроцедураDrawPoly (N, Р);вычерчивает произвольную ломаную линию. N — количество точек излома,включая крайние; Р — переменная типа PointType, которая в Graphимеет вид:

type

PointType=record

X, Y: Word

end;

Привычерчивании используются текущий цвет и текущий стиль линий. Процедура Circle(Х, Y, R); вычерчивает окружность с центром X, Y и радиусом R.

ПроцедураArc (Х, Y, Beg А, End А, R); вычерчивает дугуокружности Beg А и End А, соответственно, начальный и конечный углыдуги.

ПроцедураEllipse (Х, Y, Beg А, End А, RX, RY); вычерчивает дугуэллипса с центром X, Y; Beg А, End А – начальный и конечный угол, RXи RY – горизонтальный и вертикальный радиусы.

ПроцедураBar (Х1, Y1, Х2, Y2); заполняет прямоугольную область экранаобразцом узора и текущим цветом, которые устанавливаются процедурой SetFillStyle.

ПроцедураВаr3D(Х1, Y1, Х2, Y2, Depth, Тор); вычерчивает трехмерноеизображение параллелепипеда и закрашивает его переднюю грань. Depth –глубина третьего измерения, Top=true– верхняя грань вычерчивается, false — нет.

ПроцедураFillPoly (n, Coords); обводит линией и закрашивает замкнутыймногоугольник; n – количество вершин, Coords – переменная типа PointType,содержащая координаты вершин (см. DrawPoly).

ПроцедураFillEllipse (Х, Y,Rx, Ry); обводит линией и заполняет эллипс.

ПроцедураSector (Х, Y, Beg А, End А, Rx, Ry); вычерчивает и заполняетэллипсный сектор.

ПроцедураPieSlice (Х, Y, Beg А, End А, R); вычерчивает и заполняетсектор окружности.

ПроцедураSetColor (Color); устанавливает текущий цвет для выводимыхлиний и символов.

ПроцедураSetbkColor (Color); устанавливает цвет фона окна.

ПроцедураSetFillStyle (Fill, Color);устанавливает стиль Fill и цвет заполненияColor.

ЗначенияFill:

 0–    заполнениефоном (узор отсутствует);

 1–    сплошноезаполнение;

 2–    заполнение– – – – –;

 3–    –« –   /////// ;

 4–    –« –  утолщенными ///////;

 5–    –« – утолщенными \\\\\\ ;

 6–    –« – \\\\\\ ;

 7–    –« –   + + + + + +;

 8–    –« –   ******;

 9–    –« –   прямоугольной клеточкой;

 10–   –« –   редкими точками ;

 11–   –« –   частыми точками ;

 12–   –« –   узор определяется пользователем.

Процедура FloodPill (Х, Y, Color); заполняет произвольную замкнутуюлинию (точки соединения должны совпадать, например, концы линий не могутпересекаться) текущим стилем и текущим цветом. X, Y – координаты точкивнутри фигуры, Color — цвет ограничений линии. Если линии разомкнуты илипересекаются и концы «торчат», то цвет «разольется» по всему окну.

Функция ImageSize (X1, Y1, X2, Y2); возвращает размер памяти в байтах,необходимый для размещения прямоугольного фрагмента изображения (например, окнас рисунком).

Процедура GetImage (X1, Y1, X2, Y2, Buf); помещает в память копию прямоугольногофрагмента изображения. Buf — переменная или участки кучи, куда будет помещенакопия видеопамяти с фрагментом изображения. Размер Buf должен быть неменьше значения, возвращаемого функцией ImageSize с теми же координатамиX1...Y2.

Процедура PutImage (X, Y, Buf, Mode); выводит в заданное место экранакопию фрагмента изображения, ранее помещенную в память процедурой GetImage.

X, Y — координаты левого углатого места на экране, куда будет скопирован фрагмент изображения. Buf —переменная, или участок кучи, откуда берется фрагмент изображения. Mode —способ копирования.

 

12.3. Примеры программ

Нижеприведены программы, демонстрирующие некоторые возможности графики в Паскале.

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

      Program Prim54;Uses Graph;var grDriver,grMode,errCode,Radius,i,Width,y0,y1,y2,x1,x2:integer;BegingrDriver:=detect;    { определениеномерадрайвера}

     InitGraph(grDriver,grMode,'');

                          { инициализация графического режима }

     errCode:=GraphResult;

     if errCode=grOK then

  begin            { графический режим открыт, можно работать }

       forradius:=1to5 do

    begin            { рисуем окружности с радиусами 10,20..50,

                              с центром x=200, y=70 точек растра }

          Circle(200,70,Radius*10);readln;end;

     { Cleardevice;}      { если бы этот оператор не был в

                              комментарных скобках, т.е. не заблокирован, то

                             сейчас окружности были бы стерты с экрана }

   Ellipse(200,200,0,360,30,50); { рисуем дугу эллипса сцентром                    200,200, начальный угол=0, конечный – 360(замкнутый,

               эллипс радиусами 30,50 }

       readln;

   Ellipse(300,200,0,180,50,30);        {полэллипса }

       readln;

      for Radius:=1 to 5 do

   Arc(300,100,0,90,radius*10);   {дугисцентром300,100, от

                         0 до 90 градусов, радиусами 10,20..50}

       readln;

       Width:=10;

   Bar(30,20,50,100);    {прямоугольник с координатами 30,20 –

              верхний левый угол и 50,100 – нижний правый угол}

       for i:=1 to 5 do

   Bar(10+i*Width,300+i*10,20+i*Width,400);

    {пять прямоугольников: первый 20,310.30,400,

                         второй 30,320,40,400 и т.д. }

       readln;

   Bar3D(210,300,250,360,10,TopOn); {параллелепипед с крышкой}

       readln;

       x1:=410; y1:=300; x2:=450; y2:=360;

   Bar3D(x1,y1,x2,y2,10,TopOff);    { параллелепипедбезкрышки}

       readln;

       CloseGraph; {закрытьGraph}

       end

    else Halt(1);  { режимGraph неудалосьоткрыть.}

    End.

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

    Program Prim55;

 Uses CRT,Graph;

 var  GrDriver,grMode,errCode:integer;

 begin grDriver:=Detect;

       InitGraph(grDriver,grMode,' ');

       errCode:=GraphResult;

     if errCode=grOK then

  begin Randomize;     {запустить генератор случайныхчисел}

     repeat      {рисуются цветные линии в квадрате 500 x 500,

                  пока не будет нажата любая клавиша, координаты

                  линий случайны, цвета линий случайны}

     SetColor(Random(GetMaxColor)+1);

     Line(Random(500),Random(500),Random(500),Random(500));

     Delay(1000);           {каждая линия рисуется сзадержкой}

     until KeyPressed;

     Cleardevice;

     MoveTo(1,2);                     {перевестикурсор}

     LineRel(500,500);    {провести линию из предыдущейточки в 500,500

                           последним цветом}

     readln;         readln;

     repeat

     LineTo(random(500),random(500)); {провести линию в случайную точку}

     Delay(6000);

     until KeyPressed;  readln;

     ClearDevice;

     Rectangle(29,29,GetMaxX-29,GetMaxY-29);    {прямоугольник}

     readln;

     CloseGraph; end

 else Halt(1);     end.

Prim56рисует эллипсы и круги, закрашенные красным цветом.

ProgramPrim56;

  Uses CRT, Graph;

 Var  grDriver,grMode,errCode:integer;

 Begin  grDriver:=Detect;

      InitGraph(grDriver,grMode, ' ');

      errCode:=Graphresult;

    if errCode=grOK then

  Begin SetBkColor(blue);

      SetFillStyle(1,4);

      FillEllipse(220,150,50,50);

      FillEllipse(420,150,50,50);

      FillEllipse(320,230,50,130);

      FillEllipse(370,405,50,30);

      FillEllipse(275,410,50,30);

      readln; end

      else Halt(1); end.

Prim56рисуетобезьянустазиком.

      Program Prim57;

 Uses Graph;

 Var i,grDriver,grMode,TrrCode,errCode:integer;   x,y:word;

     xm,ym,rc,xc,yc,x1,y1,x2,y2,r:word;

     k:arccoordsType;   kr:array[1..20] of PointType;

  Begin   grDriver:=detect;

          InitGraph(grDriver,grMode,' ' );

          errCode:=GraphResult;

        if errCode=grOK then

  begin

       x:=150; y:=150;

    SetBkColor(white);

           {уши}

    y1:=y-30; x1:=x-30; x2:=x+40; r:=15;

    SetColor(lightred);

    SetFillStyle(solidfill,brown);

    pieslice(x1,y1,0,360,r);

    pieslice(x2,y1,0,360,r);

    r:=r-3;

   SetFillStyle(solidfill,lightred);

    pieslice(x1,y1,0,360,r);

    pieslice(x2,y1,0,360,r);

           {голова}

    r:=(x2-x1) div 2-3;

    x1:=x1+r+2;

    y1:=y1+2;

    xc:=x1;

    yc:=y1;

    rc:=r;

    setColor(brown);

    SetFillStyle(solidfill,brown);

    pieslice(x1,y1,0,360,r);

             {майка}

    setColor(brown);

    SetFillStyle(solidfill,yellow);

    y2:=y1+r-3;

    x1:=x1-r div 2+2;

    ym:=y2;

    line(x1-5,y2-5,x1-27,y2+68);

    x2:=x1+r+16;

    xm:=x2;

    line(x2-15,y2-5,x2+27,y2+68);

    line(x1-27,y2+68,x2+27,y2+68);

    putpixel(x2-22,y2+25,blue);

    floodfill(x2-22,y2+25,brown);

            {пояс}

    setcolor(green);

    setfillstyle(solidfill,green);

    bar(112,215,214,225);

            {штаны}

    setcolor(blue);

    setfillstyle(solidfill,blue);

    kr[1].x:=113; kr[1].y:=223;

    kr[2].x:=113; kr[2].y:=270;

    kr[3].x:=165; kr[3].y:=270;

    kr[4].x:=170; kr[4].y:=260;

    kr[5].x:=180; kr[5].y:=270;

    kr[6].x:=225; kr[6].y:=270;

    kr[7].x:=212; kr[7].y:=223;

    kr[8].x:=113; kr[8].y:=223;

    fillpoly(8,kr);

           {леваянога}

    setcolor(brown);

    setfillstyle(solidfill,brown);

    kr[1].x:=135; kr[1].y:=270;

    kr[2].x:=145; kr[2].y:=320;

    kr[3].x:=123; kr[3].y:=350;

    kr[4].x:=145; kr[4].y:=358;

    kr[5].x:=145; kr[5].y:=350;

    kr[6].x:=162; kr[6].y:=320;

    kr[7].x:=145; kr[7].y:=270;

    kr[8].x:=135; kr[8].y:=270;

    fillpoly(8,kr);

             {праваянога}

    kr[1].x:=195; kr[1].y:=270;

    kr[2].x:=205; kr[2].y:=320;

    kr[3].x:=183; kr[3].y:=350;

    kr[4].x:=205; kr[4].y:=358;

    kr[5].x:=205; kr[5].y:=350;

    kr[6].x:=222; kr[6].y:=320;

    kr[7].x:=205; kr[7].y:=270;

    kr[8].x:=195; kr[8].y:=270;

    fillpoly(8,kr);

              {башмаки}

    setfillstyle(solidfill,red);

    pieslice(160,360,0,360,10);

    pieslice(200,370,10,160,20);

    pieslice(215,360,0,360,10);

    pieslice(142,370,10,160,20);

    setfillstyle(solidfill,white);

    fillellipse(145,115,5,8);

    fillellipse(163,115,5,8);

    setfillstyle(solidfill,blue);

    pieslice(147,115,0,360,3);

    pieslice(165,115,0,360,3);

    setcolor(yellow);

    arc(154,160,30,145,30);

    setcolor(red);

    setfillstyle(solidfill,lightmagenta);

    fillellipse(154,146,5,8);

             {бабочка}

    kr[1].x:=140; kr[1].y:=153;

    kr[2].x:=135; kr[2].y:=163;

    kr[3].x:=155; kr[3].y:=158;

    kr[4].x:=175; kr[4].y:=163;

    kr[5].x:=170; kr[5].y:=153;

    kr[6].x:=155; kr[6].y:=158;

    kr[7].x:=140; kr[7].y:=153;

    fillpoly(7,kr);

              {тазик}

    setfillstyle(solidfill,blue);

    kr[1].x:=243; kr[1].y:=225;

    kr[2].x:=255; kr[2].y:=280;

    kr[3].x:=325; kr[3].y:=280;

    kr[4].x:=335; kr[4].y:=225;

    kr[5].x:=255; kr[5].y:=225;

    fillpoly(5,kr);

    sector(290,230,0,360,50,12);

    setfillstyle(solidfill,lightcyan);

    fillellipse(290,230,40,10);

           {руки}

    setfillstyle(solidfill,brown);

    kr[1].x:=184; kr[1].y:=164;

    kr[2].x:=295; kr[2].y:=225;

    kr[3].x:=300; kr[3].y:=215;

    kr[4].x:=175; kr[4].y:=150;

    kr[5].x:=180; kr[5].y:=160;

    fillpoly(5,kr);

    pieslice(295,224,0,170,12);

    pieslice(265,244,0,360,10);

    kr[1].x:=136; kr[1].y:=184;

    kr[2].x:=265; kr[2].y:=255;

    kr[3].x:=270; kr[3].y:=245;

    kr[4].x:=135; kr[4].y:=170;

    kr[5].x:=136; kr[5].y:=184;

    fillpoly(5,kr);

 end else halt(1);

readln;end.        

     Prim58 демонстрируетвозможности мультипликации: по фоновому рисунку – дом, луна, висящий«базовый» НЛО; мечется с переменной скоростью малый НЛО и издаетзвуки случайными частотами.

         Program Prim58;

     Uses CRT,Graph;

  Label loop;

  Const r=30;  p=600;  pr=1000; {константы, определяющие скорость}

                               {рисования и перемещения объектов}

  Vard,m,e,xm,ym,x,y,lx,ly,rx,ry,size,i,dx,dy,

      width,height,grDriver,grMode,errCode,a,b,c,

      f,s,j:integer;

      saucer:pointer;

  Begin grDriver:=Detect;

           InitGraph(grDriver,grMode,'');

        errCode:=GraphResult;

        if errCode=grOK then

   Begin x:=r*3; y:=r*2; xm:=GetMaxX div 2; ym:=GetMaxY div 2;

 {тарелка}

    SetBkColor(blue);

    SetFillStyle(solidfill,red);

        Ellipse(x,y,0,360,r+40,r div 10);

        Ellipse(x,y-4,0,360,r-1,r);

        Line(x+7,y-6,x+10,y-12);

        Line(x-7,y-6,x-10,y-12);

        Circle(x+10,y-12,2);

        Circle(x-10,y-12,2);

        Floodfill(x+1,y+4,White);

   {определяем габариты НЛО и помещаем данные о нем в кучу}

        lx:=x-r-1;

        ly:=y-14;

        rx:=x+r+1;

        ry:=y+r div 6;

        Width:=rx-lx+1;

        Height:=ry-ly+1;

        Size:=Imagesize(lx-9,ly,rx+3,ry+10);

        GetMem(Saucer,size);

        GetiMage(lx-9,ly,rx+10,ry+3,saucer^);

    {создаемзвездноенебо}

        Rectangle(xm,ym,3*xm,3*ym);

        SetViewPort(xm+1,ym+1,3*xm-1,3*ym-1,Clipon);

        xm:=2*xm;

        ym:=2*ym;

        for i:=1 to 200 do

    PutPixel(random(xm),random(ym),white);

 {дом}

    SetFillStyle(solidfill,DarkGray);

    bar(320,240,640,480);  Delay(p*10);  {дом}

    bar(370,220,600,240);  Delay(p*10);  {чердак}

    Line(320,240,640,240); Delay(p*10);  {крыша}

    Line(370,240,370,220); Delay(p*10);  {левая стеначердака}

    Line(600,220,600,240); Delay(p*10);  {правая стена чердака}

    Line(370,220,600,220); Delay(p*10);  {крышачердака}

    Line(430,220,430,180); Delay(p*10);  {мачтаантенны}

    Line(430,180,410,170); Delay(p*10);  {верхнийусантенны}

    Line(430,180,410,190); Delay(p*10);  {нижнийусантенны}

    Line(430,180,410,180); Delay(p*10);  {среднийусантенны}

    bar(0,460,640,480);    Delay(p*10);  {земля}

    Line(0,460,640,460);   Delay(p*10);

    SetFillStyle(solidfill,Yellow);

    b:=270;                              {окна}

    for i:=1 to 4 do

    begin  a:=350; f:=b+20; c:=a+15; Delay(p*5);

    for j:=1 to 8 do

   begin

    bar(a,b,c,f);           Delay(p*5);

    SetColor(DarkGray);

    Line(a,b+8,c,f-12);     Delay(p*5);

    Line(a+5,b+8,a+5,b+20); Delay(p*5);

    a:=a+35; c:=c+35; end;

    b:=b+50; end;           Delay(p*10);

    Pieslice(500,80,300,100,20);           {месяц}

    SetColor(green);        Delay(p*10);

    Line(150,460,150,400);  Delay(p*10);   {дерево}

    Circle(170,365,25);     Delay(p*10);

    Circle(165,375,25);     Delay(p*10);

    Circle(150,375,25);     Delay(p*10);

    Circle(135,365,25);     Delay(p*10);

    Circle(155,345,25);     Delay(p*10);

 {задаем начальное положение нло и направлениедвижения}

        x:=xm div 2;

        y:=ym div 2;

        dx:=100;

        dy:=100;

    {основнойцикл}

       Repeat

        PutImage(x,y,Saucer^,XorPut);

        Sound(Random(2*2000));

        Delay(pr*2); NoSound;

        Putimage(x,y,Saucer^,XorPut);

     {получаем новые координаты}

   loop:x:=x+dx;

        y:=y+dy;

 if(x<0) or (x+width+1>xm) or (y<0) or (y+height+1>ym) then

   begin

 {НЛОдостиг границы экрана, меняем направление его движения}

      x:=x-dx; y:=y-dy;

      dx:=GetMaxX div 10 — random(GetMaxX div5);

      dy:=GetMaxY div 30 — random(GetMaxY div 15);

      goto loop;

      end until KeyPressed;

   if ReadKey=#0 then x:=ord(ReadKey);

     endelseCloseGraph

end.


Список использованной и рекомендуемой литературы:

1.А.Н. Воловачев, В.С. Крисевич. Программирование на языке Паскаль для персональныхЭВМ ЕС. – Минск: «Высшая школа», 1989.

2.В.Я. Сердюченко. Розробка алгоритмівта програмування мовою TURBOPASCAL. – Харьков:«Паритет», 1995.

3.В.В. Фаронов. TURBOPASCAL 7.0 /Практикапрограммирования/ – «Нолидж», 1997.

4.В.В. Фаронов. TURBOPASCAL 7.0 /Начальный курс/ –«Нолидж», 1997.


ОГЛАВЛЕНИЕ

1. Предварительные сведения… 4

1.1. Алфавит… 4

1.2. Решение задач… 4

2. Простейшие программы… 5

2.1. Оператор присваивания… 5

2.2. комментарии… 7

2.3. Программа… 7

2.4. Простейший ввод-вывод… 8

2.5. Арифметические выражения… 9

2.6. Описания переменных… 12

2.7. Раздел описания типов… 14

3. Разветвляющиеся программы… 16

3.1. Общие положения… 16

3.2. Оператор goto, раздел описанияметок… 17

3.3. Оператор if… 19

3.4. Оператор case (оператор выбора)… 25

4. Циклические программы… 27

4.1. Оператор for… 27

4.2. Оператор repeat. Общий вид… 32

4.3. Оператор While… 33

4.4. Вложенные циклы… 34

5. Ввод – вывод… 37

5.1. Общие положения… 37

5. 2. Ввод… 38

5. 3. Вывод… 39

5. 4. Некоторые возможностиввода-вывода… 39

6. Массивы… 41

6. 1. Описание массивов… 41

7. Подпрограммы… 49

7.1. Общие положения… 49

7.2. Подпрограммы-функции,определенные пользователем… 51

7.3. Подпрограммы-процедуры… 54

7.4. Локальные и глобальные описанияобъектов… 58

8. Строковые данные… 59

8.1. Общие замечания… 59

8.2. Строковые выражения… 60

8.3. Стандартные процедуры и функциидля обработки строк… 61

8.3.1. Процедуры обработки строк… 61

8.3.2. Функции обработки строк… 62

9. Записи… 63

9.1. Комплексные данные… 68

9.2. Запись с вариантами… 70

10. Файлы… 71

10.1. Общие замечания… 71

10.2. Стандартные процедуры ифункции для работы с файлами… 72

10. 3. Стандартные файлы… 73

10.4. Файлы последовательногодоступа, созданные пользователем. 74

10.5. Файлы произвольного доступа… 80

10.6. Текстовые файлы… 83

11. Использование библиотеки CRT… 85

11.1. Программирование клавиатуры… 85

11.2. Текстовый вывод на экран… 88

11.3. Программирование звуковогогенератора… 96

12. Графика в Паскале… 99

12.1. Инициализация графическогорежима… 99

12.2. Процедуры и функции библиотекиGraph… 99

12.3. Примеры программ… 102

СПИСОК ИСПОЛЬЗОВАННОЙ ЛИТЕРАТУРЫ............................................109

еще рефераты
Еще работы по информатике, программированию