pascal (Программирование на языке Турбо Паскаль), страница 2

2016-07-31СтудИзба

Описание файла

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

Онлайн просмотр документа "pascal"

Текст 2 страницы из документа "pascal"

.......

if i mod 2 = 1 then i:=i-1; {else - ничего не делать}

Примечание: в примере использована операция нахождения остатка от деления (mod), для нахождения неполного частного в Турбо-Паскале используется div.

Пример 3: (с использованием составного оператора). Пусть даны две переменные типа real. Требуется поменять местами значения этих переменных, если a1>a2.

var a1,a2,buf :real;

.........

if a1>a2 then begin

buf:=a1;

a1:=a2;

a2:=buf;

end;

Следующий пример использует вложенные операторы if.

Пример 4: Поиск корней квадратного уравнения.

program SqEquation;

var a,b,c,d: real;

begin

writeln;

write('Введите коэффициенты a,b,c квадратного уравнения : ');

readln(a,b,c);

d:=sqr(b)-4*a*c;

if d>=0 then

if d=0 then writeln('Единственный корень: x=',-b/(2*a):8:3)

else writeln('Два корня : x1=',(-b+sqrt(d))/(2*a):8:3,

', x2=',(-b-sqrt(d))/(2*a):8:3)

else {d<0} writeln('Корней нет');

readln;

end.

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

Пример 5: пользователь вводит натуральное число, задача программы — поставить слово «ученик» в нужную форму в сочетании с числительным (например: 1 ученик, 3 ученика, 9 учеников и т.п.)

begin

write('Число учеников (1..20) --> '); readln(n);

write(n,' ученик');

if n<5 then begin

if n>1 then writeln('а');

end

else

writeln('ов');

readln;

end.

В этом примере пришлось использовать составной оператор (begin ... end;) для того чтобы часть else относилась не к оператору if n>1, а к if n<5.

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

Кроме оператора условного выполнения и циклов в Турбо Паскале имеется ещё одна управляющая конструкция, одно из названий которой — оператор выбора. На самом деле это усложнённый оператор if, он позволяет программе выполняться не двумя способами, в зависимости от выполнения условия, а несколькими, в зависимости от значения некоторого выражения. В общем виде этот оператор выглядит так:

case Выражение of

Вариант1: Оператор1;

Вариант2: Оператор2;

...

ВариантN: ОператорN;

[else ОператорN1;]

end;

(Пояснение: квадратные скобки означают то, что часть else может отсутствовать).

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

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

  2. Интервал, например: 1..5, 'a'..'z'.

  3. Список значений или интервалов, например: 1,3,5..8,10,12.

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

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

program SchoolChildren;

var n: integer;

begin

write('Число учеников --> '); readln(n);

write(n,' ученик');

case n of

2..4: write('а');

5..10: write('ов');

end;

readln;

end.

Можно также усовершенствовать программу для произвольного натурального n:

write(n,' ученик');

case n mod 100 of

11..19: write('ов');

else case n mod 10 of

2..4: write('а');

0,5..9: write('ов');

end;

end;

Лекция 4. Операторы циклов в Паскале

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

1. Цикл с постусловием (Repeat)

На Паскале записывается следующим образом: repeat <оператор> until <условие>. (По-русски: повторять что-то пока_не_выполнилось условие). Под обозначением <оператор> здесь понимается либо одиночный, либо последовательность операторов, разделённых точкой с запятой. Цикл работает следующим образом: выполняется оператор, затем проверяется условие, если оно пока еще не выполнилось, то оператор выполняется вновь, затем проверяется условие, и т. д. Когда условие, наконец, станет истинным выполнение оператора, расположенного внутри цикла, прекратится, и далее будет выполняться следующий за циклом оператор. Под условием, вообще говоря, понимается выражение логического типа.

Пример (подсчет суммы натуральных чисел от 1 до 100):

var i,sum: integer;

begin

sum:=0; i:=0;

repeat

i:=i+1;

sum:=sum+i;

until i=100;

writeln('Сумма равна: ',sum);

readln;

end.

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

