2.3.2 Модуль fileIO
Этот модуль содержит процедуры для файлового ввода/вывода матриц. Используются текстовые файлы, которые предварительно необходимо открыть и подготовить к чтению/записи.
Формат файла, содержащего матрицу таков: матрица записана построчно, начиная с первой строки, элементы в каждой строке записаны слева направо и разделены произвольным количеством пробелов. Именно такой файл создаёт процедура Write2DArray:
1 {
2 записывает матрицу arr в текстовый файл outFile. Файл должен быть
3 предварительно открыт
4 }
5 procedure Write2DArray(const arr: TMatrix; const outFile: TextFile);
6 var
7 rowN, colN: integer;
8 begin
9 for rowN:= low(arr) to high(arr) do
10 begin
11 for colN:= low(arr[rowN]) to high(arr[rowN]) do
12 begin
13 //ширина поля 12, так как -2147483648 - 11 символов
14 Write(outFile, arr[rowN, colN]: 12);
15 end;
16 Writeln(outFile);
17 end;
18 end;
Процедура Read2DArray читает файл по строкам, разбирая каждую строку на подстрока пробелами с помощью процедуры ExtractStrings:
1 { читает матрицу arr из текстового файла inFile. Файл должен быть
2 предварительно открыт}
3 procedure Read2DArray(var arr: TMatrix; const inFile: TextFile);
4 var
5 rowN, colN: integer;
6 colCount: integer; //максимальное количество чисел в строке (число столбцов матрицы)
7 lineStr: string; //текущая строка
8 strNumbers: TStringList;//текущая строка, разделённая на подстроки пробелами
9 begin
10 rowN:= 0;
11 colCount:= 0;
12 strNumbers:= TStringList.Create;
13 arr:= nil;
14 while not Eof(inFile) do
15 begin
16 Readln(inFile, lineStr);
17 strNumbers.Clear;
18 ExtractStrings([ ], [], PChar(lineStr), strNumbers); //разделим пробелами на подстроки
19 if colCount < strNumbers.Count then colCount:= strNumbers.Count;
20 SetLength(arr, rowN+1, colCount);//выделим память под новую строку
21 for colN:= 0 to strNumbers.Count-1 do //для каждого числа в строке
22 arr[rowN, colN]:= StrToIntDef(strNumbers[colN], 0);
23 Inc(rowN);
24 end;
25 strNumbers.Destroy;
26 end;
2.3.3 Модуль form
Модуль, содержащий форму, переменную для хранения исходной матрицы, процедуры синхронизации содержания матрицы и элементов формы, а так же процедуру задания размеров матрицы.
Так как задача чётко разделена на задания, оперирующие одними и теми же исходными данными (целочисленным двумерным массивом), было принято решение разделить интерфейс приложения на две части. В верхней части формы отображается матрица исходных данных, которую можно редактировать и размеры которой можно менять. Нижняя часть формы представляет собой набор закладок, каждая из которых соответствует одной из поставленных задач. На каждой закладке содержится описание задания, кнопка «выполнить», а так же элементы, необходимы для отображения результата в рамках этого задания. Некоторые задания состоят в изменении исходной матрицы, результат выполнения таких заданий отображается непосредственно в исходных данных в верхней части формы. Всего существует как минимум три способа выбрать задачу: щёлкнуть мышкой по закладке, выбрать нужный пункт в меню «Задачи», нажать одну из кнопок F1 - F5.
Опишем важные процедуры формы. Процедура ReadMatrix осуществляет чтение исходных данных из таблицы на форме в двумерный массив. Перед началом чтения процедура устанавливает размер массива:
1 {заполнить матрицу в соответствии с содержанием таблицы на форме}
2 procedure TMainForm.ReadMatrix;
3 var rowN, colN: integer;
4 begin
5 SetLength(workMatrix, G_Matrix.RowCount-1, G_Matrix.ColCount-1);
6 for rowN:= 0 to G_Matrix.RowCount-2 do
7 for colN:= 0 to G_Matrix.ColCount-2 do
8 workMatrix[rowN, colN]:= StrToIntDef(G_Matrix.Cells[colN+1, rowN+1], 0);
9 end;
Процедура writeMatrix осуществляет обратную операцию, она заполняет поля таблицы в соответствии с массивом. Кроме этого она меняет значения числа строк и столбцов в соответствии с размерами массива:
1 {заполнить таблицу на форме в соответствии с содержанием матрицы}
2 procedure TMainForm.writeMatrix;
3 var rowN, colN: integer;
4 begin
5 G_Matrix.Cells[1, 1]:= ;//если матрица пуста
6 E_RowsN.Text:= IntToStr(high(workMatrix) + 1);
7 if(E_RowsN.Text <> 0) then
8 E_ColsN.Text:= IntToStr(high(workMatrix[low(workMatrix)]) + 1)
9 else E_ColsN.Text:= 0;
10 B_SetDimmsClick(self);
11 //заполним таблицу
12 for rowN:= low(workMatrix) to high(workMatrix) do
13 for colN:= low(workMatrix[rowN]) to high(workMatrix[rowN]) do
14 G_Matrix.Cells[colN+1, rowN+1]:= IntToStr(workMatrix[rowN, colN]);
15 end;
Процедура B_SetDimmsClick является обработчиком нажатия кнопки «задать размеры». Она проверяет, не стали ли размеры меньше единицы, меняет число строк и столбцов в таблицах формы, а так же проставляет номера строк и столбцов:
1 {обраюотчик уствновки размеров матрицы}
2 procedure TMainForm.B_SetDimmsClick(Sender: TObject);
3 var
4 i: integer;
5 RowsN, ColsN: integer;
6 begin
7 //значения размеров не должны быть меньше 1
8 RowsN:= StrToIntDef(E_RowsN.Text, 0);
9 if RowsN < 1 then begin RowsN:= 1; E_RowsN.Text:= 1 end;
10 ColsN:= StrToIntDef(E_ColsN.Text, 0);
11 if ColsN < 1 then begin ColsN:= 1; E_ColsN.Text:= 1 end;
12 //число строк и столбцов в таблице, учитывая колонку и строку с номерами
13 G_Matrix.RowCount:= RowsN + 1;
14 G_Matrix.ColCount:= ColsN + 1;
15 //в этих таблицах отображаются одномерные массивы из первого задания
16 G_Task1B.RowCount:= RowsN;
17 G_Task1C.RowCount:= RowsN;
18 //одномерный массив из четвёртого задания имеет длину, равную числу элементов исходной матрицы
19 G_Task4.ColCount:= RowsN * ColsN;
20 //расставим номера строк и столбцов
21 for i:= 0 to RowsN do
22 begin
23 G_Matrix.Cells[0, i+1]:= IntToStr(i+1);
24 G_Task1B.Cells[0, i]:= IntToStr(i+1);
25 G_Task1C.Cells[0, i]:= IntToStr(i+1);
26 end;
27 for i:= 0 to ColsN do
28 G_Matrix.Cells[i+1, 0]:= IntToStr(i+1);
29 for i:= 0 to RowsN * ColsN do
30 G_Task4.Cells[i, 0]:= IntToStr(i+1);
31 G_Matrix.Refresh;
32 end;
Процедура FormDestroy выполняется при уничтожении формы и выполняет очень важную функцию - освобождает память, которая выделялась во время работы приложения под матрицу исходных данных.
Процедура saveClick является обработчиком щелчка по пункту меню Файл->Сохранить. Она отображает диалог выбора файла для сохранения, создаёт выбранный файл, а после окончания записи закрывает его:
1 {обработчик Файл->Сохранить}
2 procedure TMainForm.saveClick(Sender: TObject);
3 var
4 outFile: TextFile;
5 begin
6 //отобразим диалог выбора файла для сохранения, если отмена - выходим
7 if SaveDialog.Execute = false then exit;
8 AssignFile(outFile, SaveDialog.Files[0]);
9 ReWrite(outFile);//создадим файл
10 readMatrix;//прочтём матрицу из таблицы
11 Write2DArray(workMatrix, outFile);//запишем матрицу в файл
12 CloseFile(outFile);//закроем файл.
Процедура loadClick ведёт себя так же, только не создаёт файл, а открывает его для чтения:
1 {обработчик Файл->Загрузить}
2 procedure TMainForm.loadClick(Sender: TObject);
3 var
4 inFile: TextFile;
5 begin
6 //отобразим диалог выбора фала для загрузки, если отмена - выходим
7 if OpenDialog.Execute = false then exit;
8 AssignFile(inFile, OpenDialog.Files[0]);
9 Reset(inFile);//подготовим файл к чтению
10 Read2DArray(workMatrix, inFile);//прочтём матрицу из файла
11 writeMatrix;//отобразим матрицу
12 CloseFile(inFile);//закроем файл
13 end;
Остальные процедуры просто вызывают процедуры и функции других модулей, наполняют результатами соответствующие заданию элементы формы, а в конце обязательно освобождают динамическую память, если таковая была выделена в рамках процедуры.
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
- Введение
- 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 Функции для работы с массивами
- 2. Практическая часть
- 2.1 Постановка задачи
- 2.3 Описание модулей
- 2.3.1 Модуль MatrixOperations
- 2.3.2 Модуль fileIO
- 3. Эксплуатационная документация
- 3.1 Описание применения
- 3.2 Руководство оператора
- Выводы