If a[i]>a[j] then begin

t:=a[i];

a[i]:=a[j];

a[j]:=t;

end;

for i:=1 to N do

StringGrid2.Cells[i-1,0]:=IntToStr(a[i]);

FreeMem(a,N*sizeof(integer));

end;

end.

5.4. Выполнение индивидуальные задания

а). Выполните задачу из п. 4.6 используя двумерный динамический массив.

б). По указанию преподавателя выберите вариант задачи. Нарисуйте схему алгоритма. Выделение памяти под массив организовать динамически. Организуйте ввод данных из StringGrid1. Вывод организовать, в зависимости от варианта, в StringGrid2, или в Edit1.

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

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

3. Дан массив, состоящий из символов. Вывести на экран цифру, наиболее часто встречающуюся в этом массиве.

4. Дан массив, состоящий из символов. Определить количество различных элементов массива (т.е. повторяющиеся элементы считать один раз).

5. Дан массив, состоящий из символов. Элементы массива циклически сдвинуть на k позиций влево.

6. Дан массив, состоящий из символов. Элементы массива циклически сдвинуть на n позиций вправо.

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

8. Элементы каждого из массивов X и Y упорядочены по возрастанию Объединить элементы этих двух массивов в один массив Z так, чтобы они снова оказались упоряченными по возрастанию.

9. Дан массив, состоящий из символов. Определить, симметричен ли он, т.е. читается ли он одинаково слева направо и справа налево.

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

11. Определить количество инверсий в этом массиве X (т.е. таких пар элементов, в которых большее число находится слева от меньшего: xi>xjпри i<j).

12. Дан массив из строчных латинских букв. Вывести на экран в алфавитном порядке все буквы, которые входят в этот текст по одному разу.

13. Дан массив, состоящий из символов. Удалить из него повторные вхождения каждого символа.

14. Дан массив, состоящий из цифр. Удалить из него все четные числа.

15. Дан массив, состоящий из цифр. Удалить из него все отрицательные числа.

 


 

Тема 6. Программирование с использованием подпрограмм и модулей

Цель лабораторной работы: изучить возможности DELPHI для написания подпрограмм и создания модулей. Составить и отладить программу, использующую внешний модуль UNIT с подпрограммой.

6.1. Использование подпрограмм

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

Подпрограммы подразделяются на процедуры и функции.

Процедура имеет следующую структуру:

Procedure <имя процедуры> ([список имен формальных параметров с

указанием их типов]);

Const [описание используемых констант];

Type[описание используемых типов];

Var[описание используемых переменных];

Begin

// Операторы

End;

Вызов процедуры: <имя процедуры> ([список имен формальных параметров без указания их типов]);

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

Function <имя функции> ([список имен формальных параметров

с указанием их типов]): <тип результата>;

Const [описание используемых констант];

Type[описание используемых типов];

Var [описание используемых переменных];

Begin

// Операторы

Result:= … ;// Присвоение результата вычислений переменной Result

// или <имя функции>:= … ;

End;// Конец функции

Вызов функции: y:=<имя функции > ([список имен формальных параметров без указания их типов]);

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

Type <имя> = function ([список формальных параметров]):<тип рез-тата>;

или

Type <имя> = procedure ([список формальных параметров]);.

Имя процедуры или функции должно быть уникальным в пределах программы. Список формальных параметров необязателен и может отсутствовать. Если же он есть, то в нем перечисляются через точку с запятой имена формальных параметров и их типы. Имеется три вида формальных параметров: параметры-значения, параметры-переменные, параметры-константы. При вызове подпрограммы передача данных для этих видов осуществляется по-разному. Параметры-значения копируются, и подпрограмма работает с их копией, что требует дополнительных затрат памяти. Поэтому рекомендуется использовать параметры-константы или параметры-переменные. При использовании параметров-переменных (в описании перед ними ставится Var) и параметров-констант (перед ними ставится const) в подпрограмму передаются адреса (указатели фактических параметров) и она работает непосредственно с фактическими параметрами. Благодоря этому экономится память, а также организуется передача результата работы подпрограммы вызывающей программе через параметры-переменные. Через параметры-константы этого делать нельзя, т.к. их нельзя менять внутри подпрограммы. В качестве фактических параметров могут использоваться арифметические выражения, если формальный параметр – константа или параметр-значение.

6.2. Использование модулей

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

Заголовок состоит из зарезервированного слова Unit и следующего за ним имени модуля, которое должно совпадать с именем дискового файла. Использование имени модуля в разделе Uses основной программы приводит к установлению связи модуля с основной программой.

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

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

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

Завершающая часть начинается ключевым словом finalization и выполняется в момент окончания работы программы (может отсутствовать).

6.3. Пример написания программы

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

 

Рис. 6.1

6.3.1. Создание модуля