2. Цикл с предусловием (While)

Этот цикл записывается так: while <условие> do <оператор>. (Пока условие истинно, выполнять оператор). Суть в следующем: пока условие истинно, выполняется оператор (в этом случае оператор может не выполниться ни разу, т.к. условие проверяется до выполнения). Под оператором здесь понимается либо простой, либо составной оператор (т.е. несколько операторов, заключёных в begin ... end).

Рассмотрим тот же пример, выполненный с помощью while:

var i,sum: integer;

begin

sum:=0; i:=0;

while i<100 do begin

i:=i+1;

sum:=sum+i;

end;

writeln('Сумма равна: ',sum);

readln;

end.

3. Цикл со счетчиком (For)

Записывается так: for <переменная>:=<нач> to <кон> do <оператор>. Вместо to возможно слово downto. Рассмотрим такой пример: требуется вывести на экран таблицу квадратов натуральных чисел от 2 до 20.

var i: integer;

begin for i:=2 to 20 do writeln(i,' ',sqr(i)); end.

При выполнении цикла происходит следующее: переменной i присваивается начальное значение (2), затем выполняется оператор (простой или составной), после этого к i прибавляется 1, и проверяется, не стало ли значение i равно конечному (20). Если нет, то вновь выполняется оператор, добавляется 1, и т. д. В случае, когда вместо to используется downto, все происходит наоборот: единица не прибавляется, а вычитается. Например, следующий цикл выведет ту же таблицу, но в обратном порядке:

for i:=20 downto 2 do writeln(i,' ',sqr(i));

В завершение запишем программу о подсчете суммы чисел от 1 до 100 с помощью for:

var i, sum: integer;

begin

sum:=0;

for i:=1 to 100 do sum:=sum+i;

writeln(sum);

end.

Лекция 5. Символьные и строковые переменные

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

1. Символьный тип

Тип данных, переменные которого хранят ровно один символ (букву, цифру, знак препинания и т.п.) называется символьным, а в Паскале — char. Объявить переменную такого типа можно так: var ch: char;. Для того чтобы положить в эту переменную символ, нужно использовать оператор присваивания, а символ записывать в апострофах, например: ch:='R';. Для символьных переменных возможно также использование процедуры readln, например:

write(‘Выйти из игры? (Да/Нет)’); readln(ch);

if ch=’Д’ then ...{выходить}...

else ...{продолжать}...;

Символьные переменные в памяти компьютера хранятся в виде числовых кодов, иначе говоря, у каждого символа есть порядковый номер. К примеру, код пробела равен 32, код ‘A’ — 65, ‘B’ — 66, ‘C’ — 67, код символа ‘1’ — 48, ‘2’ — 49, ‘.’ — 46 и т. п. Некоторые символы (с кодами, меньшими 32) являются управляющими, при выводе таких символов на экран происходит какое либо действие, например, символ с кодом 10 переносит курсор на новую строку, с кодом 7 — вызывает звуковой сигнал, с кодом 8 — сдвигает курсор на одну позицию влево. Под хранение символа выделяется 1 байт (байт состоит из 8 бит, а бит может принимать значения 0 или 1), поэтому всего можно закодировать 28=256 различных символов. Кодировка символов, которая используется Турбо-Паскале, называется ASCII (American Standard Code for Information Interchange — американский стандартный код для обмена информацией).

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

var i: byte; {число, занимающее 1 байт, значения — от 0 до 255}

ch: char;

...

readln(i); writeln('символ с кодом ',i,' — это ',chr(i));

Если в качестве кода используется конкретное число, а не выражение и не переменная, то можно использовать символ «#», скажем так: ch:=#7;. Для того перехода от кода к символу используется функция ord (от слова ordinal — порядковый). Имеющиеся знания позволяют нам написать программу, которая выдаёт на экран таблицу с кодами символов:

program ASCII;

var ch: char;

begin

for ch:=#32 to #255 do write(ord(ch),'—>',ch,' ');

readln;

end.

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

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

  1. succ (от succeedent — последующий), она выдаёт символ со следующим кодом.

  2. pred (от predecessor — предшественник), выдаёт символ с предыдущим кодом.

