Работа с двумерными числовыми массивами











Содержание
Введение
1. Теоретическая часть
1.1 Общее понятие о массивах
1.1.1 Определение и область применения
1.1.2 Специфические типы массивов
1.1.3 Реализация массивов
1.1.4 Достоинства массивов
1.1.5 Недостатки массивов
1.2 Массивы в Object Pascal
1.2.1 Статические массивы
1.2.2 Динамические массивы
1.2.3 Функции для работы с массивами
1.3 Использование массивов в рамках проекта
2. Практическая часть
2.1 Постановка задачи
2.2 Функциональная структура приложения
2.3 Описание модулей
2.3.1 Модуль MatrixOperations
2.3.2 Модуль fileIO
2.4 Модуль form
3. Эксплуатационная документация
3.1 Описание применения
3.2 Руководство оператора
Выводы
Приложения
Введение
В вычислительной технике данные обычно отличают от программ. Программа является набором инструкций, которые детализируют вычисление или задачу, производимую компьютером. Данными же традиционно называется всё, что не выступает в роли программы. В языках высокого уровня данные воплощаются в виде переменных.
Часто перед программистами встают задачи, связанные с обработкой стразу множества значений данных. В таких случаях крайне неудобно для хранения каждого значения заводить отдельную именованную переменную. Для такой ситуации синтаксис многих языков предусматривает создание массивов – множеств переменных, доступ к которым осуществляется посредством одного имени (имени массива) и одного или нескольких индексов.
Данная курсовая работа рассматривает методики использования многомерных массивов в среде Delphi. Она демонстрирует использование встроенных возможностей языка, а так же применение широко известных операций над массивами, таких как последовательный обход значений, сортировка, циклический сдвиг.
1. Теоретическая часть
1.1 Общее понятие о массивах
1.1.1 Определение и область применения
Массив (или индексный массив), это именованный набор однотипных переменных, расположенных в памяти непосредственно друг за другом, доступ к которым осуществляется по индексу. Количество используемых индексов массива может быть различным. Массивы с одним индексом называют одномерными, с двумя — двумерными и т. д. Одномерный массив нестрого соответствует вектору в математике, двумерный — матрице. Массивы хорошо подходят для отображения таких объектов реального мира, как строки (массивы символов), наборы координат, таблицы данных, математические множества и вообще множества однотипных объектов.
Без использования массивов не обойтись в таких областях программирования как работа с базами данных, компьютерная графика, визуализация результатов научных экспериментов, статистический анализ. Массивы являются входными и выходными параметрами процедур сортировки.
Поддержка индексных массивов (свой синтаксис объявления, функции для работы с элементами и т. д.) есть в большинстве высокоуровневых языков программирования. Максимально допустимая размерность массива, типы и диапазоны значений индексов, ограничения на типы элементов определяются языком программирования и/или конкретным транслятором.
В языках программирования, допускающих объявления программистом собственных типов, как правило, существует возможность создания типа «массив». В определении такого типа может указываться размер, тип элемента, диапазон значений и типы индексов. В дальнейшем возможно определение переменных созданного типа. Все такие переменные-массивы имеют одну структуру. Некоторые языки поддерживают для переменных-массивов операции присваивания (когда одной операцией всем элементам массива присваиваются значения соответствующих элементов другого массива).
1.1.2 Специфические типы массивов
Динамическим называется массив, размер которого может меняться во время исполнения программы. Для изменения размера динамического массива язык программирования, поддерживающий такие массивы, должен предоставлять встроенную функцию или оператор. Динамические массивы дают возможность более гибкой работы с данными, так как позволяют не прогнозировать хранимые объёмы данных, а регулировать размер массива в соответствии с реально необходимыми объёмами. Обычные, не динамические массивы называют ещё статическими.
Гетерогенным называется массив, в разные элементы которого могут быть непосредственно записаны значения, относящиеся к различным типам данных. Массив, хранящий указатели на значения различных типов, не является гетерогенным, так как собственно хранящиеся в массиве данные относятся к единственному типу — типу «указатель». Гетерогенные массивы удобны как универсальная структура для хранения наборов данных произвольных типов. Отсутствие их поддержки в языке программирования приводит к необходимости реализации более сложных схем хранения данных. С другой стороны, реализация гетерогенности требует усложнения механизма поддержки массивов в трансляторе языка.
Многомерные массивы, как правило, реализованные как одномерные массивы, каждый элемент которых является ссылкой на другой одномерный массив.
1.1.3 Реализация массивов
Стандартным способом реализации статических массивов с одним типом элементов является следующий:
Под массив выделяется непрерывный блок памяти объёмом
S*m1*m2*m3…mn,
где S — размер одного элемента, а m1…mn — размеры диапазонов индексов (то есть количество значений, которые может принимать соответствующий индекс).
При обращении к элементу массива A[i1, i2, i3, … in] адрес соответствующего элемента вычисляется как
B+S*(i1p*m1+i2p*m2+…+i(n-1)p*mn-1+inp),
где B — база (адрес начала блока памяти массива), ikp-значение k-го индекса, приведённое к целому с нулевым начальным смещением.
Таким образом, адрес элемента с заданным набором индексов вычисляется так, что время доступа ко всем элементам массива одинаково. Первый элемент массива, в зависимости от языка программирования, может иметь различный индекс. Различают три основных разновидности массивов: с отсчетом от нуля (zero-based), с отсчетом от единицы (one-based) и с отсчетом от специфического значения заданного программистом (n-based).
Отсчет индекса элемента массивов с нуля более характерен для низкоуровневых языков программирования, однако этот метод был популяризирован в языках более высокого уровня языком программирования С.
Более сложные типы массивов — динамические и гетерогенные — реализуются сложнее.
1.1.4 Достоинства массивов
Быстрый доступ к элементам, причём время доступа не зависит от длины массива
Элементы расположены в памяти непосредственно друг за другом, что облегчает копирование и перемещение всего массива целиком
Отсутствие необходимости в дополнительной памяти
1.1.5 Недостатки массивов
для статического массива — отсутствие динамики, невозможность удаления или добавления элемента без сдвига других
для динамического и/или гетерогенного массива — более низкое (по сравнению со статическим) быстродействие и дополнительные накладные расходы на поддержку динамических свойств и/или гетерогенности.
при работе с массивом в отсутствие дополнительных средств контроля — угроза выхода за границы массива и повреждения «чужих» данных
1.2 Массивы в Object Pascal
Ключевое слово Array используется для определения одномерных и многомерные массивов данных. В Object Pascal существует два типа массивов
1.2.1 Статические массивы
Создаются с заранее определёнными, неизменяемыми размерами. Могут быть одномерными, или многомерными – во втором случае представляя из себя массив массивов (массивов массивов и так далее).
Величина каждой размерности определяется двумя способами, которые могут свободно сочетаться при определении многомерного массива:
Тип Index, где Index – целый тип, обычно Byte или Word. Диапазон типа определяет диапазон размерности, например 0..255 для Byte
Ordinal..Ordinal. Таким образом, можно непосредственно задать диапазон размерности, например 12..44.
Например:
1var
2wordArray : Array[Word] of Integer; // размер равен High(Word)
3multiArray : Array[Byte, 1..5] of char; // двумерный массив
4rangeArray : Array[5..20] of string; // размер равен 16
1.2.2 Динамические массивы
У для динамических массивов память заранее не выделяется, создаётся только указатель. У таких массивов необходимо задавать размер перед использованием. Например
SetLength(dynArray, 5);
устанавливает длину первой размерности массива dynArray в пять, при этом выделяется необходимая память. Для всех динамических массивов минимальный индекс равен нулю.
Отдельные подмассивы многомерного динамического массива могут иметь разные размеры, так как по сути они являются отдельными массивами.
Пример определения динамических массивов:
var
5byteArray: Array of Byte; // одномерный массив
6multiArray: Array of Array of string; // двумерный массив
1.2.3 Функции для работы с массивами
Copy (Source : array; StartIndex, Count : Integer ) : array – создает копию части массива.
High (type or variable): Ordinal type - возвращает верхнюю границу диапазона значений массива.
Length (const SourceArray: array): Integer - возвращает число элементов в массиве.
Low (type or variable): Ordinal type - возвращает нижнюю границу диапазона значений массива
SetLength (var ArrayToChange: Array type; Dim1Length: Integer {;Dim2Length: Integer; ...}) - изменяет размер динамического массива. Для многомерных массивов может принимать более одного параметра длины.
Slice (SourceArray: array; Count: Integer): array - создает часть массива для передачи его как параметр в процедуру или функцию.
При использовании динамических массивов необходимо помнить, что вызовы SetLength выделяют для массива дополнительную память, которую необходимо освобождать после окончания работы с массивом. Для этого ему нужно присвоить специальное значение nil.
1.3 Использование массивов в рамках данного проекта
Работа со статическими массивами более проста и менее затратна в плане использования ресурсов компьютера, но так как в задании нигде не оговариваются конкретные размеры исходных матриц, то было принято решение построить программу ну основе использования динамических массивов.
Приложение построено таким образом, что размер используемой матрицы можно менять во время выполнения, так же он автоматически определяется при загрузке исходных данных из файла. Размеры динамических массивов внутри программы изменяются соответствующим образом автоматически.
2. Практическая часть
2.1 Постановка задачи
Приложение предназначено для выполнения специфической обработки матриц. Исходные матрицы должны загружаться из файла, либо вводиться непосредственно в элементы интерфейса приложения.
Граничные условия на вводимые данные таковы:
Размеры матрицы должны лежать в пределах [1; 2147483647]. Если введено число, выходящее из этого диапазона, либо значение, не являющееся целым числом, то размер устанавливается равным единице.
Элементы матрицы должны лежать в пределах [-2147483648; 2147483647]. Если какой-то из элементов лежит вне этого диапазона, либо введёно значение, не являющееся целым числом, то элемент устанавливается равным нулю.
В заданиях, связанных с подсчётом сумм элементов, результат может лежать в пределах [-9223372036854775808; 9223372036854775807]. Если сумма выходит за эти пределы, результат не определён.
2.2 Функциональная структура программы
Программа разделена на три модуля:
MatrixOperations – различные операции с матрицей
fileIO – сохранение матрицы в файл/ чтение матрицы из файла
form – форма приложения, процедуры обмена данными между массивами и элементами формы. Структура связей модулей такова:
2.3 Описание модулей
2.3.1 Модуль MatrixOperations
Это основной модуль программы, содержащий процедуры для выполнения матричных операций, предусмотренных заданием.
Определяет повсеместно используемые типы «матрица» и «вектор»:
type
7TVector = array of integer;
8TMatrix = array of TVector;
Поиск максимальных элементов в матрице.
Процедура GetMaxVals, которая, перебирая все строки матрицы, находит в каждой максимальный элемент, записывает его значение в массив maxVal, а его номер столбца в массив maxValCol. Предварительно процедура выделяет необходимую намять для этих массивов. Листинг:
1 {
формирует массив максимальных элементов maxVal и массив номеров столбцов,
9содержащих максимальные элементы maxValCol на основе матрицы arr
10}
11procedure GetMaxVals(var maxVal, maxValCol: TVector; const arr: TMatrix);
12var
13RowN, ColN, maxInRow: integer;
14begin
15//выделим необходимый для каждого массива объём памяти
16SetLength(maxVal, high(arr)+1);
17SetLength(maxValCol, high(arr)+1);
18for RowN:= low(arr) to high(arr) do
19begin//для каждой строки
20maxVal[RowN]:= low(integer);//по умолчанию максимальное значение -2147483648
21maxValCol[RowN]:= -1;//по умолчанию номер столбца с макс элементом -1
22for ColN:= low(arr[RowN]) to high(arr[RowN]) do
23begin//для каждого столбца
24if arr[RowN, ColN] > maxVal[RowN] then
25begin//если элемент больше макс значения, то
26maxVal[RowN]:= arr[RowN, ColN];//максимальное значение приравняем элементу
27maxValCol[RowN]:= ColN;//номер столбца приравняем текущему столбцу
28end;
29end;
30end;
31end;
Суммы элементов между диагоналями
Далее идут функции, осуществляющие подсчёт сумм элементов выше и ниже пересечения диагоналей, а так же смену местами этих элементов. Главной диагональю считается множество элементов матрицы, индексы которых совпадают, побочной диагональю считается та, которая идёт по диагонали из нижнего левого угла матрицы.
Функции GetSumAbove и GetSumBelow проходят соответствующие половины строк матрицы, для каждой строки высчитывая диапазон столбцов, из которых нужно суммировать элементы:
{возвращает сумму элементов выше пересечения диагоналей матрицы arr}
32function GetSumAbove (const arr: TMatrix): Int64;
33var
34RowN, ColN: integer;
35lastColumn: integer;//номер столбца, содержащего элемент дальней диагонали минус 1
36begin
37Result:= 0;
38for RowN:= 0 to (high(arr) div 2) do
39begin//с нулевой, по средюю строку
40lastColumn:= high(arr)-RowN-1;//определим номер столбца последнего элемента, подлежащего суммированию
41//если число столбцов меньше числа строк, то последний столбец может оказаться ближе
42if lastColumn > high(arr[RowN]) then lastColumn:= high(arr[RowN]);
43for ColN:= RowN+1 to lastColumn do //просуммируем элементы в высчитаных пределах
44Result:= Result + arr[RowN, ColN];
45end;
46end;
47{возвращает сумму элементов ниже пересечения диагоналей матрицы arr}
48function GetSumBelow(const arr: TMatrix): Int64;
49var
50RowN, ColN: integer;
51lastColumn: integer;//номер столбца, содержащего элемент дальней диагонали минус 1
52begin
53Result:= 0;
54for RowN:= (high(arr) div 2)+1 to high(arr) do
55begin//со средней по последнюю строку
56lastColumn:= RowN-1;//определим номер столбца последнего элемента, подлежащего суммированию
57//если число столбцов меньше числа строк, то последний столбец может оказаться ближе
58if lastColumn > high(arr[RowN]) then lastColumn:= high(arr[RowN]);
59for ColN:= high(arr)-RowN+1 to lastColumn do //просуммируем элементы в высчитаных пределах
60Result:= Result + arr[RowN, ColN];
61end;
62end;
Процедура SwapAboveBelow таким же образом, как функция GetSumAbove, определяет, какие элементы лежат выше пересечения диагоналей, но не суммирует их, а каждый меняет местами с элементом того же столбца, симметричным текущему относительно верхней и нижней границ матрицы. Для смены используется вспомогательная процедура swap для целых чисел, определённая в этом же модуле:
{вспомогательная процедура: поменять местами два целых числа}
63procedure swap(var first, second: integer);
64var tmp: integer;
65begin
66tmp:= first;
67first:= second;
68second:= tmp;
69end;
70{поменять местами элементы выше и ниже пересечения диагоналей матрицы arr}
71procedure SwapAboveBelow (var arr: TMatrix);
72var
73RowN, ColN: integer;
74lastColumn: integer;//номер столбца, содержащего элемент дальней диагонали минус 1
75begin
76for RowN:= 0 to (high(arr) div 2) do
77begin//с нулевой, по средюю строку
78lastColumn:= high(arr)-RowN-1;//определим номер столбца последнего элемента, подлежащего суммированию
79//если число столбцов меньше числа строк, то последний столбец может оказаться ближе
80if lastColumn > high(arr[RowN]) then lastColumn:= high(arr[RowN]);
81for ColN:= RowN+1 to lastColumn do//для каждого элемента в высчитаных пределах
82//поменяем его местами с элементом того же столбца, отстаящем на то же число строк, но от нижней границы матрицы
83swap(arr[RowN, ColN], arr[high(arr) - RowN, ColN]);
84end;
85end;
Циклический сдвиг строк
Далее функция CircuarShift, осуществляющая циклический сдвиг строк матрицы вверх, или вниз. Направление сдвига определяется булевым параметром shiftUp, передаваемым процедуре:
{
осуществляет циклический сдвиг строк матрицы arr вверх при shiftUp = true,
86и вниз, при shiftUp = false
87}
88procedure CircuarShift(var arr: TMatrix; shiftUp: boolean);
89var
90RowN: integer;
91tmpRow: TVector;//временная переменная для хранения строки иатрицы
92
93begin
94
95if high(arr) < 1 then exit;//если в матрице меньше двух строк - выходим
96if shiftUp then
97begin//если сдвиг вверх
98tmpRow:= arr[high(arr)];//сохраним последнюю строку матрицы
99arr[high(arr)]:= arr[0];//приравняем последнюю строку первой
100for rowN:= 0 to high(arr)-2 do
101begin//для строк с нулевой по пред-предпоследнюю
102arr[rowN]:= arr[rowN+1];//текущая строка равна нижней
103end;
104arr[high(arr)-1]:= tmpRow;//предпоследнюю строку приравняем последней
105end
106else
107begin//иначе, если сдвиг вниз
108tmpRow:= arr[0];//сохраним нулвую строку
109arr[0]:= arr[high(arr)];//приравняем нулевую строку последней
110for rowN:= high(arr) downto 2 do
111begin//для строк с последней по вторую
112arr[RowN]:= arr[RowN-1];//текущая строка равна верхней
113end;
114arr[1]:= tmpRow;//первую строку приравняем нулевой
115end;
116end;
«Разворачивание» матрицы
Процедура UnwindMatrix осуществляет "разворачивание" матрицы в одномерный массив против часовой стрелки. Эта процедура в своих локальных переменных хранит координаты текущего элемента, текущее направление обхода (посредством перечислимого типа TDirection), а так же границы ещё не обойдённой части матрицы, которые сужаются каждый раз, когда проходится целая строка, или столбец. В этот же момент меняется направление обхода и текущим становится элемент в этом направлении. Обход завершается, когда число пройденных элементов станет равняться количеству элементов в матрице:
//перечисление - направления
type TDirection = (down, right, up, left);
117
118{обходит матрицу arr против часовой стрелки и наполняет элементами массив res}
119procedure UnwindMatrix(const arr: TMatrix; var res: TVector);
120var
121count, cur: integer;//число элементов в матрице и счётчик элементов
122
123RowN, ColN: integer;
124leftB, bottomB, rightB, topB: integer;//границы обхода - меняются при проходе полной строки или столбца
125direction: TDirection;//текущее направление обхода
126
127begin
128if (length(arr) = 0) or (length(arr[0]) = 0) then exit;//если в матрице нет элементов - выходим
129count:= length(arr) * length(arr[0]);//подсчитаем число элементов в матрице
130SetLength(res, count);//выделим память для хранения всех элементов матрицы
131
132//начальные условия обхода: текущий элемент [0,0], границы совпадают с граниуцами матриы, направление - вниз
133direction:= down;
134RowN:= 0;
135ColN:= 0;
136leftB:= 0;
137bottomB:= high(arr);
138rightB:= high(arr[0]);
139topB:= 0;
140
141for cur:= 0 to count-1 do
142begin//пока не пройдём count элементов
143res[cur]:= arr[RowN, ColN];//добавляем текущий элемент в массив
144//дальненйшие действия зависят от текущего направления обхода
145case direction of
146down://если вниз
147if RowN < bottomB then inc(RowN)//если не дошли до нижней границы - сдвигаемся вниз
148else
149begin//иначе - прошли левый столбец
150direction:= right;//сменим направление на "вправо"
151inc(leftB);//сдвинем левую границу к центру
152inc(ColN);//сдвинемся вправо
153end;
154
155";background: #f2f2f2; border: 1px solid #00000a;line-height: 150%"> 156if ColN < rightB then inc(ColN)//если не дошли до правой границы - сдвигаемся вправо
157else
158begin//иначе - прошли нижнюю строку
159direction:= up;//сменим направление на "вверх"
160dec(bottomB);//сдвинем нижнюю границу к центру
161dec(RowN);//сдвинемся вверх
162end;
163
164up://если вверх
165if RowN > topB then dec(RowN)//если не дошли до верхней границы - сдвигаемся вверх
166else
167begin//иначе - прошли правый столбец
168direction:= left;//сменим направление на "влево"
169dec(rightB);//сдвинем правую границу к центру
170dec(ColN);//сдвинемся влево
171end;
172
173";background: #f2f2f2; border: 1px solid #00000a;line-height: 150%"> 174if ColN > leftB then dec(ColN)//если не дошли до левой границы - сдвигаемся влево
175else
176begin//иначе - прошли верхнюю строку
177direction:= down;//сменим направление на "вниз"
178inc(topB);//сдвинем верхнюю границу к центру
179inc(RowN);//сдвинемся вниз
180end;
181end;
182end;
183end;
Сортировка строк матрицы
Наконец упорядочивание строк матрицы по убыванию суммы элементов каждой строки. Вспомогательная функция getRowSum возвращает сумму элементов заданной строки:
{возвращает сумму элементов RowN-ой строки матрицы arr}
function getRowSum(const arr: TMatrix; RowN: integer): Int64;
184var ColN: integer;
185begin
186Result:= 0;
187if RowN > high(arr) then exit;//если в матрице нет RowN-ой строки - выходим
188for ColN:= 0 to high(arr[RowN]) do//суммируем элементы строки
189Result:= Result + arr[RowN, ColN];
190end;
Сама сортировка осуществляется посредством процедуры SortRows. Был выбран алгоритм прямой вставки, так как число строк в матрице не предполагается большим, а этот алгоритм эффективен на небольших наборах данных. В любом случае сортировка осуществляется быстро, так как при перемене мест строк не происходит копирование данных, но просто переставляются местами указатели. Листинг этой функции:
{сортирует строки матрицы по убыванию сумм элементов каждой строки}
procedure SortRows(var arr: TMatrix);
191var
192i, k: integer;//переменные для алгоритма сортировки
193tmpRow: TVector;//временная переменная для алгоритма сортировки
194begin
195//алгоритм сортировки методом прямой вставки
196for i:= 1 to high(arr) do
197begin//для строк с первой по последнюю
198k:= i;//начиная с текущей строки
199while (k > 0) and (getRowSum(arr, k) > getRowSum(arr, k-1)) do
200begin//пока не дошли до нулевой строки, и сумма строки над текущей строкой больше текущей суммы
201swap(arr[k-1], arr[k]);//поменяем текущую строку и строку над ней местами
202dec(k);//сдвинемся вверх
203end;
204end;
205end;
2.3.2 Модуль fileIO
Этот модуль содержит процедуры для файлового ввода/вывода матриц. Используются текстовые файлы, которые предварительно необходимо открыть и подготовить к чтению/записи.
Формат файла, содержащего матрицу таков: матрица записана построчно, начиная с первой строки, элементы в каждой строке записаны слева направо и разделены произвольным количеством пробелов. Именно такой файл создаёт процедура Write2DArray:
{
206записывает матрицу arr в текстовый файл outFile. Файл должен быть
207предварительно открыт
208}
209procedure Write2DArray(const arr: TMatrix; const outFile: TextFile);
210var
211rowN, colN: integer;
212begin
213for rowN:= low(arr) to high(arr) do
214begin
215for colN:= low(arr[rowN]) to high(arr[rowN]) do
216begin
217//ширина поля 12, так как -2147483648 - 11 символов
218Write(outFile, arr[rowN, colN]: 12);
219end;
220Writeln(outFile);
221end;
222end;
Процедура Read2DArray читает файл по строкам, разбирая каждую строку на подстрока пробелами с помощью процедуры ExtractStrings:
{ читает матрицу arr из текстового файла inFile. Файл должен быть
223предварительно открыт}
224procedure Read2DArray(var arr: TMatrix; const inFile: TextFile);
225var
226rowN, colN: integer;
227colCount: integer; //максимальное количество чисел в строке (число столбцов матрицы)
228lineStr: string; //текущая строка
229strNumbers: TStringList;//текущая строка, разделённая на подстроки пробелами
230begin
231rowN:= 0;
232colCount:= 0;
233strNumbers:= TStringList.Create;
234arr:= nil;
235while not Eof(inFile) do
236begin
237Readln(inFile, lineStr);
238strNumbers.Clear;
239ExtractStrings([' '], [], PChar(lineStr), strNumbers); //разделим пробелами на подстроки
240if colCount < strNumbers.Count then colCount:= strNumbers.Count;
241SetLength(arr, rowN+1, colCount);//выделим память под новую строку
242for colN:= 0 to strNumbers.Count-1 do //для каждого числа в строке
243arr[rowN, colN]:= StrToIntDef(strNumbers[colN], 0);
244Inc(rowN);
245end;
246strNumbers.Destroy;
247end;
2.3.3 Модуль form
Модуль, содержащий форму, переменную для хранения исходной матрицы, процедуры синхронизации содержания матрицы и элементов формы, а так же процедуру задания размеров матрицы.
Так как задача чётко разделена на задания, оперирующие одними и теми же исходными данными (целочисленным двумерным массивом), было принято решение разделить интерфейс приложения на две части. В верхней части формы отображается матрица исходных данных, которую можно редактировать и размеры которой можно менять. Нижняя часть формы представляет собой набор закладок, каждая из которых соответствует одной из поставленных задач. На каждой закладке содержится описание задания, кнопка «выполнить», а так же элементы, необходимы для отображения результата в рамках этого задания. Некоторые задания состоят в изменении исходной матрицы, результат выполнения таких заданий отображается непосредственно в исходных данных в верхней части формы. Всего существует как минимум три способа выбрать задачу: щёлкнуть мышкой по закладке, выбрать нужный пункт в меню «Задачи», нажать одну из кнопок F1 - F5.
Опишем важные процедуры формы. Процедура ReadMatrix осуществляет чтение исходных данных из таблицы на форме в двумерный массив. Перед началом чтения процедура устанавливает размер массива:
{заполнить матрицу в соответствии с содержанием таблицы на форме}
248procedure TMainForm.ReadMatrix;
249var rowN, colN: integer;
250begin
251SetLength(workMatrix, G_Matrix.RowCount-1, G_Matrix.ColCount-1);
252for rowN:= 0 to G_Matrix.RowCount-2 do
253for colN:= 0 to G_Matrix.ColCount-2 do
254workMatrix[rowN, colN]:= StrToIntDef(G_Matrix.Cells[colN+1, rowN+1], 0);
255end;
Процедура writeMatrix осуществляет обратную операцию, она заполняет поля таблицы в соответствии с массивом. Кроме этого она меняет значения числа строк и столбцов в соответствии с размерами массива:
{заполнить таблицу на форме в соответствии с содержанием матрицы}
procedure TMainForm.writeMatrix;
256var rowN, colN: integer;
257begin
258G_Matrix.Cells[1, 1]:= '';//если матрица пуста
259E_RowsN.Text:= IntToStr(high(workMatrix) + 1);
260if(E_RowsN.Text <> '0') then
261E_ColsN.Text:= IntToStr(high(workMatrix[low(workMatrix)]) + 1)
262else E_ColsN.Text:= '0';
263B_SetDimmsClick(self);
264//заполним таблицу
265for rowN:= low(workMatrix) to high(workMatrix) do
266for colN:= low(workMatrix[rowN]) to high(workMatrix[rowN]) do
267G_Matrix.Cells[colN+1, rowN+1]:= IntToStr(workMatrix[rowN, colN]);
268end;
Процедура B_SetDimmsClick является обработчиком нажатия кнопки «задать размеры». Она проверяет, не стали ли размеры меньше единицы, меняет число строк и столбцов в таблицах формы, а так же проставляет номера строк и столбцов:
{обраюотчик уствновки размеров матрицы}
269procedure TMainForm.B_SetDimmsClick(Sender: TObject);
270var
271i: integer;
272RowsN, ColsN: integer;
273begin
274//значения размеров не должны быть меньше 1
275RowsN:= StrToIntDef(E_RowsN.Text, 0);
276if RowsN < 1 then begin RowsN:= 1; E_RowsN.Text:= '1' end;
277ColsN:= StrToIntDef(E_ColsN.Text, 0);
278if ColsN < 1 then begin ColsN:= 1; E_ColsN.Text:= '1' end;
279//число строк и столбцов в таблице, учитывая колонку и строку с номерами
280G_Matrix.RowCount:= RowsN + 1;
281G_Matrix.ColCount:= ColsN + 1;
282//в этих таблицах отображаются одномерные массивы из первого задания
283G_Task1B.RowCount:= RowsN;
284G_Task1C.RowCount:= RowsN;
285//одномерный массив из четвёртого задания имеет длину, равную числу элементов исходной матрицы
286G_Task4.ColCount:= RowsN * ColsN;
287//расставим номера строк и столбцов
288for i:= 0 to RowsN do
289begin
290G_Matrix.Cells[0, i+1]:= IntToStr(i+1);
291G_Task1B.Cells[0, i]:= IntToStr(i+1);
292G_Task1C.Cells[0, i]:= IntToStr(i+1);
293end;
294for i:= 0 to ColsN do
295G_Matrix.Cells[i+1, 0]:= IntToStr(i+1);
296for i:= 0 to RowsN * ColsN do
297G_Task4.Cells[i, 0]:= IntToStr(i+1);
298G_Matrix.Refresh;
299end;
Процедура FormDestroy выполняется при уничтожении формы и выполняет очень важную функцию – освобождает память, которая выделялась во время работы приложения под матрицу исходных данных.
Процедура saveClick является обработчиком щелчка по пункту меню Файл->Сохранить. Она отображает диалог выбора файла для сохранения, создаёт выбранный файл, а после окончания записи закрывает его:
{обработчик Файл->Сохранить}
procedure TMainForm.saveClick(Sender: TObject);
300var
301outFile: TextFile;
302begin
303//отобразим диалог выбора файла для сохранения, если отмена - выходим
304if SaveDialog.Execute = false then exit;
305AssignFile(outFile, SaveDialog.Files[0]);
306ReWrite(outFile);//создадим файл
307 readMatrix;//прочтём матрицу из таблицы
308Write2DArray(workMatrix, outFile);//запишем матрицу в файл
309CloseFile(outFile);//закроем файл.
Процедура loadClick ведёт себя так же, только не создаёт файл, а открывает его для чтения:
{обработчик Файл->Загрузить}
310procedure TMainForm.loadClick(Sender: TObject);
311var
312inFile: TextFile;
313begin
314//отобразим диалог выбора фала для загрузки, если отмена - выходим
315if OpenDialog.Execute = false then exit;
316AssignFile(inFile, OpenDialog.Files[0]);
317Reset(inFile);//подготовим файл к чтению
318Read2DArray(workMatrix, inFile);//прочтём матрицу из файла
319writeMatrix;//отобразим матрицу
320CloseFile(inFile);//закроем файл
321end;
Остальные процедуры просто вызывают процедуры и функции других модулей, наполняют результатами соответствующие заданию элементы формы, а в конце обязательно освобождают динамическую память, если таковая была выделена в рамках процедуры.
2.4 Описание формата исходных файлов
Матрица в исходном файле представляется в текстовом виде. Каждая строка матрицы начинается с новой строки. Каждый элемент строки отделён от других произвольным числом пробелов и должен быть представлен целым числом, лежащим в диапазоне [-2147483648; 2147483647]. Если какой-то элемент выходит за границы этого диапазона, либо не является целым числом, то он интерпретируется как ноль.
Пример правильно составленного исходного файла:
100000 10000 20000 40000 -4000
50 100 -20 1000 2000
-100 -50 -20 0 20
-1000 -200 200 2 12
4000 -100000 -40000 -10000 80000
3. Эксплуатационная документация
3.1 Описание применения
Программа предназначена для выполнения определённого набора операций над матрицами. Описание каждой операции можно прочесть на соответствующей вкладке в интерфейсе программы.
Программа предназначена для исполнения на IBM-совместимых компьютерах с операционной системой Windows (тестирование проводилось на Windows XP).
Минимальные системные требования:
Дисплей с разрешением 1024x768
Клавиатура
10 мегабайт свободной оперативной памяти
Требования приложения к оперативной памяти сильно зависят от размера обрабатываемой матрицы. Соответствующий минимальным требованиям компьютер сможет обрабатывать матрицы размером не менее ста элементов.
Входными параметрами для приложения являются файлы, описанные в пункте 3.4. Так же есть возможность ввести исходную матрицу непосредственно в таблицу на форме.
Выходные данные представляются в элементах формы, расположенных на соответствующей заданию вкладке (смотрите руководство оператора)
3.2 Руководство оператора
Интерфейс приложения разделён на две части. В верхней части формы отображается матрица исходных данных, которую можно редактировать и размеры которой можно менять. Нижняя часть формы представляет собой набор закладок, каждая из которых соответствует одной из поставленных задач. На каждой закладке содержится описание задания, кнопка «выполнить», а так же элементы, необходимы для отображения результата в рамках этого задания. Некоторые задания состоят в изменении исходной матрицы, результат выполнения таких заданий отображается непосредственно в исходных данных в верхней части формы. Всего существует как минимум три способа выбрать задачу: щёлкнуть мышкой по закладке, выбрать нужный пункт в меню «Задачи», нажать одну из кнопок F1 - F5.
Открытие файла с данными:
Выполнение задачи №1:
Результат выполнения задачи №1:
Переход к задаче №3:
Выполнение задачи №3:
Результат двукратного выполнения задачи №3:
Результат выполнения задачи №2:
Результат выполнения задачи №5:
Результат выполнения задачи №4:
Сохранение полученной матрицы в файл:
Завершение работы программы:
Содержание сохранённого файла:
100000 10000 20000 40000 -4000
50 100 -20 1000 2000
-100 -50 -20 0 20
-1000 -200 200 2 12
4000 -100000 -40000 -10000 80000
Выводы
Двумерный динамический массив – очень удобная конструкция для представления матрицы, размеры которой во время написания программы не известны. Но при его использовании нужно быть осторожным и учитывать некоторые особенности:
При вызове SetLength с одним параметром размера будет выделена память только под первую размерность массива (например, будет увеличено число строк в матрице), остальные размерности затронуты не будут (в каждой добавленной строке будет ноль элементов).
Каждый подмассив многомерного массива может иметь свою размерность (например, каждая строка матрицы в общем то может иметь длину, отличную от других)
Необходимо всегда знать границы каждой размерности, чтобы не выйти за пределы массива в чужую память. Для этого полезны функции low и high.
Необходимо всегда освобождать динамически выделенную память.
При присваивании динамических массивов копирования данных не происходит, присваиваются лишь указатели, таким образом, после присваивания два массива будут указывать на одну и ту же область памяти. Чтобы получить копию массива, можно использовать функцию Copy.
Copy копирует не весь многомерный массив, но только его первую размерность.
Приложения
Приложение 1. Тестовые примеры
Тест 1: Квадратная матрица 5x5.
Исходная матрица:
-100 -50 -20 0 20
50 100 200 1000 2000
4000 10000 20000 40000 80000
100000 -100000 -40000 -10000 -4000
-1000 -200 -20 2 12
Результат выполнения первого задания:
Максимальные элементы по строкам: 20; 2000; 80000; 100000; 12
Столбцы с максимальными элементами: 5; 5; 5; 1; 5
Результат выполнения второго задания:
S1 = 130
S2 = -40218
S1 > S2, матрица не была изменена
Результат выполнения третьего задания:
Число столбцов нечётно – был произведён сдвиг «вниз»
-1000 -200 -20 2 12
-100 -50 -20 0 20
50 100 200 1000 2000
4000 10000 20000 40000 80000
100000 -100000 -40000 -10000 -4000
Результат выполнения четвёртого задания:
Матрица, «развёрнутая» против часовой стрелки: -100; 50; 4000; 100000; -1000; -200; -20; 2; 12; -4000; 80000; 2000; 20; 0; -20; -50; 100; 10000; -100000; -40000; -10000; 40000; 1000; 200; 20000
Результат выполнения пятого задания:
Строки отсортированы в невозрастающем порядке сумм:
4000 10000 20000 40000 80000
50 100 200 1000 2000
-100 -50 -20 0 20
-1000 -200 -20 2 12
100000 -100000 -40000 -10000 -4000
Тест 2: прямоугольная матрица 3x8.
Исходная матрица:
1 - 18 17 -16 15 -14 13 -12
-2 19 20 2000 200000 20000000 2000000000 11
3 -4 5 -6 7 -8 9 -10
Результат выполнения первого задания:
Максимальные элементы по строкам: 17; 2000000000; 9
Столбцы с максимальными элементами: 3; 7; 7
Результат выполнения второго задания:
S1 = -18 S2 = -4
S1 < S2, матрица была изменена:
1 -4 17 -16 15 -14 13 -12
-2 19 20 2000 200000 20000000 2000000000 11
3 -18 5 -6 7 -8 9 -10
Результат выполнения третьего задания:
Число столбцов чётно – был произведён сдвиг «вверх»
-2 19 20 2000 200000 20000000 2000000000 11
3 -18 5 -6 7 -8 9 -10
1 -4 17 -16 15 -14 13 -12
Результат выполнения четвёртого задания:
Матрица, «развёрнутая» против часовой стрелки: 1; -2; 3; -4; 5; -6; 7; -8; 9; -10; 11; -12; 13; -14; 15; -16; 17; -18; 19; 20; 2000; 200000; 20000000; 2000000000;
Результат выполнения пятого задания:
Строки отсортированы в невозрастающем порядке сумм:
-2 19 20 2000 200000 20000000 2000000000 11
3 -4 5 -6 7 -8 9 -10
1 -18 17 -16 15 -14 13 -12
Тест 3: прямоугольная матрица 10x5, наполненная случайными числами.
Исходная матрица:
4490 6540 -12901 20330 -6046
-27459 -22256 26705 14852 -30502
23701 -11502 -30162 -14325 -20739
-15721 -14704 17504 -23934 21020
-27932 7054 -30557 -28698 -19302
-16794 -24715 28069 -2485 -11281
30727 18102 20673 -32373 23140
-16762 -1303 5821 21065 -25295
-24472 27091 -6385 -13002 -22009
-12309 26284 20788 -21316 -25044
Результат выполнения первого задания:
Максимальные элементы по строкам: 20330; 26705; 23701; 21020; 7054
Столбцы с максимальными элементами: 4; 3; 1; 5; 2
Результат выполнения второго задания:
S1 = 4934
S2 = -21774
S1 > S2, матрица не была изменена
Результат выполнения третьего задания:
Число столбцов нечётно – был произведён сдвиг «вниз»
-12309 26284 20788 -21316 -25044
4490 6540 -12901 20330 -6046
-27459 -22256 26705 14852 -30502
23701 -11502 -30162 -14325 -20739
-15721 -14704 17504 -23934 21020
-27932 7054 -30557 -28698 -19302
-16794 -24715 28069 -2485 -11281
30727 18102 20673 -32373 23140
-16762 -1303 5821 21065 -25295
-24472 27091 -6385 -13002 -22009
Результат выполнения четвёртого задания:
Матрица, «развёрнутая» против часовой стрелки: 4490; -27459; 23701; -15721; -27932; -16794; 30727; -16762; -24472; -12309; 26284; 20788; -21316; -25044; -22009; -25295; 23140; -11281; -19302; 21020; -20739; -30502; -6046; 20330; -12901; 6540; -22256; -11502; -14704; 7054; -24715; 18102; -1303; 27091; -6385; -13002; 21065; -32373; -2485; -28698; -23934; -14325; 14852; 26705; -30162; 17504; -30557; 28069; 20673; 5821
Результат выполнения пятого задания:
Строки отсортированы в невозрастающем порядке сумм:
30727 18102 20673 -32373 23140
4490 6540 -12901 20330 -6046
-12309 26284 20788 -21316 -25044
-15721 -14704 17504 -23934 21020
-16762 -1303 5821 21065 -25295
-16794 -24715 28069 -2485 -11281
-27459 -22256 26705 14852 -30502
-24472 27091 -6385 -13002 -22009
23701 -11502 -30162 -14325 -20739
-27932 7054 -30557 -28698 -19302
Тест 4: матрица с большими по модулю числами.
Исходная матрица:
0 -2000000000 -2100000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2000000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2000000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -1900000000 -200000000 1
Результат выполнения первого задания:
Максимальные элементы по строкам: 1; 1000000000; 1; 1000000000; 1; 1000000000; 1
Столбцы с максимальными элементами: 5; 1; 5; 1; 5; 1; 5
Результат выполнения второго задания:
S1 = -7699999981
S2 = -7499999981
S1 < S2, матрица была изменена:
0 -2000000000 -1900000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2000000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2000000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2100000000 -2000000000 1
Результат выполнения третьего задания:
Число столбцов нечётно – был произведён сдвиг «вниз»
0 -2000000000 -1900000000 -2000000000 1
0 -2000000000 -2100000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2000000000 -2000000000 1
1000000000 -800000000 400000000 3 15
0 -2000000000 -2000000000 -2000000000 1
1000000000 -800000000 400000000 3 15
Результат выполнения четвёртого задания:
Матрица, «развёрнутая» против часовой стрелки: 0; 1000000000; 0; 1000000000; 0; 1000000000; 0; -2000000000; -1900000000; -2000000000; 1; 15; 1; 15; 1; 15; 1; -2000000000; -2100000000; -2000000000; -800000000; -2000000000; -800000000; -2000000000; -800000000; 400000000; 3; -2000000000; 3; -2000000000; 3; 400000000; -2000000000; 400000000; -2000000000
Результат выполнения пятого задания:
Строки отсортированы в невозрастающем порядке сумм:
1000000000 -800000000 400000000 3 15
1000000000 -800000000 400000000 3 15
1000000000 -800000000 400000000 3 15
0 -2000000000 -1900000000 -2000000000 1
0 -2000000000 -2000000000 -2000000000 1
0 -2000000000 -2000000000 -2000000000 1
0 -2000000000 -2100000000 -2000000000 1
Тест 5: матрица с ошибками.
Исходная матрица:
9999999999 123 fdf
456 rt 8888888888
1234567890 9876543210 789
q 0xf e
-77777777777 000 -13
915 -376 19
ddd -ddd 1111111111
Внутри программы такая матрица будет интерпретирована следующим образом:
0 123 0
456 0 0
1234567890 0 789
0 15 0
0 0 -13
915 -376 19
0 0 1111111111
Результат выполнения первого задания:
Максимальные элементы по строкам: 123; 456; 1234567890; 15; 0; 915; 1111111111
Столбцы с максимальными элементами: 2; 1; 1; 2; 1; 1; 3
Результат выполнения второго задания:
S1 = 123
S2 = 1111111130
S1 < S2, матрица была изменена:
0 0 1111111111
456 0 19
1234567890 0 789
0 15 0
0 0 -13
915 -376 0
0 123 0
Результат выполнения третьего задания:
Число столбцов нечётно – был произведён сдвиг «вниз»
0 0 1111111111
0 123 0
456 0 0
1234567890 0 789
0 15 0
0 0 -13
915 -376 19
Результат выполнения четвёртого задания:
Матрица, «развёрнутая» против часовой стрелки: 0; 456; 1234567890; 0; 0; 915; 0; 0; 1111111111; 19; -13; 0; 789; 0; 0; 123; 0; 0; 15; 0; -376
Результат выполнения пятого задания:
Строки отсортированы в невозрастающем порядке сумм:
1234567890 0 789
0 0 1111111111
915 -376 19
456 0 0
0 123 0
0 15 0
0 0 -13
Приложение 2. Полный листинг формы (файл form.pas)
322{
323Модуль, содержащий форму, переменную для хранения исходной матрицы,
324процедуры синхронизации содержания матрицы и элементов формы, а так же
325процедуру задания размеров матрицы
326}
327unit form;
328
329interface
330
331uses
332Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
333Dialogs, Menus, StdCtrls, ExtCtrls, ComCtrls, Grids,
334//модули программы
335fileIO, MatrixOperations;
336
337type
338TMainForm = class(TForm)
339Pages: TPageControl;
340Task1: TTabSheet;
341Task2: TTabSheet;
342Task3: TTabSheet;
343Task4: TTabSheet;
344Task5: TTabSheet;
345Menu: TMainMenu;
346A1: TMenuItem;
347load: TMenuItem;
348save: TMenuItem;
349N1: TMenuItem;
350quit: TMenuItem;
351N4: TMenuItem;
352M_Task1: TMenuItem;
353M_Task2: TMenuItem;
354M_Task3: TMenuItem;
355M_Task4: TMenuItem;
356M_Task5: TMenuItem;
357GroupBox1: TGroupBox;
358G_Matrix: TStringGrid;
359E_RowsN: TEdit;
360Label1: TLabel;
361Label2: TLabel;
362E_ColsN: TEdit;
363B_SetDimms: TButton;
364SaveDialog: TSaveDialog;
365OpenDialog: TOpenDialog;
366Label3: TLabel;
367Label4: TLabel;
368G_Task1B: TStringGrid;
369Label5: TLabel;
370Label6: TLabel;
371G_Task1C: TStringGrid;
372B_Task1Run: TButton;
373Label7: TLabel;
374Label8: TLabel;
375Label9: TLabel;
376E_Task2S1: TEdit;
377B_Task2Run: TButton;
378E_Task2S2: TEdit;
379L_Task2MatrxChanged: TLabel;
380Label10: TLabel;
381B_Task3Run: TButton;
382L_Task3Result: TLabel;
383Label11: TLabel;
384B_Task4Run: TButton;
385Label12: TLabel;
386B_Task5Run: TButton;
387about: TMenuItem;
388MEM_Task4: TMemo;
389procedure saveClick(Sender: TObject);
390procedure loadClick(Sender: TObject);
391procedure B_SetDimmsClick(Sender: TObject);
392procedure FormCreate(Sender: TObject);
393procedure quitClick(Sender: TObject);
394procedure M_Task1Click(Sender: TObject);
395procedure M_Task2Click(Sender: TObject);
396procedure M_Task3Click(Sender: TObject);
397procedure M_Task4Click(Sender: TObject);
398procedure M_Task5Click(Sender: TObject);
399procedure B_Task1RunClick(Sender: TObject);
400procedure FormDestroy(Sender: TObject);
401procedure B_Task2RunClick(Sender: TObject);
402procedure B_Task3RunClick(Sender: TObject);
403procedure B_Task4RunClick(Sender: TObject);
404procedure B_Task5RunClick(Sender: TObject);
405procedure aboutClick(Sender: TObject);
406private
407procedure readMatrix;
408procedure writeMatrix;
409public
410published
411{ Public declarations }
412end;
413
414var
415MainForm: TMainForm;
416workMatrix: TMatrix;
417
418implementation
419
420uses Math;
421
422{$R *.dfm}
423
424{заполнить матрицу в соответствии с содержанием таблицы на форме}
425procedure TMainForm.ReadMatrix;
426var rowN, colN: integer;
427begin
428SetLength(workMatrix, G_Matrix.RowCount-1, G_Matrix.ColCount-1);
429for rowN:= 0 to G_Matrix.RowCount-2 do
430for colN:= 0 to G_Matrix.ColCount-2 do
431workMatrix[rowN, colN]:= StrToIntDef(G_Matrix.Cells[colN+1, rowN+1], 0);
432end;
433
434{заполнить таблицу на форме в соответствии с содержанием матрицы}
435procedure TMainForm.writeMatrix;
436var rowN, colN: integer;
437begin
438G_Matrix.Cells[1, 1]:= '';//если матрица пуста
439//обновим размеры матрицы
440E_RowsN.Text:= IntToStr(high(workMatrix) + 1);
441if(E_RowsN.Text <> '0') then
442E_ColsN.Text:= IntToStr(high(workMatrix[low(workMatrix)]) + 1)
443else E_ColsN.Text:= '0';
444B_SetDimmsClick(self);
445//заполним таблицу
446for rowN:= low(workMatrix) to high(workMatrix) do
447for colN:= low(workMatrix[rowN]) to high(workMatrix[rowN]) do
448G_Matrix.Cells[colN+1, rowN+1]:= IntToStr(workMatrix[rowN, colN]);
449end;
450
451{обработчик Файл->Сохранить}
452procedure TMainForm.saveClick(Sender: TObject);
453var
454outFile: TextFile;
455begin
456//отобразим диалог выбора файла для сохранения, если отмена - выходим
457if SaveDialog.Execute = false then exit;
458AssignFile(outFile, SaveDialog.Files[0]);
459ReWrite(outFile);//создадим файл
460
461readMatrix;//прочтём матрицу из таблицы
462Write2DArray(workMatrix, outFile);//запишем матрицу в файл
463
464CloseFile(outFile);//закроем файл
465
466end;
467
468{обработчик Файл->Загрузить}
469procedure TMainForm.loadClick(Sender: TObject);
470var
471inFile: TextFile;
472begin
473//отобразим диалог выбора фала для загрузки, если отмена - выходим
474if OpenDialog.Execute = false then exit;
475AssignFile(inFile, OpenDialog.Files[0]);
476Reset(inFile);//подготовим файл к чтению
477
478Read2DArray(workMatrix, inFile);//прочтём матрицу из файла
479writeMatrix;//отобразим матрицу
480
481CloseFile(inFile);//закроем файл
482end;
483
484{обраюотчик уствновки размеров матрицы}
485procedure TMainForm.B_SetDimmsClick(Sender: TObject);
486var
487i: integer;
488RowsN, ColsN: integer;
489begin
490//значения размеров не должны быть меньше 1
491RowsN:= StrToIntDef(E_RowsN.Text, 0);
492if RowsN < 1 then begin RowsN:= 1; E_RowsN.Text:= '1' end;
493ColsN:= StrToIntDef(E_ColsN.Text, 0);
494if ColsN < 1 then begin ColsN:= 1; E_ColsN.Text:= '1' end;
495//число строк и столбцов в таблице, учитывая колонку и строку с номерами
496G_Matrix.RowCount:= RowsN + 1;
497G_Matrix.ColCount:= ColsN + 1;
498//в этих таблицах отображаются одномерные массивы из первого задания
499G_Task1B.RowCount:= RowsN;
500G_Task1C.RowCount:= RowsN;
501//одномерный массив из четвёртого задания имеет длину, равную числу элементов исходной матрицы
502//G_Task4.ColCount:= RowsN * ColsN;
503//расставим номера строк и столбцов
504for i:= 0 to RowsN do
505begin
506G_Matrix.Cells[0, i+1]:= IntToStr(i+1);
507G_Task1B.Cells[0, i]:= IntToStr(i+1);
508G_Task1C.Cells[0, i]:= IntToStr(i+1);
509end;
510for i:= 0 to ColsN do
511G_Matrix.Cells[i+1, 0]:= IntToStr(i+1);
512
513//for i:= 0 to RowsN * ColsN do
514// G_Task4.Cells[i, 0]:= IntToStr(i+1);
515G_Matrix.Refresh;
516end;
517
518{при создании формы задаём размер матрицы по умолчанию}
519procedure TMainForm.FormCreate(Sender: TObject);
520begin
521B_SetDimmsClick(Sender);
522end;
523
524{при уничтожении формы освобождаем память, выделенную для хранения матрицы}
525procedure TMainForm.FormDestroy(Sender: TObject);
526begin
527workMatrix:= nil;
528end;
529
530{обработчик Файл->Выход}
531procedure TMainForm.quitClick(Sender: TObject);
532begin
533if mrYes = MessageDlg('Вы уверены, что хотите выйти?', mtConfirmation, [mbYes, mbNo], 0)
534then Close;
535end;
536
537{обработчик Задачи->задача 1}
538procedure TMainForm.M_Task1Click(Sender: TObject);
539begin
540Pages.ActivePageIndex:= 0;
541end;
542{обработчик Задачи->задача 2}
543procedure TMainForm.M_Task2Click(Sender: TObject);
544begin
545Pages.ActivePageIndex:= 1;
546end;
547{обработчик Задачи->задача 3}
548procedure TMainForm.M_Task3Click(Sender: TObject);
549begin
550Pages.ActivePageIndex:= 2;
551end;
552{обработчик Задачи->задача 4}
553procedure TMainForm.M_Task4Click(Sender: TObject);
554begin
555Pages.ActivePageIndex:= 3;
556end;
557{обработчик Задачи->задача 5}
558procedure TMainForm.M_Task5Click(Sender: TObject);
559begin
560Pages.ActivePageIndex:= 4;
561end;
562
563{выполнение первого задания}
564procedure TMainForm.B_Task1RunClick(Sender: TObject);
565var
566maxVal: TVector; //массив максимальных элементов из каждой строки
567maxValCol: TVector; //массив номеров столбцов с максимальными элементами
568RowN: integer;
569begin
570readMatrix;//прочитаем матрицу из таблицы
571GetMaxVals(maxVal, maxValCol, workMatrix);//сформируем массивы по заданию
572for RowN:= low(maxVal) to high(maxVal) do
573begin//выведем сформированные массивы в элементы формы
574G_Task1B.Cells[1, RowN]:= IntToStr(maxVal[RowN]);
575G_Task1C.Cells[1, RowN]:= IntToStr(maxValCol[RowN]+1);
576end;
577//освободим память
578maxVal:= nil;
579maxValCol:= nil;
580end;
581
582{выполнение второго задания}
583procedure TMainForm.B_Task2RunClick(Sender: TObject);
584var S1, S2: Int64;//суммы выше и ниже пересечения диагоналей
585begin
586readMatrix;//проситаем матрицу из таблицы
587//высчитаем суммы
588S1:= GetSumAbove(workMatrix);
589S2:= GetSumBelow(workMatrix);
590//выведем суммы в элементы формы
591E_Task2S1.Text:= IntToStr(S1);
592E_Task2S2.Text:= IntToStr(S2);
593if S1 >= S2 then L_Task2MatrxChanged.Caption:= 'Матрица не была изменена'
594else
595begin//если S1 < S2, то
596SwapAboveBelow(workMatrix);//меняем местами элементы выше и ниже пересечения диагоналей
597writeMatrix;//выводим изменённую матрицу на форму
598L_Task2MatrxChanged.Caption:= 'Матрица была изменена'
599end;
600end;
601
602{выполнение третьего задания}
603procedure TMainForm.B_Task3RunClick(Sender: TObject);
604begin
605readMatrix;//прочтём матрицу из таблицы
606if (high(workMatrix)+1) mod 2 = 0 then
607begin//если число строк - чётное
608CircuarShift(workMatrix, true);//осуществим циклический сдвиг вверх
609L_Task3Result.Caption:= 'был произведён сдвиг "вверх"';
610end
611else
612begin//иначе, если число строк - нечётное
613CircuarShift(workMatrix, false);//осуществим циклический сдвиг вниз
614L_Task3Result.Caption:= 'был произведён сдвиг "вниз"';
615end;
616writeMatrix;//выведем изменённую матрицу в таблицу
617end;
618
619{выполнение четвёртого задания}
620procedure TMainForm.B_Task4RunClick(Sender: TObject);
621var arrayB: TVector;//массив, содержащий "развёрнутую" матрицу
622var i: integer;
623begin
624readMatrix;//прочтём матрицу из таблицы
625UnwindMatrix(workMatrix, arrayB);//наполним массив, обходя матрицу по спирали
626MEM_Task4.Lines[0]:= '';
627for i:= 0 to high(arrayB) do
628begin//выведем все элементы из массива на форму
629//G_Task4.Cells[i, 1]:= IntToStr(arrayB[i]);
630MEM_Task4.Lines[0]:= MEM_Task4.Lines[0] + IntToStr(arrayB[i]) + '; '
631end;
632arrayB:= nil;//освободим память
633end;
634
635{выполнение пятого задания}
636procedure TMainForm.B_Task5RunClick(Sender: TObject);
637begin
638readMatrix;//прочтём матрицу из таблицы
639SortRows(workMatrix);//отсортируем строки матрицы по убыванию сумм
640writeMatrix;//выведем матрицу в таблицу
641end;
642{обработчик About}
643procedure TMainForm.aboutClick(Sender: TObject);
644var info: string;
645begin
646info:= 'Курсовая работа по дисциплине "Программирование на ЯВУ"'#10#10 +
647'Тема: "Работа с двумерными числовыми массивами"'#10 +
648'Выполнил: студент группы ВСМ-06-08 Филон Д. В.'#10#10#10 +
649#9#9#9#9#9#9'Москва 2010 год';
650MessageDlg(info, mtInformation, [mbIgnore], 0);
651end;
652end.

Нравится материал? Поддержи автора!
Ещё документы из категории информатика:
Чтобы скачать документ, порекомендуйте, пожалуйста, его своим друзьям в любой соц. сети.
После чего кнопка «СКАЧАТЬ» станет доступной!
Кнопочки находятся чуть ниже. Спасибо!
Кнопки:
Скачать документ