Главная Учебники - Разные Лекции (разные) - часть 32
КУРСОВОЙ ПРОЕКТ
по курсу «Структуры и организация данных в ЭВМ»
на тему
«Инф
ормационная система начальника
жилищно-эксплуатационной службы
»
Тема данного курсового проекта – «Информационная система начальника жилищно-эксплуатационной службы». При этом по заданию к курсовому проекту необходимо использовать структуру данных типа вектор и сортировку QuickSort. Для разработки приложения была выбрана среда программирования Delphi. Среда визуального объектно-ориентированного проектирования Delphi позволяет: 1. Создавать законченные приложения для Windows самой различной направленности. 2. Быстро создавать профессионально выглядящий оконный интерфейс для любых приложений; интерфейс удовлетворяет всем требованиям Windows и автоматически настраивается на ту систему, которая установлена, поскольку использует функции, процедуры и библиотеки Windows. 3. Создавать свои динамически присоединяемые библиотеки компонентов, форм, функций, которые потом можно использовать из других языков программирования. 4. Создавать мощные системы работы с базами данных любых типов. 5. Формировать и печатать сложные отчеты, включающие таблицы, графики и т.п. 6. Создавать справочные системы, как для своих приложений, так и для любых других. 7. Создавать профессиональные программы установки для приложений Windows, учитывающие всю специфику и все требования операционной системы. Delphi – быстро развивающаяся система. Первая версия Delphi была выпущена в феврале 1995 года, в 1996 году вышла вторая версия, 1997 – третья, 1998 – четвертая, 1999 – пятая, 2001 – шестая. Все версии, начиная с Delphi 2.0, рассчитаны на разработку 32-разрядных приложений, т.е. приложений для операционных систем Windows 95/98, NTи т.д. В 2002 году вышла седьмая версия, основным нововведением в которой были Интернет-технологии. Проект данной курсовой работы представляет собой инструмент для управления информационной системой начальника жилищно-эксплуатационной службы. 1.1 Состав проекта
Данный проект состоит из двух форм: InputForm и ReportForm: На форме InputFormрасположены следующие компоненты (см. рис1): – компонент AddBtn – верхняя кнопка кнопка в правой части формы для добавления записей данных. – компонент CopyBtn – кнопка для копирования записей данных. – компонент DelBtn – кнопка для удаления записей данных. – компонент SortBtn – кнопка для сортировки выделенного столбца в таблице данных. – компонент FindBtn – кнопка для поиска определенного пользователем значения в столбце данных. – компонент SaveBtn – кнопка для сохранения всех табличных данных на форме в текстовых файл. – компонент LoadBtn – кнопка для загрузки всех табличных данных на форме из текстового файла. – компонент SaveBtn – кнопка для сохранения всех табличных данных на форме в текстовых файл. – компонент FBtn – кнопка для отображения формы ReportForm и формирования отчета Ф5. – компонент BitBtn1 – кнопка для закрытия приложения. – компонент MSpinEdit – поле ввода для задания количества этажей M. – компонент KSpinEdit – поле ввода для задания количества подъездов К. На форме также находятся компоненты Label1, Label2 для отображения подсказок для ввода информации и невизуальные компоненты OpenDialog1, SaveDialog1 для вызова стандартных окон открытия и сохранения файлов. – компонент PageControl1 – содержит вкладки TabSheet 1–5 на которых отражены данные (соответственно «Квартиры», «СХЕМА», «ГК (Р)», «Жители члены семей ГК (А)», и «Атрибуты квартир (С)»). Компоненты TabSheet 1–5 содержат в себе элементы таблиц StringGrid 1–5, которые связаны с векторами данных, соответственно «Kvart», «Scheme», «GK», «People», «FlatAtr»). Рис. 1 – Главная форма программы На форме ReportForm расположены следующие компоненты (см. рис 2): – компоненты Panel1, Panel2 – панели на форме для разделения формы на отчет и панель кнопок. – компонент OkBtn – кнопка для закрытия формы. – компонент ListBox1 – список для отображения отчета. Рис. 2 – форма для формирования отчета Ф5. 1.2 Основные модули и процедуры, входящие в состав программного комплекса
Список модулей:
Программа содержит следующие модули: Unit1 – модуль главной формы проекта. Unit2 – модуль отчетной формы проекта. MyTypes – модуль с описаниями классов данных. Список основных процедур, входящих в состав программного комплекса:
– procedureLoadButtonClick– процедура загрузки данных из файла в векторы. – procedureSaveButtonClick – процедура сохранения данных в файл. – procedureFillStringGrid– процедура инициализации таблиц и заполнения их в соответствии с массивами. – procedurePageControl1Change – процедура выбора необходимой страницы с данными и вызова перезаполнения соответствующей таблицы. – procedureSGDblClick – процедура ввода / редактирования данных в текущей ячейки таблицы данных. – procedureAddBtnClick – процедура добавления строки в текущую таблицу данных и вектор данных. – procedureDelBtnClick – процедура для удаления записей данных. – procedureSortBtnClick – процедура для сортировки выделенного столбца в таблице данных. – procedureKSpinEditChange – процедура для изменения значения количества подъездов К в соответствии с полем ввода. – procedure MSpinEditChange – процедура для изменения значения количества этажей M в соответствии с полем ввода. – procedureCopyBtnClick – процедура ввода новой строки данных копированием текущей строки. – procedureFindBtnClick – процедура для поиска определенного пользователем значения в столбце данных. – procedureSortBtn – кнопка для сортировки выделенного столбца в таблице данных. – procedureFButtonClick – процедура для отображения формы ReportForm и формирования отчета Ф5. – procedureReadVec – процедура чтения вектора данных из текстового файла. – procedureWriteVec – процедура записи вектора данных из текстового файла. В программе для хранения данных был спроектирован класс TVector в котором для хранения данных использовался вектор векторов FArr. Для хранения имен колонок использовался вектор FNames, описанный как array [1..100] of string. В программе были созданы 5 объектов класса TVector: Kvart
: TVector; Scheme
: TVector; Gk
: TVector; People
: TVector; FlatAtr
: TVector; Кроме того, в программе для временных нужд объявляются переменные: KPod
,
M
,
i
, j
, k, x
, типа integer (каждая по 4 байта); FileNameT
типа string (200 байт); Ft
типа TextFile (460 байт); FSGVector
– векторссылоктипа TStringGrid (40 байт). Базовой структурой данного проекта является класс TVector в котором для хранения данных использовался вектор векторов FArr и организованы свойства и методы для доступа и обработки данных класса. Объявление вектора FArr выглядит следующим образом: FArr
: array [1..100] of TVarMas, где TVarMas = array [1..MaxN] of Variant; Вектор (array) – это линейная структура данных (список) с элементами одинакового размера в которой адрес элемента однозначно определяется его номером. Для логического определения вектора ему необходимо присвоить имя, указать пару ограниченных значений индекса, а также указать тип элементов. Элементами векторов также могут являются векторы. Логическая схема структуры вектора векторов FArr:
Каждый элемент одного вектора занимает 16 байт памяти. Соответственно FArr
будет занимать (100*100)*16=160000 байт. Логическая схема структуры вектора имен FNames:
Каждый элемент вектора занимает 101 байт памяти. Соответственно вектор FNames
будет занимать 100*101 =10100 байт. Основной операцией обработки структуры в данном программном обеспечении является сортировка QuickSort(по заданию на курсовое проектирование). Быстрая сортировка
(quicksort
), часто называемая qsort по имени реализации в стандартной библиотеке языка Си – широко известный алгоритм сортировки, разработанный английским Информатиком Чарльзом Хоаром. Один из быстрых известных универсальных алгоритмов сортировки массивов (в среднем О (n
log n
) обменов при упорядочении n
элементов), хотя и имеющий ряд недостатков. Алгоритм Быстрая сортировка использует стратегию «разделяй и властвуй». Шаги алгоритма таковы: 1. Выбираем в массиве некоторый элемент, который будем называть опорным элементом
. С точки зрения корректности алгоритма выбор опорного элемента безразличен. С точки зрения повышения эффективности алгоритма выбираться должна медиана, но без дополнительных сведений о сортируемых данных её обычно невозможно получить. Известные стратегии: выбирать постоянно один и тот же элемент, например, средний или последний по положению; выбирать элемент со случайно выбранным индексом. 2. Операция разделения
массива: реорганизуем массив таким образом, чтобы все элементы, меньшие или равные опорному элементу, оказались слева от него, а все элементы, большие опорного – справа от него. Обычный алгоритм операции: 1. Два индекса – l и r, приравниваются к минимальному и максимальному индексу разделяемого массива соответственно. 2. Вычисляется индекс опорного элемента m. 3. Индекс l последовательно увеличивается до m до тех пор, пока l-й элемент не превысит опорный. 4. Индекс r последовательно уменьшается до m до тех пор, пока r-й элемент не окажется меньше опорного. 5. Если r = l – найдена середина массива – операция разделения закончена, оба индекса указывают на опорный элемент. 6. Если l < r – найденную пару элементов нужно обменять местами и продолжить операцию разделения с тех значений l и r, которые были достигнуты. Следует учесть, что если какая-либо граница (l или r) дошла до опорного элемента, то при обмене значение m изменяется на r-й или l-й элемент соответственно. 3. Рекурсивно упорядочиваем подмассивы, лежащие слева и справа от опорного элемента. 4. Базой рекурсии являются наборы, состоящие из одного или двух элементов. Первый возвращается в исходном виде, во втором, при необходимости, сортировка сводится к перестановке двух элементов. Все такие отрезки уже упорядочены в процессе разделения. Поскольку в каждой итерации (на каждом следующем уровне рекурсии) длина обрабатываемого отрезка массива уменьшается, по меньшей мере, на единицу, терминальная ветвь рекурсии будет достигнута всегда и обработка гарантированно завершится. Этот алгоритм в применении к нашему вектору FArr реализован следующи методом класса TVector: // xMode = 1 – по возрастанию // xMode = 2 – по убыванию // xMode = 0-использовать текущий режим SortMode и затем поменять его procedure TVector. Sort (xMode: integer = 0); procedure QSort (l, r: Integer); function Less (var x, y: Variant): boolean; begin if (X < Y) and (SortMode=1) // повозрастанию then Less:=true else Less:=false; end; var i, j, x: integer; y: TVarMas; //Variant; begin i:= l; j:= r; x:= (l+r) DIV 2; repeat while Less (FArr[i] [SortId], FArr[x] [SortId]) do i:= i + 1; while Less (FArr[x] [SortId], FArr[j] [SortId]) do j:= j – 1; if i <= j then begin y:= FArr[i]; FArr[i]:= FArr[j]; FArr[j]:= y; i:= i + 1; j:= j – 1; end; until i > j; if l < j then QSort (l, j); if i < r then QSort (i, r); end; begin {QuickSort}; if xMode<>0 then SortMode:= xMode; QSort (1, Size); if xMode=0 then // Поменяем режим сортировки begin if SortMode = 1 then SortMode:=2 else SortMode:=1; end; end; Оценка эффективности QuickSort является существенно улучшенным вариантом алгоритма сортировки с помощью прямого обмена (его варианты известны как «Пузырьковая сортировка»), известного, в том числе, своей низкой эффективностью. Принципиальное отличие состоит в том, что в первую очередь меняются местами наиболее удалённые друг от друга элементы массива. · Лучший случай.
Для этого алгоритма самый лучший случай – если в каждой итерации каждый из подмассивов делился бы на два равных по величине массива. В результате количество сравнений, делаемых быстрой сортировкой, было бы равно значению рекурсивного выражения CN
= 2CN/2
+N. Это дало бы наименьшее время сортировки. · Среднее.
Даёт в среднем O (n
log n
) обменов при упорядочении n
элементов. В реальности именно такая ситуация обычно имеет место при случайном порядке элементов и выборе опорного элемента из середины массива либо случайно. · 2CN/2
покрывает расходы по сортировке двух полученных подмассивов; N – это стоимость обработки каждого элемента, используя один или другой указатель. Известно также, что примерное значение этого выражения равно CN
= N lg N. · Худший случай.
Худшим случаем, очевидно, будет такой, при котором на каждом этапе массив будет разделяться на вырожденный подмассив из одного опорного элемента и на подмассив из всех остальных элементов. Такое может произойти, если в качестве опорного на каждом этапе будет выбран элемент либо наименьший, либо наибольший из всех обрабатываемых. · Худший случай даёт O (n
²) обменов, но количество обменов и, соответственно, время работы – это не самый большой его недостаток. Хуже то, что в таком случае глубина рекурсии при выполнении алгоритма достигнет n, что будет означать n-кратное сохранение адреса возврата и локальных переменных процедуры разделения массивов. Данное программное обеспечение имеет интуитивно понятный интерфейс и использует все возможности среды Delphi. Программа имеет пять вкладок. При первоначальном запуске активируется первая – вкладка «Квартиры» (см. рис. 3). Рис. 3 – Вкладка таблицы квартир На каждой вкладке с элементами таблицы можно выполнить операции добавления новой строки, удаление существующей, изменение значения ячеек, а также сортировки текущего столбца и поиска заданного значения в текущем столбце. Сортировка выполняется методом быстрой сортировки QuickSort. При выполнении сортировки вначале выполняется сортировка по возрастанию, при следующем нажатии кнопки «Сортировка» выполняется сортировка по убыванию и т.д. На вкладке «Квартиры» можно изменить только колонки: «Номер квартиры», «Стоимость квартиры», «Признак приват.». Остальные колонки рассчитываются по таблицам «Атрибуты квартир (С)» и «СХЕМА» следующим образом: Три первых колонки определяются исходя из данных таблицы «СХЕМА». Колонка «Жилая площадь» = сумма площадей всех комнат, взятых из таблицы С. Колонка «Общая площадь» =атр. 4 + атрибуты 7–9 из таблицы С. Одновременно после ввода / изменения номера квартиры выдается информационное сообщение (см. рис. 4) Рис. 4 – Информационное сообщение В случае попытки редактирования колонок №№2–5 выдается следующее сообщение (см. рис. 5). Рис. 5 – Сообщение о невозможности редактирования ячейки При переходе на вкладку «СХЕМА» отображается следующее окно (см. рис. 6) Рис. 6 – Вкладка схемы квартир «СХЕМА» Третья вкладка «ГК (Р)» содержит атрибуты таблицы главных квартиросъемщиков квартир (см. рис. 7). Рис. 7 – Вкладка таблицы главных квартиросъемщиков ГК(Р) В данной вкладке как и в прдедыдущих можно радактировать атрибуты, удалять их, добавлять новые, сортировать и искать определенные значения. В четвертой вкладке находится таблица жителей квартир – членов семей главных квартиросъемщиков (А). (см. рис. 8) Рис. 8 – Вкладка таблицы жителей квартир – членов семей главных квартиросъемщиков (А) На пятой вкладке находится таблица (С) с атрибутами квартир (С). (см. рис. 9) Рис. 9 – Вкладка таблицы (С) с атрибутами квартир Из всех вкладок доступны кнопки «Сохранить в файл» и «Загрузить из файла» с помощью которых можно сохранить данные всех вкладок в текстовый файл *.dat и загрузить данные из файла. Для формирования отчета формы Ф5 необходимо нажать на кнопку «Отчет Ф5», при этом открывается новое окно с отчетными данными (см. рис. 10). Закрыть окно можно нажав на кнопку «ОК». Рис. 9 – Вкладка таблицы (С) с атрибутами квартир В процессе разработки данного курсового проекта были изучены и закреплены знания по физическим размещениям структур данных и методам их обработки (сортировки). В среде Delphi была разработана информационная система начальника жилищно-эксплуатационной службы. При создании программы не использовались компоненты баз данных данной среды Delphi. Тестирование данного продукта показало полноту реализованных функций и отсутствие ошибок и недочётов в программе. Были изучены базовая структура данных типа вектор и метод быстрой сортировки QuickSort. Литература
unitUnit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, math, Grids, Buttons, Mask, Calendar, ComCtrls, Spin, MyTypes, Unit2; Type TInputForm = class(TForm) BitBtn1: TBitBtn; OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; LoadButton: TButton; SaveButton: TButton; PageControl1: TPageControl; TabSheet1: TTabSheet; TabSheet2: TTabSheet; TabSheet3: TTabSheet; StringGrid1: TStringGrid; DelBtn: TBitBtn; AddBtn: TBitBtn; StringGrid2: TStringGrid; SortBtn: TBitBtn; TabSheet4: TTabSheet; TabSheet5: TTabSheet; StringGrid3: TStringGrid; StringGrid4: TStringGrid; StringGrid5: TStringGrid; Label1: TLabel; KSpinEdit: TSpinEdit; Label2: TLabel; MSpinEdit: TSpinEdit; FindBtn: TBitBtn; CopyBtn: TBitBtn; FButton: TButton; procedure FormCreate (Sender: TObject); procedure LoadButtonClick (Sender: TObject); procedure SaveButtonClick (Sender: TObject); procedure PageControl1Change (Sender: TObject); procedure AddBtnClick (Sender: TObject); procedure SGDblClick (Sender: TObject); procedure DelBtnClick (Sender: TObject); procedure SortBtnClick (Sender: TObject); procedure KSpinEditChange (Sender: TObject); procedure MSpinEditChange (Sender: TObject); procedure SGKeyPress (Sender: TObject; var Key: Char); procedure FormDestroy (Sender: TObject); procedure CopyBtnClick (Sender: TObject); procedure FindBtnClick (Sender: TObject); procedure FButtonClick (Sender: TObject); private {Private declarations} public {Public declarations} //Fz: file of TVector; // Файл типа запись KPod, M: integer; // Количество подъездов и этажей People: TVector; // Вектор – члены семей ГК GK: TVector; // Вектор – главные квартиросъемщики Scheme: TVector; // Вектор – СХЕМА FlatAtr: TVector; // Вектор – Атрибуты квартир KVART: TVector; // Вектор – КВАРТ Ft: TextFile; // Текстовой файл FileNameT: string[200]; // Имя файла FSGVector: array [1..10] of TStringGrid; procedure FillStringGrid (SG: TStringGrid; Vec: TVector); function GetVec: TVector; procedure ReadVec (var Vec: TVector); procedure WriteVec (Vec: TVector); // Запись вектора в файл end; var InputForm: TInputForm; Implementation {$R *.DFM} procedure TInputForm. FormCreate (Sender: TObject); begin KPod:=2; M:= 3; // – Kvart:= TVector. Create; Kvart. Cols:= 7; Kvart. Names[1]:= 'Номер квартиры'; Kvart. Names[2]:= 'число комнат'; Kvart. Names[3]:= 'номер этажа'; Kvart. Names[4]:= 'жилая площадь (кв. м.)'; Kvart. Names[5]:= 'общая площадь (кв. м.)'; Kvart. Names[6]:= 'стоимость квартиры'; Kvart. Names[7]:= 'Приват.'; // – Scheme:= TVector. Create; Scheme. Cols:= 4; Scheme. Names[1]:= 'Кв. 1'; Scheme. Names[2]:= 'Кв. 2'; Scheme. Names[3]:= 'Кв. 3'; Scheme. Names[4]:= 'Кв. 4'; // – GK:= TVector. Create; GK. Cols:= 8; GK. Names[1]:= 'Номер Квартиры'; GK. Names[2]:= 'Фамилия'; GK. Names[3]:= 'Имя'; GK. Names[4]:= 'Отчество'; GK. Names[5]:= 'Год рождения'; GK. Names[6]:= 'Место работы'; GK. Names[7]:= 'Льготы'; GK. Names[8]:= 'Долг (тыс. руб.)'; // – // 1.5. Таблица А содержит список жильцов – членов семей главных квартиросъемщиков: // 1) фамилия, // 2) родственное отношение к ГК (мать / отец/муж/жена / дочь/сын), // 3) номер квартиры, // 4) признак «пенсионер / учащийся / работает / дошкольник». People:= TVector. Create; People. Cols:= 4; People. Names[1]:= 'Фамилия'; People. Names[2]:= 'Родств.отн-ние'; People. Names[3]:= 'Номер квартиры'; People. Names[4]:= 'Признак'; People. Names[5]:= 'Место работы'; People. Names[6]:= 'Льготы'; People. Names[7]:= 'Долг (тыс. руб.)'; // 1.6. Таблица С содержит следующие атрибуты квартир (в соответствии с числом комнат): // 1) число комнат, // 2) месячная квартплата, // 3) площадь первой комнаты (кв. м.), // 4) площадь второй комнаты (если она есть), // 5) площадь третьей комнаты, // 6) площадь четвертой комнаты, // 7) площадь коридора, // 8) площадь кухни, // 9) общая площадь туалета и ванной комнаты. FlatAtr:= TVector. Create; FlatAtr. Cols:= 9; FlatAtr. Names[1]:= 'Числокомн.'; FlatAtr. Names[2]:= 'Квартплата'; FlatAtr. Names[3]:= 'Пл.ком. №1'; FlatAtr. Names[4]:= 'Пл.ком. №2'; FlatAtr. Names[5]:= 'Пл.ком. №3'; FlatAtr. Names[6]:= 'Пл.ком. №4'; FlatAtr. Names[7]:= 'Пл.коридора'; FlatAtr. Names[8]:= 'Пл.кухни'; FlatAtr. Names[9]:= 'Пл.туалета'; // – PageControl1Change(Sender); FSGVector[1]:= StringGrid1; FSGVector[2]:= StringGrid2; FSGVector[3]:= StringGrid3; FSGVector[4]:= StringGrid4; FSGVector[5]:= StringGrid5; end; procedure TInputForm. ReadVec (var Vec: TVector); var x, i, j: integer; St: String; begin Readln (Ft, x); Vec. Cols:= x; for i:=1 to Vec. Cols do begin Readln (Ft, St); Vec. Names[i]:= St; end; Readln (Ft, x); Vec. Size:= x; for i:=1 to Vec. Size do begin for j:=1 to Vec. Cols do begin Readln (Ft, St); Vec.X [i, j]:= St; end; end; Vec. SortId:= 1; Vec. SortMode:= 1; end; procedure TInputForm. WriteVec (Vec: TVector); var i, j: integer; begin Writeln (Ft, Vec. Cols); for i:=1 to Vec. Cols do Writeln (Ft, Vec. Names[i]); Writeln (Ft, Vec. Size); for i:=1 to Vec. Size do begin for j:=1 to Vec. Cols do Writeln (Ft, Vec.X [i, j]); end; end; // Чтение данных из файла procedure TInputForm. LoadButtonClick (Sender: TObject); begin OpenDialog1. Title:= 'Открыть из файла'; // Изменение заголовка окна диалога if not OpenDialog1. Execute then exit; FileNameT:= OpenDialog1. FileName; // Возвращение имени дискового файла AssignFile(Ft, FileNameT); // Связывание файловой переменной Fz с именем файла Reset(Ft); // Открытие существующего файла ReadVec(Kvart); // Чтение вектора из файла ReadVec(Scheme); ReadVec(GK); ReadVec(People); ReadVec(FlatAtr); PageControl1Change(Sender); CloseFile(Ft); end; procedure TInputForm. SaveButtonClick (Sender: TObject); begin ifnotSaveDialog1. Executethenexit; begin FileNameT:= SaveDialog1. FileName; // Возвращение имени дискового файла AssignFile(Ft, FileNameT); // Связывание файловой переменной Fz с именем файла {$I-} Rewrite(Ft); // Открытие нового файла {$I+} if not((IOResult = 0) and (FileNameT <> «)) then begin Application. MessageBox ('Не возможно открыть файл!', 'Ошибка', MB_OK); exit; end; end; WriteVec(Kvart); // Запись в файл WriteVec(Scheme); WriteVec(GK); WriteVec(People); WriteVec(FlatAtr); CloseFile(Ft); // Закрытие файла end; // Процедура заполнения объекта StringGrid данными из Вектора Vec procedure TInputForm. FillStringGrid (SG: TStringGrid; Vec: TVector); var i, j: integer; begin Sg. ColCount:= Vec. Cols+1; if Vec. Size=0 then Sg. RowCount:=2 else Sg. RowCount:=Vec. Size+1; for i:=1 to Vec. Cols do Sg. Cells [i, 0]:= Vec. Names[i]; for i:=1 to Vec. Size do begin Sg. Cells [0, i]:= IntToStr(i); for j:=1 to Vec. Cols do Sg. Cells [j, i]:= Vec.X [i, j]; end; Sg. ColWidths[0]:= 25; end; procedure TInputForm. PageControl1Change (Sender: TObject); begin case PageControl1. ActivePageIndex of 0: FillStringGrid (StringGrid1, Kvart); 1: FillStringGrid (StringGrid2, Scheme); 2: FillStringGrid (StringGrid3, GK); 3: FillStringGrid (StringGrid4, People); 4: FillStringGrid (StringGrid5, FlatAtr); end; end; procedure TInputForm. AddBtnClick (Sender: TObject); var SG: TStringGrid; Vec: TVector; begin Sg:= FSGVector [PageControl1. ActivePageIndex+1]; Vec:= GetVec; Vec. Add; FillStringGrid (SG, Vec); end; procedure TInputForm.SGDblClick (Sender: TObject); var NRooms, NKv, NKvart, NPod, NFloor: integer; porch: array [0..MaxN] of integer; SG: TStringGrid; Vec: TVector; i, j, x, k, l: integer; InputString: String; begin Sg:= TStringGrid(Sender); i:= Sg. Selection. Left; j:= Sg. Selection. Top; Vec:= GetVec; if (i<1) then exit; // Запределамиредактирования if (Sg. Name = 'StringGrid1') and (i in [2,3,4,5]) then begin Application. MessageBox( 'Это поле заполняется автоматически по номеру квартиры и не редактируется!' 'Ошибка', MB_OK); exit; end; InputString:= InputBox ('', 'Введите значение', Vec.X [j, i]); if InputString='' then exit; SG. Cells [i, j]:= InputString; Vec.X [j, i]:= InputString; if (Sg. Name = 'StringGrid1') and (i = 1) then begin NKvart:= Vec.X [j, i]; porch[0]:= 0; x:= 0; for i:=1 to Scheme. Size do begin porch[i]:= 2; if Scheme.X [i, 3]='' then porch[i]:= 2 else if Scheme.X [i, 4]='' then porch[i]:= 3 else porch[i]:=4; if NKvart <= x + (porch[i]*M) then begin NPod:= i; // Определили номер подъезда NFloor:= (NKvart-x) divM +1; // Определили номер этажа NKv:= (NKvart-x) modM; // Определили номер кв. на этаже if NKv=0 then NKv:= M; NRooms:= Scheme.X[i, NKv]; // Определили кол-во комнат // Запишем количество комнат в квартире SG. Cells[2, j]:= IntToStr(NRooms); Vec.X[j, 2]:= NRooms; // Запишем номер этажа SG. Cells[3, j]:= IntToStr(NFloor); Vec.X[j, 3]:= NFloor; for k:=1 to FlatAtr. Size do begin if FlatAtr.X [i, 1]= NRooms then // совпадает количество комнат begin x:= 0; for l:=1 to NRooms do try x:= x + StrToInt (FlatAtr.X [k, 2+l]); except end; // Запишем жилую площадь Vec.X [j, 4]:= x; SG. Cells [4, j]:= Vec.X [j, 4]; x:= x + StrToInt (FlatAtr.X [i, 7])+StrToInt (FlatAtr.X [i, 8])+ StrToInt (FlatAtr.X [i, 9]); // Запишем общую площадь SG. Cells [5, j]:= IntToStr(x); Vec.X [j, 5]:= x; break; end; end; InputString:= 'Квартира №'+IntToStr(NKvart)+ ' находится в подъезде №'+IntToStr(NPod)+ ' на этаже №'+IntToStr(NFloor)+ ' ('+IntToStr(NRooms)+' комната(ы)).'; Application. MessageBox (PChar(InputString), '', MB_OK); exit; end; x:= x + porch[i]*M; end; Application. MessageBox('Указанная квартира не найдена по схеме дома', 'Ошибка', MB_OK); SG. Cells[2, j]:= «; Vec.X[j, 2]:= «; SG. Cells [3, j]:= «; Vec.X [j, 3]:= «; end; if (j>Vec. Size) then // Кликнули за пределами области данных begin Vec. Add; FillStringGrid (SG, Vec); end; end; function TInputForm. GetVec: TVector; begin case PageControl1. ActivePageIndex of 0: result:= Kvart; 1: result:= Scheme; 2: result:= GK; 3: result:= People; 4: result:= FlatAtr; else result:= Kvart; end; end; procedure TInputForm. DelBtnClick (Sender: TObject); var SG: TStringGrid; Vec: TVector; i: integer; begin Sg:= FSGVector [PageControl1. ActivePageIndex+1]; i:= Sg. Selection. Top; // удаляемая строка Vec:= GetVec; Vec. Delete(i); FillStringGrid (SG, Vec); end; procedure TInputForm. SortBtnClick (Sender: TObject); var SG: TStringGrid; Vec: TVector; i: integer; begin Sg:= FSGVector [PageControl1. ActivePageIndex+1]; i:= Sg. Selection. Left; // Будемсортироватьэтотстолбец Vec:= GetVec; if (i<1) thenexit; // За пределами редактирования Vec. SortId:= i; // установим сортируемый столбец Vec. Sort; FillStringGrid (SG, Vec); end; procedure TInputForm.KSpinEditChange (Sender: TObject); begin KPod:= KSpinEdit. Value; end; procedure TInputForm.MSpinEditChange (Sender: TObject); begin M:= MSpinEdit. Value; end; procedure TInputForm.SGKeyPress (Sender: TObject; var Key: Char); begin if Key =#13 then // Если нажата клавиша Enter то… SGDblClick(Sender); end; procedure TInputForm. FormDestroy (Sender: TObject); begin People. Destroy; GK. Destroy; Scheme. Destroy; FlatAtr. Destroy; Kvart. Destroy; end; procedure TInputForm. CopyBtnClick (Sender: TObject); var SG: TStringGrid; Vec: TVector; i: integer; begin Sg:= FSGVector [PageControl1. ActivePageIndex+1]; i:= Sg. Selection.top; // Будемкопироватьэтустроку Vec:= GetVec; Vec. AddCopy(i); FillStringGrid (SG, Vec); end; procedure TInputForm. FindBtnClick (Sender: TObject); var SG: TStringGrid; Vec: TVector; res, Row, Col: integer; InputString: String; begin Sg:= FSGVector [PageControl1. ActivePageIndex+1]; Col:= Sg. Selection. Left; Row:= Sg. Selection. Top; Vec:= GetVec; if (Col<1) thenexit; // За пределами редактирования InputString:= InputBox('', 'Введите значение для поиска', «); if InputString='' then exit; res:= Vec. Find (Col, Row, InputString); if res=0 then begin Application. MessageBox ('Указанное значение не найдено!', 'Ошибка', MB_OK); exit; end; Sg. Row:= res; end; procedure TInputForm.FButtonClick (Sender: TObject); var NKvart, NPod: integer; fl, i, k, x, p: integer; St, FIO: String; begin // ReportForm. ListBox1. Items. Clear; ReportForm. ListBox1. Items. Add( ' Cписок всех жильцов дома, проживающих в квартирах, '+ 'в которых ГК имеет льготы по квартплате'); for k:=1 to People. Size do begin NKvart:= People.x [k, 3]; // Номер квартиры fl:= 0; for i:=1 to GK. Size do begin if Gk.X [i, 1]=NKvart then begin fl:= 1; break; end; end; if (fl=0) or ((fl=1) and (Gk.X [i, 7]<>'да')) then continue; // У ГК нет льгот; FIO:= People.X [k, 1]; x:= 0; NPod:= 0; for i:=1 to Scheme. Size do begin if Scheme.X [i, 3]='' then p:= 2 else if Scheme.X [i, 4]='' then p:= 3 else p:=4; if NKvart <= x + (p*M) then begin NPod:= i; break; end; end; for i:=1 to Kvart. Size do if Kvart.X [i, 1]= NKvart then begin // получили искомую строку квартиры St:= FIO+' кв. №'+IntToStr(NKvart)+' подъезд №'+IntToStr(NPod)+' – '+ IntToStr (Kvart.X [i, 2])+' комн. '; if Kvart.X [i, 7]='да' thenSt:= St + ' – кв-ра приватизирована ' elseSt:= St + ' – кв-ра не приватизирована '; // списка: Фамилия жильца, номер квартиры, подъезд, число комнат, признак ReportForm. ListBox1. Items. Add(St); end; end; ReportForm. ShowModal; end; end. unit Unit2; interface uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ComCtrls, ExtCtrls; type TReportForm = class(TForm) Panel1: TPanel; Panel2: TPanel; OKBtn: TButton; CancelBtn: TButton; ListBox1: TListBox; private {Private declarations} public {Public declarations} end; var ReportForm: TReportForm; implementation {$R *.DFM} end. unit MyTypes; interface uses Sysutils, Contnrs; const MaxN = 100; type TVarType = Variant; //TVarRec; TVarMas = array [1..MaxN] of TVarType; TVector = class (TInterfacedObject) private {Private declarations} FArr: array [1..MaxN] of TVarMas; //source data FNum: integer; //number of items FCols: integer; //number of columns FNames: array [1..MaxN] of String[MaxN]; //names of columns function GetSize: Integer; procedure SetSize (value: Integer); function GetCols: Integer; procedure SetCols (value: Integer); procedure SetX (Index1, Index2: integer; value: TVarType); function GetX (Index1, Index2: integer): TVarType; procedure SetName (Index: integer; value: String); function GetName (Index: integer): String; public SortId: integer; // Текущийсортируемыйстолбец SortMode: integer; // Текущийрежимсортировки constructor Create; property X [Index1, Index2: Integer]: TVarType read GetX write SetX; property Names [Index: Integer]: String read GetName write SetName; property Size: Integer read GetSize write SetSize; property Cols: Integer read GetCols write SetCols; procedure Sort (xMode: integer = 0); procedure Add(); procedure AddCopy (Index: integer); procedure Delete (Index: integer); function Find (Col, Row: integer; Value: Variant): integer; end; implementation constructor TVector. Create; begin FNum:= 0; SortId:= 0; SortMode:= 1; end; function TVector. GetSize: Integer; begin result:= FNum; end; procedure TVector. SetSize (value: Integer); begin FNum:= value; end; function TVector. GetCols: Integer; begin result:= FCols; end; procedure TVector. SetCols (value: Integer); begin FCols:= value; end; procedure TVector. SetX (Index1, Index2: integer; value: TVarType); begin FArr[Index1] [Index2]:= value; end; function TVector. GetX (Index1, Index2: integer): TVarType; begin result:= FArr[Index1] [Index2]; end; function TVector. GetName (Index: integer): String; begin result:= FNames[Index]; end; procedure TVector. SetName (Index: integer; value: String); begin FNames[Index]:= Value; end; procedure TVector. Add(); begin FNum:= FNum + 1; end; procedure TVector. AddCopy (Index: integer); begin FNum:= FNum + 1; FArr[FNum]:= FArr[Index]; end; procedure TVector. Delete (Index: integer); var i: integer; begin if FNum=0 then exit; // Вродекакнечегоудалять for i:=Index+1 to FNum do // Перенесемстроки FArr [I-1]:= FArr[I]; FNum:= FNum -1; // уменьшаем количество end; // Процедура сортировки вектора данных по индексу SortId с режимом xMode // xMode = 1 – по возрастанию // xMode = 2 – по убыванию // xMode = 0 – использовать текущий режим SortMode и затем поменять его procedure TVector. Sort (xMode: integer = 0); procedure QSort (l, r: Integer); function Less (var x, y: Variant): boolean; begin if (X < Y) and (SortMode=1) // повозрастанию then Less:=true else Less:=false; end; var i, j, x: integer; y: TVarMas; //Variant; begin i:= l; j:= r; x:= (l+r) DIV 2; repeat while Less (FArr[i] [SortId], FArr[x] [SortId]) do i:= i + 1; while Less (FArr[x] [SortId], FArr[j] [SortId]) do j:= j – 1; if i <= j then begin y:= FArr[i]; FArr[i]:= FArr[j]; FArr[j]:= y; i:= i + 1; j:= j – 1; end; until i > j; if l < j then QSort (l, j); if i < r then QSort (i, r); end; begin {QuickSort}; if xMode<>0 then SortMode:= xMode; QSort (1, Size); if xMode=0 then // Поменяем режим сортировки begin if SortMode = 1 then SortMode:=2 else SortMode:=1; end; end; // Процедура поиска значения Value в столбце Col с позиции Row // возвращает индекс найденой строки или 0 если ничего не найдено function TVector. Find (Col, Row: integer; Value: Variant): integer; var i: integer; begin result:= 0; for i:=Row to FNum do if FArr[I] [Col] = Value then begin result:= i; exit; end; end; end.
|