Если попытаться в программе получить succ(#255) или pred(#0), то возникнет ошибка. Пользуясь этими функциями можно переписать предыдущую программу и по-другому:

...

ch:=#32;

while ch<>#255 do begin

write(ord(ch),'—>',ch,' ');

ch:=succ(ch);

end;

...

Сравнение символов. Также как и числа, символы можно сравнивать на =, <>, , =. В этом случае Паскаль сравнивает не сами символы, а их коды. Таблица ASCII составлена таким образом, что коды букв (латинских и большинства русских) возрастают при движении в алфавитном порядке, а коды цифр расположены по порядку: ord(‘0’)=48, ord(‘1’)=49, ... ord(‘9’)=57. Сравнения символов можно использовать везде, где требуются логические выражения: в операторе if, в циклах и т.п.

2. Строковый тип

Для хранения строк (то есть последовательностей из символов) в Турбо-Паскале имеется тип string. Значениями строковых переменных могут быть последовательности различной длины (от нуля и более, длине 0 соответствует пустая строка). Объявить строковую переменную можно двумя способами: либо var s: string; (максимальная длина строки — 255 символов), либо var s: string[n]; (максимальная длина — n символов, n — константа или конкретное число).

Для того чтобы положить значение в строковую переменную используются те же приёмы, что и при работе с символами. В случае присваивания конкретной строки, это строка должна записываться в апострофах (s:='Hello, world!'). Приведём простейший пример со строками: программа спрашивает имя у пользователя, а затем приветствует его:

program Hello;

var s: string;

begin

write('Как Вас зовут: ');

readln(s);

write('Привет, ',s,'!');

readln;

end.

Хранение строк. В памяти компьютера строка хранится в виде последовательности из символьных переменных, у них нет индивидуальных имён, но есть номера, начинающиеся с 1). Перед первым символом строки имеется ещё и нулевой, в котором хранится символ с кодом, равным длине строки. Нам абсолютно безразлично, какие символы хранятся в байтах, находящихся за пределами конца строки. Рассмотрим пример. Пусть строка s объявлена как string[9], тогда после присваивания s:=’Привет’; она будет хранится в следующем виде:

Номер байта

0

1

2

3

4

5

6

7

8

9

Содержимое

#6

‘П’

‘р’

‘и’

‘в’

‘е’

‘т’

‘ю’

‘s’

‘%’

Для того чтобы в программе получить доступ к n-му символу строки используется запись s[n]. Если поменять значение s[0] то это отразится на длине строки. В следующем примере из строки 'Привет' мы сделаем 'Привет!': s[0]:=#7; s[7]:='!';.

Сравнение строк. Строки сравниваются последовательно, по символам. Сравниваются первые символы строк, если они равны — то вторые, и т. д. Если на каком-то этапе появилось различие в символах, то меньшей будет та строка, в которой меньший символ. Если строки не различались, а затем одна из них закончилась, то она и считается меньшей. Примеры: 'ананас'<'кокос', 'свинья'>'свинина', ''<'A', 'hell'<'hello'.

Склеивание (конкатенация) строк. К строкам можно применять операцию «+», при этом результатом будет строка, состоящая из последовательно записанных «слагаемых». Пример: после действия s:= 'abc'+'def'+'ghi'; переменная s будет содержать ‘abcdefghi’.

Процедуры и функции для работы со строками. Наиболее часто употребляется функция length(s: string): integer (после двоеточия записан тип значения, возвращаемого функцией, в нашем случае — целое число). Эта функция возвращает длину строки s.

Другие процедуры и функции приведены в таблице:

Процедура или функция

Назначение

Пример

функция

Copy(s: string; start: integer;
len: integer): string

Возвращает вырезку из строковой переменной s, начиная с символа с номером start, длина которой len

s:=’Бестолковый’;

s1:=Copy(s,4,4);

{в s1 станет толк’}

функция

Pos(s1: string; s: string): byte