В среде Delphi модули могут создаваться как со своей формой, так и без нее. Для создания нового модуля без своей формы необходимо в меню File выбрать New – Unit. В результате будет создан файл с заголовком Unit Unit2. Имя модуля можно изменить на другое, отвечающее внутреннему содержанию модуля, например Unit Matfu. Для этого необходимо сохранить содуль с новым именем (например Matfu.pas). Следует обратить внимание на то, что имя файла должно совпадать с именем модуля.

6.3.2. Подключение модуля

Для того чтобы подключить модуль к проекту, необходимо в меню Project выбрать опцию Add to Project… и выбрать файл, содержащий модуль. После этого в разделе Uses добавить имя подключаемого модуля – MatFu. Теперь в проекте можно использовать функции, содержащиеся в модуле.

Панель диалога будет иметь следующий вид (рис. 6.1).

Тексты модуля (Листинг 6.1) и вызывающей программы (Листинг 6.2) приведены ниже (получение рекуррентной формулы см. п. 3.3).

Листинг 6.1

unit matfu;

Interface

uses StdCtrls, SysUtils;

Type

fun = function(x : extended):extended; // Объявление типа функция

{Расчет таблицы функции f (табуляция функции)}

procedure Tabl(f:fun;xn,xk:extended; m: word; Mem1 : TMemo);

Implementation

procedure Tabl;

var x,y,h: extended;

i : integer;

Begin

x:=xn; h:=(xn-xk)/m;

for i:=1 to m+1 do begin

y:=f(x);

Mem1.Lines.Add(' x='+FloatToStrf(x,fffixed,8,3)+

' y='+FloatToStrf(y,fffixed,8,3));

x:=x+h;

end;

end;

end. // Конец модуля matfu

Листинг 6.2

unit Unit6;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, Buttons, ExtCtrls, Matfu;

type

TForm1 = class(TForm)

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

Edit1: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Edit4: TEdit;

RadioGroup1: TRadioGroup;

Memo1: TMemo;

BitBtn1: TBitBtn;

BitBtn2: TBitBtn;

procedure FormCreate(Sender: TObject);

procedure BitBtn1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

xn,xk,e : extended;

m : word;

implementation

{$R *.dfm}

 

function sx(x:extended):extended;

var a,n,s : extended;

k : integer;

begin

k:=-1; a:=1; n:=0; s:=1;

try

while (abs(a) > e) do begin

n:=n+1;

a:=-a*x/n;

s:=s+a;

end;

Result:=s;

except

on EInvalidOp do

