Ситкин. Информатика. Программирование в DELPHI
.pdfProcedure TForm1.Button1Click(Sender: TObject); var Cod:integer;
Begin
Val(Edit1.Text, n, Cod); //проверка синт-са и ввод n if (Cod < > 0) or (n<2) then //если ошибка, - то begin
Button2.Enabled:=False; //блокировка кнопки 2
ShowMessage('ошибка размера матрицы');
Exit; //досрочное завершение процедуры
end;
with StringGrid1 do //оператор присоединения -
begin //вып-е неск. действий с одним компонентом |
|
|
RowCount:=n; |
//установление числа строк |
Рис. 9.6 |
ColCount:=n; |
//установление числа столбцов |
|
Visible:=True; |
//сделать StringGrid1 видимым |
|
end; //конец действий, выполняемых с компонентом
Button2.Enabled:=True; //активация кнопки 2
End; //конец первой процедуры
Procedure TForm1.Button2Click(Sender: TObject); var x:array of array of real; i, j:byte; Cod:integer;
Begin
Label2.Caption:=''; //очистка поля вывода при повт. щелчке SetLength(x, n, n); //выделение памяти под матрицу
for i:=0 to n 1 do //внешний цикл (перебор строк) begin //начало тела внешнего цикла
for j:=0 to n 1 do //вложенный цикл (перебор столбцов) begin //начало тела вложенного цикла
Val(StringGrid1.Cells[i, j], x[i, j], Cod); //ввод xij
if Cod <>0 then begin //если ошибка синтаксиса, то Рис. 9.7
Label2.Caption:=''; //очистка поля вывода
ShowMessage('ошибка синтаксиса в матрице'); SetLength(x, 0, 0); Exit; //высвоб. памяти и выход
end; //конец действий для случая синтакс. ошибки
if i=j then x[i,j]:=2*x[i, j]; //удв-е элемента, если он на главной диагон.
Label2.Caption:=Label2.Caption+#9+FloatToStr(x[i, j]); //вывод xij
end; //конец тела вложенного цикла
Label2.Caption:=Label2.Caption+#13; //перевод строки вывода
end; //конец тела внешнего цикла
SetLength(x, 0, 0); //высвобождение памяти хранения элементов матрицы End; END. //конец второй процедуры и конец модуля проекта
111
Сортировка массивов
Сортировка массива процесс упорядочивания набора одно-
типных данных по возрастанию или убыванию значения какого-либо признака. При сортировке числового массива его элементы меняются местами таким образом, что их значения оказываются упорядочен-
ными по возрастанию или убыванию. Сортировка является важным действием над массивами в системах поиска данных, т.к. в отсорти-
рованных массивах процесс поиска значительно ускоряется.
Существует много алгоритмов сортировки, которые отличают-
ся друг от друга по скорости работы, что заметно на больших масси-
вах, для небольших массивов можно использовать простые из них.
Сортировка методом обмена (метод «пузырька»)
Суть данного метода сортировки по возрастанию состоит в сле-
дующем. Каждый элемент массива, начиная с первого и заканчивая предпоследним, сравнивается со следующим элементом. Если теку-
щий элемент больше следующего, то элементы меняются местами.
Циклический процесс просмотра всех элементов массива повторяется столько раз, сколько элементов в массиве минус единица. Таким об-
разом более «лёгкие» элементы массива постепенно продвигаются к началу («всплывают»), а более «тяжёлые» к концу («тонут»). Этот алгоритм простой, но очень медленный. Его можно несколько уско-
рить, если массив изначально частично отсортирован. Для этого вво-
дится переменная-признак, контролирующая процесс обмена. Если при очередном просмотре массива не было ни одной перестановки, то это значит, что массив отсортирован и, в соответствии со значением переменной-признаком, процесс завершается.
112
На рис. 9.8 представлена блок-схема описанного алгоритма сор-
тировки. Чтобы не отвлекаться на второстепенные действия ввода и вывода массива, процесс сортировки представлен в виде пользова-
тельской процедуры, причём с формальным открытым параметром-
массивом, что позволит сортировать передаваемые в процедуру фак-
тические массивы произвольной длины. Напомним, что нумерация элементов у такого массива начинается с нуля. Для возможности воз-
врата в вызывающий блок, массив сделан параметром-переменной.
procedure Sort_obmen(var t:array of real);
начало
var buf:real; //для временного хранения элемента
f = false
k:byte;
k = 0
f:boolean; //переменная-признак
k число нет
э-ов 2
да
tk tk+1 нет
да
buf = tk
tk = tk+1 tk = buf
f = true
/обмен был/
k = k + 1
нет |
f true |
|
да
конец
Рис. 9.8
begin
repeat //внешний цикл контроля обменов f:=false; //пусть обменов не было
for k:=0 to high(t)-1 do //от начального до
//предпоследнего элемента массива (напомним,
//ф-я high сама отнимает единицу от числа эл-ов) if t[k]>t[k+1] then //если текущий элемент begin //больше следующего, то поменять их
buf:=t[k]; //местами с использованием t[k]:=t[k+1]; //буферной переменной
t[k+1]:=buf;
f:=true; //обмен состоялся
end;
until not f; //до тех пор, пока обмен не состоялся
end;
113
Сортировка методом выбора Суть данного метода сортировки по возрастанию состоит в сле-
дующем. Начиная с первого элемента, просматривается массив, нахо-
дится минимальный элемент, который ставится на место первого, а |
||||
|
начало |
|
|
первый занимает место минимального. Затем, |
|
|
|
|
|
|
|
|
|
начиная со второго элемента, просматривается |
|
m = 0 |
|
|
|
|
|
|
оставшаяся часть массива, находится мини- |
|
|
|
|
|
|
|
|
|
|
мальный элемент, который меняется местами |
|
|
|
|
|
|
m число |
нет |
|
|
|
э-ов 2 |
|
|
со вторым, и т.д. до предпоследнего элемента. |
|
да |
|
|
Блок-схема описанного алгоритма представ- |
|
|
|
|
|
|
min = m |
|
|
|
|
|
|
лена на рис. 9.9. Как и в предыдущем методе, |
|
|
|
|
|
|
|
n = m + 1 |
|
|
процесс сортировки оформим в виде пользо- |
|
|
|
|
|
|
n число |
нет |
||
|
вательской процедуры с открытым массивом. |
|||
|
э-ов 1 |
|
|
|
|
да |
|
|
procedure Sort_vubor(var t:array of real); |
|
tn < tmin |
нет |
var buf:real; |
|
|
|
|
|
|
|
да |
|
|
min, m, n:byte; |
min = n
n = n + 1
buf = tm
tm = tmin
tmin = buf
m = m + 1
конец
Рис. 9.9
begin
for m:=0 to high(t)-1 do //от начального до
begin //предпоследнего элемента массива min:=m; //пусть номер миним. эл-та равен m
for n:=m+1 to high(t) do //цикл поиска миним. if t[n]<t[min] then min:=n; //элемента
buf:=t[m]; //перестановка первого элемента t[m]:=t[min]; //в оставшейся последовательности t[min]:=buf; //с минимальным через буф. пер-ную
end;
end;
114
Пример 9.3 |
|
|
|
|
|
|
|
|
|
|
|
|
||
Разработаем проект для построчной сортировки по возрастанию |
||||||||||||||
начало |
|
|
элементов двумерного массива пе- |
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
||
m = число |
|
|
ременной длины строк. |
|
|
|
||||||||
|
|
|
Разделим задачу на две части. |
|||||||||||
строк |
|
|
|
|||||||||||
выделить па- |
|
|
В первой части щелчком по кнопке |
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
||
мять под m |
|
|
Button1 сформируем таблицу String- |
|||||||||||
элементов |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Grid для ввода элементов, которую |
|||||||||||
номер строки |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = 0 |
|
|
изначально |
сделаем |
невидимой. |
|||||||||
|
|
|
Для |
задания |
пользователем |
числа |
||||||||
i m 1 |
нет |
число столб.=m |
элементов |
каждой |
строки |
разме- |
||||||||
число стр.=max |
||||||||||||||
|
|
таблица видна |
стим на форме |
компонент |
Memo, |
|||||||||
да |
|
|
||||||||||||
ввод yi эл-та |
|
кнопка сорти- |
тем |
самым |
будет |
определено |
и |
|||||||
c проверкой |
|
ровки строк |
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|||
синтаксиса |
|
доступна |
число |
строк |
двумерного |
массива |
||||||||
|
|
|||||||||||||
|
|
1 |
(таблицы). На рис. 9.10 изображена |
|||||||||||
ошибка |
|
|
||||||||||||
да |
|
|
|
|
|
|
|
|
|
|
|
|
||
или yi 2 |
|
|
блок-схема алгоритма первой части |
|||||||||||
нет |
|
|
(обработка |
события |
Button1Click). |
|||||||||
|
|
кнопка сорти- |
||||||||||||
|
нет |
|
|
|
|
|
|
|
|
|
|
|
||
i = 0 |
ровки строк |
По |
числу |
заполненных |
строк |
в |
||||||||
|
||||||||||||||
|
|
недоступна |
|
|
|
|
|
|
|
|
|
|
|
|
да |
|
|
Memo выделяется память под мас- |
|||||||||||
max = y0 |
|
ошибка |
|
|
|
|
|
|
|
|
|
|
|
|
|
длины |
сив хранения длин строк таблицы. |
||||||||||||
|
|
строки |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
В теле цикла, контролируя синтак- |
|||||||||||
|
нет |
высвободить |
сис |
и |
длину, |
вводятся |
размеры |
|||||||
yi > max |
память из-под |
|||||||||||||
|
|
m элементов |
строк |
в |
массив, |
и |
параллельно |
|||||||
да |
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
1 |
определяется максимальное значе- |
|||||||||||
max = yi |
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
конец |
ние массива. Вне тела формируется |
|||||||||||
|
|
|
||||||||||||
i = i + 1 |
|
|
размер таблицы по числу строк в |
|||||||||||
|
|
Memo и максимальному числу эле- |
||||||||||||
|
|
|
||||||||||||
|
|
Рис. 9.10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
начало |
|
|
|
|
|
|
|
|
|
номер строки |
|
|
|
|
i = 0 |
|
|
|
|
|
|
|
|
|
i m 1 |
нет 1 |
|
|
|
да |
|
|
|
|
выделить па- |
|
|
|
|
мять под i-ую |
|
|
|
|
строку |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
номер элемента |
|
|
|
|
в i-ой строке |
|
|
|
|
j = 0 |
|
|
|
|
|
|
|
|
|
j yi 1 |
нет |
|
|
|
|
|
|
|
|
да |
|
|
|
|
ввод zj эл-та |
|
|
j = j + 1 |
|
c проверкой |
|
|
|
|
синтаксиса |
|
|
нет ошибка
синтакси-
ошибка да са
синтаксиса в таблице
1 |
|
сортировка |
|
|
|
|
|
|
|
|
|
i-ой строки |
|
|
высвободить |
|
|
|
|
|
|
|
|
|
память из-под |
|
|
|
|
|
номер элемента |
|
||
i-ой строки |
|
|
||
|
в i-ой строке |
|
|
|
|
|
|
|
|
|
|
|
||
конец |
|
j = 0 |
|
|
|
|
|
|
|
|
j yi 1 |
нет |
||
|
|
|||
|
|
|
|
|
|
|
да |
|
|
j = j + 1 |
|
вывод zj |
|
|
|
|
|
|
|
i = i + 1 |
перевод |
|
строки |
|
|
|
вывода |
Рис.9.11 |
|
|
ментов одной из строк. Сама таблица становится видимой, а кнопка сортировки строк Button2
(изначально недоступная) до-
ступной. Нарушение допусти-
мости размера любой из строк приводит к выводу сообщения об ошибке, высвобождению па-
мяти из-под массива хранения длин строк и недоступности кнопки Button2.
Во второй части задачи (обработка события Button2Click),
рис. 9.11, во внешнем цикле вы-
деляется память под элементы текущей строки таблицы. Затем в первом вложенном цикле они записываются в одномерный массив (если нет ошибок), вне тела этого цикла сортируются процедурой Sort_obmen (с от-
крытым массивом, т.к. строк не-
сколько и они разных длин) и во втором вложенном цикле выво-
дятся в компонент Label. Затем всё повторяется для следующей строки и т.д.
116
IMPLEMENTATION
{$R *.dfm}
var m:byte; //глобальная переменная, т.к. используется в двух процедурах y:array of byte; //глобальный динамический массив длин строк
Procedure Sort_obmen(var t:array of real); //пользовательская процедура
var buf:real; k:byte; f:boolean;
Begin repeat
f:=false;
for k:=0 to high(t)-1 do if t[k]>t[k+1] then begin
buf:=t[k]; t[k]:=t[k+1]; t[k+1]:=buf; f:=true;
end;
until not f;
End; //конец пользовательской процедуры сортировки одномерного массива
Procedure TForm1.Button1Click(Sender: TObject); var i, max:byte; Cod:integer;
Begin
m:=Memo1.Lines.Count; //определение числа строк в Memo
SetLength(y, m); //выделение памяти под массив хранения длин строк for i:=0 to m-1 do //цикл перебора строк в Memo
begin //начало тела цикла
Val(Memo1.Lines[i], y[i], Cod); //ввод в массив длины i-ой строки
if (Cod<>0) or (y[i]<2) then //если синт. ошибка или недопуст. длина
begin //то
Button2.Enabled:=False; //кнопка сортировки строк недоступна
ShowMessage('ошибка длины строки'); //вывод сообщения
SetLength(y,0); Exit; //высвободить память и досрочный выход end; //конец действий для случая ошибки
if i=0 then max:=y[0]; //пусть нулевая строка максимальной длины if y[i]>max then max:=y[i]; //поиск самой длинной строки
end; //конец тела цикла
with StringGrid1 do begin //формирование таблицы для ввода значений
RowCount:=m;
ColCount:=max;
Visible:=True;
end;
Button2.Enabled:=True; //кнопка сортировки строк доступна End; //конец процедуры формирования таблицы
117
Procedure TForm1.Button2Click(Sender: TObject); var i, j:byte; Cod:integer; z:array of real;
Begin
Label2.Caption:=''; //очистка поля вывода при повторном щелчке for i:=0 to m-1 do //внешний цикл – перебор строк таблицы begin //начало тела внешнего цикла
SetLength(z, y[i]); //выделение памяти под i-ую строку
for j:=0 to y[i]-1 do //первый вложенный цикл – ввод i-ой строки таблицы begin //начало тела первого вложенного цикла
Val(StringGrid1.Cells[j, i],z[j], Cod); //ввод j-го элемента i-ой строки
if Cod<>0 then begin //если синтаксическая ошибка
Label2.Caption:=''; //очистка поля вывода
ShowMessage('ошибка синтаксиса в таблице'); SetLength(z, 0); Exit; //высвоб. память и доср. выход
end; //конец действий для случая синтаксич. ошибки end; //конец тела первого вложенного цикла
Sort_obmen(z); //сортировка элементов i-ой строки таблицы
for j:=0 to y[i]-1 do //второй влож. цикл – вывод отсортиров-ой строки
Label2.Caption:= Label2.Caption+#9+FloatToStr(z[j]); Label2.Caption:= Label2.Caption+#13; //перевод строки вывода
end; //конец тела внешнего цикла
SetLength(z, 0); //высвобождение памяти из-под массива значений таблицы end; END. //конец процедуры построчной сортировки и конец модуля
Память из-под массива y длин строк не высвобождалась, т.к. она выделяется во второй процедуре, а массив используется и в третьей,
кроме того, возможен повторный щелчок пользователем по кнопке Button2 без щелчка по Button1, поэтому и в третьей процедуре освобо-
дить память нельзя. В данном примере представляет интерес вопрос выделения памяти, по-
этому он отражён в блок-
схемах, что необычно. На рис. 9.12 представлен пример рабо-
ты приложения.
Рис. 9.12
118
Задание
Разработать проект для ввода с формы элементов прямоуголь-
ной матрицы задаваемого пользователем размера и
1.Умножить элементы 1-ой строки и 1-го столбца на коэффициент.
2.Найти суммы элементов каждой строки и всех элементов.
3.Найти суммы элементов каждого столбца и всех элементов.
4.Найти столбец с наименьшей суммой элементов.
5.Найти строку с наибольшей суммой элементов.
6.Определить есть ли заданный элемент, указать его положения.
7.Определить число положительных элементов в каждой строке.
8.Определить число нечётных элементов в каждом столбце.
9.Найти наибольший элемент, указать его положение.
Содержание отчёта
цель работы и задание;
блок-схемы алгоритмов формирования и обработки матрицы;
текст модуля проекта;
пример работы приложения с указанием компонентов формы;
выводы по работе.
Контрольные вопросы |
|
1. Приведите примеры описаний |
3. Какое значение получит k? |
двумерных массивов, почему для |
var i, j, k: byte; |
их обработки требуются кон- |
i:=1; k:=0; |
струкции с вложенными циклами? |
while i<3 do begin |
2. Как выделить память под не- |
inc(i); |
прямоугольный двумерный дина- |
for j:=1 to i do inc(k); |
мический массив? |
end; |
119
Лабораторная работа № 10
ВНЕШНИЕ ФАЙЛЫ
Цель работы приобретение умений организации обмена данными между приложением и внешними файлами.
Во всех предыдущих проектах результаты работы приложений представлялись на форме и были доступны только до момента закрытия формы. В случае необходимости последующего использования полученных результатов или их долговременного хранения, эти результаты в виде данных приложение должно записать в файл, сохраняемый на диске компьютера. Само приложение для своей работы также может получать исходные данные из файла, который был создан заранее. Такие файлы будем называть внешними.
Физические и логические файлы
Файл именованный набор данных одного типа практически произвольной длины, хранящихся на внешнем носителе данных в областях памяти, разделённых на кластеры. Размер файла ограничивается только ёмкостью носителя данных. Организация хранения зависит от конкретного носителя. Файл в таком понимании называют физическим файлом. Для организации работы с физическими файлами в языках программирования предусмотрены специальные структуры данных тип данных файл. Файл в таком понимании называют логическим файлом (файловой переменной), так как в этом случае он представляет собой лишь логическую модель хранения данных, не зависящую от организации конкретного физического файла.
120