Ищет подстроку s1 в строке s. Если находит, то возвращает номер символа, с которого начинается первое вхождение s1 в s; если s1 не входит в s, то функция возвращает 0

n:=pos(‘министр’,

‘администратор’); {=3}

n:=pos(‘abc’,

‘stuvwxyz’);{=0}

процедура

Insert(s1: string; s: string;
start: integer)

Вставляет строку s1 в строковую переменную s начиная с символа с номером start.

S:=‘кот’;

insert(‘мпо’,s,3);

{в s станеткомпот’}

процедура

Delete(s: string; start: integer;
len: integer)

Удаляет из строковой переменной s фрагмент, начинающийся с символа с номером start и длиной len

s:= ‘треугольник’;

delete(s,4,7);

{в s останется трек’}

Лекция 6. Перечисляемый и ограниченный типы

1. Перечисляемый тип

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

type Days = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);

После этого можно завести переменную этого типа (var day: Days;) и использовать её. Ниже приведены примеры использования:

day:=Wed;

...

if day>Fri then writeln('Сегодня выходной');

...

if day=Mon then writeln('Началась рабочая неделя');

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

Для переменных перечисляемых типов возможно применение функций succ и pred, например, succ(Wed) дает Thu, Pred(Sun) дает Sat. Если попытаться написать Pred(Mon) или Succ(Sun), то уже на этапе проверки программы компилятором произойдет ошибка.

Хранение значений перечисляемого типа устроено внутри довольно просто: хранятся целые числа от 0 до n, в нашем случае n=6. Существует функция Ord, которая позволяет получить то число, в виде которого хранится какое-либо значение перечисляемого типа, например Ord(Wed) дает 2. При необходимости можно получить значение перечисляемого типа по его численному представлению, например, Days(1) есть Tue. После всего сказанного можно заметить, что при сравнении величин перечисляемого типа в действительности сравниваются их порядковые номера (Ord).

Пример использования перечисляемых типов:

Пусть корабль может двигаться только по четырем направлениям: на север, на запад, на юг и на восток, то есть текущее направление движения определяется переменной типа Directions = (North, West, South, East);. Этому кораблю можно подавать приказы следующих типов: вперёд, назад, влево, вправо, то есть любой приказ задать переменной типа Orders = (Ahead, Back, Left, Right);. Пусть корабль двигался по направлению d1, после чего ему дали приказ p. Программа должна определить, в каком направлении корабль будет двигаться после выполнения приказа.

program Ship;

type Courses = (North, West, South, East);

Orders = (Ahead, Back, Left, Right);

var d1, d2: Courses;

p: Orders;

i: integer;

s: string;

begin

{Запрашиваем у пользователя информацию о курсе и приказе}

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

write('(0-север, 1-запад, 2-юг, 3-восток) ');

readln(i);

d1:=Courses(i);

writeln('Введите приказ, данный кораблю ');

write('(0-прямо, 1-назад, 2-влево, 3-вправо) ');

readln(i);

p:=Orders(i);

{Определяем новый курс}

case p of

Ahead : d2:=d1;

Back : d2:=Courses((ord(d1)+2) mod 4);

Left : d2:=Courses((ord(d1)+1) mod 4);

Right : d2:=Courses((ord(d1)+3) mod 4);

{-1 - нельзя, так как (Ord(North)-1) mod 4 = -1}

end;

{Выводим результат на экран}

case d2 of

North : s:='север';

West : s:='запад';

South : s:='юг';

East : s:='восток';

end;

writeln('Теперь корабль движется на '+s);

readln;

end.

2. Ограниченный тип

Этот тип также рассмотрим на примере. Пусть в некоторой переменной нужно хранить текущее число, то есть номер дня в месяце. В Турбо Паскале можно задать тип DaysInMonth = 1..31;. Переменные и константы этого типа могут принимать только такие значения, если попытаться задать что-либо другое, то компилятор выдаст ошибку. В качестве границ могут употребляться и отрицательные числа, например Temperature=-60..50;