k:=MessageDlg('Неправильная операция с плавающей точкой. ’+

’ Продолжить вычисления?',mtError,[mbYes,mbNo],0);

on EOverFlow do

k:=MessageDlg('Переполнение при выполне-нии операции с’+

’ плавающей точкой! Продолжить вычисления?',mtError,[mbYes,mbNo],0);

else

k:=MessageDlg('Возникла неизвестная исключительная ситуация!’+

‘ Продолжить вычисления?',mtError,[mbYes,mbNo],0);

end;

case k of

mrYes : Result:=0;

mrNo : Halt(1);

end;

end;

 

function yx(x:extended):extended;

begin

Result:=exp(-x);

end;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

Memo1.Clear;

RadioGroup1.ItemIndex:=0;

Edit1.Text:='0';

Edit2.Text:='2';

Edit3.Text:='6';

Edit4.Text:='0,001';

end;

 

procedure TForm1.BitBtn1Click(Sender: TObject);

begin

Memo1.Clear;

Memo1.Lines.Add('Лаб. раб. №6 ст. гр. 552003 Иванова А.А.');

xn:=StrToFloat(Edit1.Text);

Memo1.Lines.Add(' xn='+FloatToStrF(xn,ffFixed,6,2));

xk:=StrToFloat(Edit2.Text);

Memo1.Lines.Add(' xk='+FloatToStrF(xk,ffFixed,6,2));

m:=StrToInt(Edit3.Text);

Memo1.Lines.Add(' h='+IntToStr(m));

e:=StrToFloat(Edit4.Text);

Memo1.Lines.Add(' e='+FloatToStrF(e,ffFixed,8,5));

case RadioGroup1.ItemIndex of

0 : begin

Memo1.Lines.Add('Расчет S(x)');

Tabl(sx,xn,xk,m,Memo1);

end;

1 : begin

Memo1.Lines.Add('Расчет Y(x)');

Tabl(yx,xn,xk,m,Memo1);

end;

end;

end;

end.

6.4. Выполнение индивидуального задания

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


 

Тема 7. CИСТЕМЫ СЧИСЛЕНИЯ. Программирование с использованием множеств и строк.

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

7.1. Системы счисления

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

где – цифры, p – основание системы счисления. Количество цифр равно p. Для записи цифр в общем случае может быть использован любой набор p символов. Обычно для используют символы 0…9, для добавляют буквы латинского алфавита A, B, C, D, E, F которые в десятичной системе представляют числами 10, 11, 12, 13, 14, 15. Например

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

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

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

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

7.2 Тип множество

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

Для работы с множествами в Паскале введен тип переменных set of:

type <имя типа>=set of <базовый тип>;

var A,B,C: имя типа;

здесь <базовый тип> - любой порядковый тип кроме Word, Integer, Longint, т.е. (перечисляемый, интервальный, char, byte, boolean).

Множество-константа: [i1, i2, …, ik], где ik – элементы множества.

7.2.1 Операции над множествами

Над переменными типа множеств допустимы операции присваивания сложения, вычитания, умножения. Эти операции дополняют две процедуры

Include (S, i); - добавление в множество S элемента i, базового типа;

Exclude (S, i); - исключение из множества S элемента i, базового типа.

Эти операции выполняются значительно быстрее, чем их эквивалентные s:=s+[i]; s:=s-[i];

Операции проверки условия

Результат c=d будет true если множества одинаковы;

Результат c< > d будет true если множества не одинаковы;

Результат c>=d будет true если все элементы d принадлежат с;

Результат c<=d будет true если все элементы с принадлежат d;

Результат iin c будет true если элемент i принадлежит с.

7.2.2 Примеры работы с множествами

1. Ввод n элементов множества:

......

Var A:set of char;

s:char;

n:Word;

Begin

A:=[ ];// Очистка множества

for i:=1 to n do begin

read(s);

A:=A+[s];

end;

end.

2. Распечатать содержимое множества:

......

Var B:set of 1..100;

k:byte;

Begin

for k:=1 to 100 do if k in B then Write(k);

......

end.

3. Сокращение проверок в операторе if:

Оператор if (k=5) or (k=1) or (k=8) then ....можно записать более изящно:

if k in [5,1,8] then ....

7.3. Типы данных для работы со строками и основные операции

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

Var

s1 : String[N] ; // Короткая строка, N £ 255

s2 : ShortString; // Короткая строка, N = 255

s3 : String; // Длинная строка, N £ 2 ГБайт

s4 : WideString; // Широкая строка

s5 : PChar; // Нуль-терминальная строка

Короткие строки занимают фиксированное количество байт. Строка типа String[N] может содержать nt (0≤nt≤255) символов. Под переменную типа String[N] отводится N+1 байт. В s1[0] содержится текущая длина строки. Строка ShortString эквивалентна String[255].

Длинная строка типа String. При работе с этим типом данных, в отличие от String[N] память выделяется по мере необходимости (динамически) и может занимать практически всю доступную программе память. Фактически переменные этого типа являются типизированными указателями.

Широкая строка типа WideString. Введена для обеспечения совместимости с компонентами, основанными на OLE-технологии. От типа String отличается только тем, что для представления каждого символа используется не один, а два байта.

Нуль-терминальная строка типа PChar. Представляет собой цепочку символов, ограниченную символом #0. Максимальная длина строки ограничена только доступной программе памятью. Нуль-терминальные строки широко используются при обращениях к API-функциям Windows (API – Application Program Interface – интерфейс прикладных программ).

К каждому элементу строки можно обращаться с помощью индекса, аналогично обращению к элементу массива символов: s[i]:=s[j].

Основные операции над переменными строкового типа: присвоение, сцепление (s:=s1+’ fg’+s2), сравнение (>, ³, =, <, ≤). Большей считатется та, строка у которой больше первый (второй, трений, …) символ.

7.4 Некоторые процедуры и функции обработки строк

Процедуры:

Delete(St:String; pz,n:integer); - удаляет из строки n символов начиная с позиции pz.

Insert(St,St1;string;pz:integer); - вставляет строку St внутрь строки St1 начиная с позиции pz.

Функции:

St:=Copy(St1,pz,n); - выделяет из строки St1 подстроку St из n символов начиная с позиции pz, при этом St1 сохраняется.

N:=Length(St); - определяет текущую длину строки.

pz:=pos(St,St1); - определяет номер позиции, начиная с которой внутри строки St1 расположена строка St, если внутри St1 нет St тогда pz=0.

Описание функций преобразования чисел в строки и наоборт помещено в Приложении 1.

7.5 Пример написания программы

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

Панель диалога будет иметь вид (рис. 7.1).

Рис. 7.1

Текст программы приведен на Листинге 7.1.

Листинг 7.1.

unit Unit7;

Interface

Uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,

Forms, Dialogs, StdCtrls;

Type

TForm1 = class(TForm)

Edit1: TEdit;

Label2: TLabel;

Edit2: TEdit;

Label1: TLabel;

procedure FormCreate(Sender: TObject);

procedure Edit1KeyPress(Sender: TObject; var Key: Char);

private{ Private declarations }

public{ Public declarations }

end;

varForm1: TForm1;

Implementation

{$R *.dfm}

 

Function Krz(St:string):Word; // Подсчет кол-ва различныx символов

Var a : set of char;

m,i : Word;

Begin

m:=0; a:=[];

for i:=1 to Length(St do