В качестве базового типа (то есть типа, из которого выбирается диапазон значений) могут использоваться почти все порядковые типы, то есть те, которые хранятся в виде целых чисел. К порядковым типам относятся: все целые типы (byte, integer, и т. п.), char, boolean, перечисляемые типы и ограниченные типы. В качестве базового типа нельзя использовать лишь сам ограниченный тип (трудно представить, как это можно сделать). С учетом этого правила допустимы такие объявления типов:

type SmallLatin = 'a'..'z'; {малые латинские буквы}

MyBoolean = True..False; {хотя это и бессмысленно}

Holidays = Sat..Sun; {выходные}

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

type Wrong = -1.25..1.25;

Заметим, что функции Ord, Succ и Pred могут применяться к любым порядковым типам, и, в частности, к ограниченным.

Лекция 7. Массивы

1. Понятие массива. Одномерные массивы

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

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

Переменная a состоит из десяти ячеек типа real, можно записывать и извлекать значения из них, пользуясь записью a[<номер ячейки>].

Пример 1. Поиск наибольшего числа среди элементов массива.

program FindMaximumInArray;

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

i,max: integer;

begin

for i:=1 to 10 do begin

write('Введите элемент номер ',i,' -> ');

readln(a[i]);

end;

max:=a[1];

for i:=2 to 10 do

if a[i]>max then max:=a[i];

writeln('Максимум равен ',max);

readln;

end.

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

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

var Numbers: array [0..1000] of integer;

Names: array [1..10] of string;

Crit: array[shortint] of boolean;

CountAll: array[char] of integer;

Count: array['a'..'z'] of integer;

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

Пример 2. Подсчет количества различных букв в строке.

program CountLetters;

var s: string;

count: array['a'..'z'] of byte;

ch: char;

i: byte;

begin

write('Введите строку > ');

readln(s);

for i:=1 to length(s) do

if (s[i]>='a')and(s[i]<='z') then inc(count[s[i]]);

writeln('Количество различных букв в строке: ');

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

if count[ch]<>0 then

writeln(ch,': ',count[ch]);

readln;

end.

2. Многомерные массивы

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

Примеры описаний многомерных массивов:

var Matrix: array[1..4,1..3] of real;

Cube3D: array[1..5,1..5,1..5] of integer;

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

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

program Calendar;

type tWeekDay = (Mon,Tue,Wed,Thu,Fri,Sat,Sun,NoDay);

{NoDay - нет дня (например, 30.02)}

tCalendar = array [1..12,1..31] of tWeekDay;

var CL: tCalendar;

m,d: byte; {месяц и число}

wd: tWeekDay; {день недели}

begin

{Строим массив:}

{1. Заполним весь календарь значениями "нет дня":}

for m:=1 to 12 do

for d:=1 to 31 do CL[m,d]:=NoDay;

{2. Строим массив-календарь:}

m:=1; d:=1;

wd:=Mon;

repeat

CL[m,d]:=wd;

case m of

4,6,9,11: if d=30 then begin m:=m+1; d:=1; end else d:=d+1;

1,3,5,7,8,10,12: if d=31 then begin m:=m+1; d:=1; end else d:=d+1;

2: if d=28 then begin m:=m+1; d:=1; end else d:=d+1;

end;

wd:=tWeekDay((ord(wd)+1) mod 7);

until m=13;

{Выводим на экран:}

repeat

write('Номер месяца > '); readln(m);

write('Число > '); readln(d);

case CL[m,d] of

Mon: writeln('Понедельник');

Tue: writeln('Вторник');

Wed: writeln('Среда');

Thu: writeln('Четверг');

Fri: writeln('Пятница');

Sat: writeln('Суббота');

Sun: writeln('Воскресенье');

NoDay: writeln('Такого дня нет в календаре');

end;

until false;

end.

3. Сортировка и поиск

В прикладных программах широко распространены два типа операций, связанных с массивами:

  1. Упорядочивание элементов массива по возрастанию или убыванию (сортировка)

  2. Поиск элемента в массиве.

Рассмотрим простейший вариант сортировки массива (сортировка выбором). Пусть есть массив из n элементов; сначала найдём в нём самый маленький среди элементов с номерами 2,3,...n и поменяем местами с первым элементом, затем среди элементов с номерами 3,4,...n найдём наименьший и обменяем со вторым, и т. д. В результате наш массив окажется отсортированным по возрастанию.

program SelectSort;

const n = 10;

var a: array [1..n] of integer;

i,j,jmin,buf: integer;

{jmin - номер наименьшего элемента,

buf используется при обмене значений двух элементов}

begin

for i:=1 to 10 do begin

write('Введите элемент номер ',i,' -> ');

readln(a[i]);

end;

for i:=1 to n-1 do begin

jmin:=i;

for j:=i+1 to n do

if a[j]then jmin:=j;

buf:=a[i];

a[i]:=a[jmin];

a[jmin]:=buf;

end;

write('Результат: ');

for i:=1 to 10 do write(a[i],' ');

readln;

end.

Другой способ — пузырьковая сортировка, он работает чуть быстрее, чем предыдущий. На первом этапе двигаемся от n-го элемента до 2-го и для каждого из них проверяем, не меньше ли он предыдущего; если меньше, то меняем местами текущий и предыдущий. В итоге первый элемент будет наименьшим в массиве. На втором этапе также проходим элементы от n-го до 3-го, на третьем — от n-го до 4-го, и т. д. В итоге массив будет отсортирован по возрастанию.

program BubbleSort;

...

var i,j: integer;

buf: integer;

begin

...

for i:=2 to n do

for j:=n downto i do

if a[j]then begin

buf:=a[j];

a[j]:=a[j-1];

a[j-1]:=buf;

end;

end.

Лекция 8. Тип запись

Тип запись, также как и массив, является структурированным типом данных, то есть таким, переменные которого составлены из нескольких частей. В Турбо-Паскале существует возможность объединить в одну переменную данные разных типов (тогда как в массиве все элементы имеют одинаковый тип). Приведём пример такого типа. Пусть в переменной требуется хранить сведения о некотором человеке: ФИО, пол, адрес, телефон. Тогда для хранения этих данных будет удобен такой тип:

type tPerson = record

Name,Surname,SecondName: string[30];

Male: boolean;

Address: string;

Phone: longint;

end;

Объявление переменной типа запись выполняется стандартно, с помощью var. Части записи (в нашем случае: Name, Surname, SecondName, Male, Address, Phone) называются полями. Обращение к полю записи в программе производится с помощью знака ‘.’ (точка). Пример обращения к полям:

var p: tPerson;

...

begin

...

p.Surname:=’Иванов’;

p.Name:=’Иван’;

p.SecondName:=’Иванович’;

...

if (p.Phone<0) or (p.Phone>999999)

then writeln(‘Ошибка’);

...

end.

Заметим, что в этом примере постоянно приходится обращаться к полям одной и той же переменной типа запись, и, следовательно, постоянно писать её имя. Есть возможность избавиться от этого неудобства. В Турбо Паскале есть оператор присоединения (with), который позволяет один раз указать, какой записью мы пользуемся и в дальнейшем писать только имена полей. Обычно этот оператор выглядит так:

with <имя_записи> do ;

Чаще всего в качестве оператора используется составной оператор.

Пример:

with p do begin

Surname:=’ Иванов’;

Name:=’Иван’;

...

end;

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

const N = 30;

type tStaff = array [1..N] of tPerson;

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

type tPoint = record

x,y: integer;

end;

tRectangle = record

LeftTop: tPoint;

Width, Height: integer;

Color: integer;

end;

Для такой записи можно применять ещё одну форму оператора with, которая может «присоединять» несколько имён записей, например:

var rect: tRect;

with rect, LeftTop do begin

x:=100;

y:=150;

Color:=11;

...

end;

Без использования with появились бы выражения вида rect.Color, rect.LeftTop.x, rect.LeftTop.y и т. п.

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

const MaxVertex = 200;

type tPolygon = record

size: integer;

V: array [1..MaxVertex] of tPoint;

Color: tColor;

end;

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

type tFKind = (fCir,fRect,fSqr);

tFigure = record

Color: integer;

case kind: tFKind of

fCir: (Center: tPoint; r: integer);

fRect: (LeftTop,RightBottom: tPoint);

fSqr: (LT: tPoint; size: integer);

end;

В этой записи имеется одно обычное поле (Color), а остальные 6 и представляют собой вариантную часть. Для окружности в ней имеются поля Center и r, для прямоугольника — LeftTop и RightBottom, для квадрата — LT и size. Фраза kind: tFKind не является обязательной, она служит для понимания того, какие поля к каким фигурам относятся. Можно написать просто case integer of ... и нумеровать варианты целыми числами. Заметим также, что в объявлении нашей записи нет слова end, относящегося к case.



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

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

Лекция 9. Процедуры и функции

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

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

program ...

const ...

type ...

var ...

procedure MyProc;

begin

{действия}

end;

begin

{основная программа}

end.

Рассмотрим пример нахождения максимума из трёх чисел:

program Max1;

var a,b,c,m: integer;

begin

write('Введите a: '); readln(a);

write('Введите b: '); readln(b);

write('Введите c: '); readln(c);

if a>b then m:=a else m:=b;

if c>m then m:=c;

writeln('Максимум = ',m);

readln;

end.

Перепишем его с использованием процедуры:

program Max2;

var a,b,c,m: integer;

procedure FindMax;

begin

if a>b then m:=a else m:=b;

if c>m then m:=c;

end;

begin

write('Введите a: '); readln(a);

write('Введите b: '); readln(b);

write('Введите c: '); readln(c);

FindMax;

writeln('Максимум = ',m);

readln;

end.

Этот вариант можно улучшить. Пока наша процедура может искать минимум только среди значений конкретных переменных a, b и c. Заставим её искать минимум среди любых трёх целых чисел и помещать результат в нужную нам переменную, а не всегда в m.

Чтобы была видна польза от такой процедуры, рассмотрим пример программы для поиска максимума среди чисел a+b, b+c и a+c:

program Max3;

var a,b,c,m: integer;

procedure FindMax(n1,n2,n3: integer; var max: integer);

begin

if n1>n2 then max:=n1 else max:=n2;

if n3>max then max:=n3;

end;

begin

write('Введите a: '); readln(a);

write('Введите b: '); readln(b);

write('Введите c: '); readln(c);

FindMax(a+b,b+c,a+c,m);

writeln('Максимум из сумм = ',m);

readln;

end.

В скобках после имени процедуры (в её описании) записаны так называемые параметры. Эта запись обозначает, что внутри процедуры можно использовать целые числа, обозначенные n1, n2 и n3, а также заносить значения в переменную типа integer, которая внутри процедуры называется max (а реально во время работы программы все действия производятся над переменной m). Параметры, в которых хранятся числа (n1,n2,n3) называются параметрами-значениями; а те, которые обозначают переменные (max) – параметрами-переменными, перед ними в описании ставится слово var. Параметры, на которые имеются ссылки внутри процедуры (n1, n2, n3, max), называются формальными, а те, которые реально используются при вызове (a+b, b+c, a+c, m) — фактическими.

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

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

program Max4;

var a,b,c,m: integer;

function Max(n1,n2,n3: integer) : integer;

var m: integer;

begin

if n1>n2 then m:=n1 else m:=n2;

if n3>m then m:=n3;

Max:=m;

end;

begin

write('Введите a: '); readln(a);

write('Введите b: '); readln(b);

write('Введите c: '); readln(c);

writeln('Максимум = ',Max(a+b,b+c,a+c));

readln;

end.

Нам уже известно как вызывать функцию из программы (например sqrt, sin и т. п.). Рассмотрим описание функции. Оно очень похоже на описание процедур, но есть два отличия:

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

  2. Среди операторов в теле функции наиболее важными являются операторы присваивания значения функции (в нашем случае это строчка Max:=m;).

В записанной выше функции используется так называемая локальная переменная m, то есть переменная, которая «видна» только нашей функции, а другие процедуры и функции, а также главная программа её «не видят». Кроме локальных переменных в Турбо-Паскале можно определять локальные константы и типы.

Приведём другие примеры процедур и функций.

  1. Напишем на Паскале функцию .

function Cube(x: real): real;

begin

Cube:=x*x*x;

end;

  1. Вычисление площади треугольника через длины сторон. Здесь будет использована формула Герона: , где p – полупериметр треугольника, a, b, c – длины сторон.

function Square(a,b,c: real): real;

var p: real;

begin

p:=(a+b+c)/2;

Square:=sqrt(p*(p-a)*(p-b)*(p-c));

end;

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

procedure SqEquation(a,b,c: real; var RootsExist: boolean;

var x1,x2: real);

var d: real;

begin

d:=sqr(b)-4*a*c;

if d>=0 then begin

RootsExist:=true;

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

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

end

else RootsExist:=false;

end;

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

function EqHasRoots(a,b,c: real; var x1,x2: real) : boolean;

var d: real;

begin

d:=sqr(b)-4*a*c;

if d>=0 then begin

EqHasRoots:=true;

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

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

end

else EqHasRoots:=false;

end;

Использовать такую функцию даже проще чем последнюю процедуру:

if EqHasRoots(1,2,1,r1,r2) then writeln(r1,' ',r2) else writeln('Нет корней');

Лекция 10. Модуль CRT

Модуль CRT - набор средств для работы с экраном в текстовом режиме, клавиатурой и для управления звуком. Для того чтобы использовать эти средства требуется после заголовка программы записать: uses CRT;.

1. Управление экраном

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

Наиболее распространённым в настоящее время является текстовый режим 80x25 при 16 возможных цветах текста и фона. Многие графические адаптеры позволяют использовать другие режимы, например: 40x25, 80x43, 80x50 и т. д.

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

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

Название

Назначение

InsLine

Вставить строку в том месте где находится курсор, все строки ниже курсора сдвигаются вниз на одну позицию. Курсор остаётся на том же месте.

DelLine

Удалить строку в позиции курсора. Курсор остаётся на том же месте.

GotoXY(x,y: byte)

Переместить курсор в позицию (x,y); x — номер строки, y — номер столбца.

ClrEOL

Очистить строку от курсора и до правого края экрана. Курсор остаётся на прежнем месте

HighVideo

Устанавливает повышенную яркость для вывода текста

LowVideo

Пониженная яркость

NormVideo

Нормальная яркость

TextColor(color: byte)

Устанавливает цвет для вывода текста. Значения цветов — обычно числа от 0 до 15. Вместо этих чисел можно указывать и существующие константы (black, white, red, green, blue, magenta, cyan, brown, lightgray и т. п.). При необходимости можно заставить текст мерцать прибавляя к номеру цвета число 128 или константу Blink.

TextBackGround(color: byte)

Устанавливает цвет для фона.

ClrScr

Очистить экран и поместить курсор в левый верхний угол, т.е. в позицию (1,1) — 1-я строка, 1-й столбец. При очистке экран заполняется цветом фона (см. TextBackground)

WhereX: byte

Эта функция возвращает номер строки, в которой находится курсор.

WhereY: byte

Номер столбца, в котором находится курсор

2. Работа с клавиатурой

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

  1. KeyPressed: boolean — возвращает true, если очередь клавиатуры не пуста (то есть была нажата). Простейший пример использования — повторять какие либо действия, пока не нажата клавиша: repeat ... until KeyPressed;.

  2. ReadKey: char — возвращает символ, соответствующий нажатой клавише (из очереди клавиатуры). Если пользователь нажал клавишу, для которой имеется код ASCII, то в очередь будет положен один соответствующий символ, а если это специальная клавиша (F1, F2, ... F12, клавиши управления курсором, Ins, Del, Home, End, PgUp, PgDn), то сначала в очередь будет положен символ с кодом 0, а затем дополнительный символ. Если очередь клавиатуры пуста, то Readkey будет ждать, пока пользователь не нажмёт какую-либо клавишу.

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

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5173
Авторов
на СтудИзбе
437
Средний доход
с одного платного файла
Обучение Подробнее