ЛАБОРАТОРНАЯ РАБОТА #4 ТЕМА: Интегрированные структуры данных, записи.
1. Цель работы Приобретение и закрепление навыков в работе с записями, в интергации данных, в модульном программировании. 2. Прорабатываемые темы Простейшие статические структуры данных. Векторы, массивы, записи. Типичные операции. 3. Постановка задачи Для заданной прикладной области разработать описание объектов этой области. Разработать процедуры, реализующие базовые операции над этими объектами, в том числе: • текстовый ввод-вывод (консольный и файловый); • присваивание; • задание константных значений; • сравнение (не менее 2-х типов).
Процедуры и описания данных должны составлять отдельный модуль (модуль типа данных). Подготовить на магнитном носителе файл исходных данных, содержащих не менее 10 значений конкретных объектов. Используя процедуры и описания модуля типа данных, разработать программу, обеспечивающую ввод исходных данных из файла данных в память и хранение их в массиве, сортировку массива по алфавитному и по числовому параметру.
4. Варианты индивидуальных заданий Для каждой области перечислены параметры объекта. Среди параметров обязательно есть ключевое алфавитное поле (например, фамилия), которое идентифицирует объект, у каждого объекта имеется также одно или несколько числовых полей, по которым вероятны обращения к объекту. Набор характеристик может быть расширен и усложнен по усмотрению исполнителя. Nпп Прикладная область Атрибуты информации
1 Отдел кадров фамилия сотрудника, имя, отчество, должность, стаж работы, оклад 2 Красная книга вид животного, род, семейство, место обитания, численность популяции 3 Производство обозначение изделия, группа к которой оно относится, год выпуска, объем выпуска, расход металла 4 Персональные ЭВМ фирма-изготовитель, тип процессора, тактовая частота, емкость ОЗУ, емкость жесткого диска 5 Библиотека автор книги, название, год издания, код УДК, цена, количество в библиотеке 6 Спутники планет название, название планеты-хозяина, год открытия, диаметр, период обращения 7 Радиодетали обозначение, тип, номинал, количество на схеме, обозначение возможного заменителя 8 Текстовые редакторы наименование, фирма-изготовитель, количество окон, количество шрифтов, стоимость 9 Телефонная станция номер абонента, фамилия, адрес, наличие блокиратора, задолженность 10 Быт студентов фамилия студента, имя, отчество, факультет, размер стипендии, число членов семьи 11 Спортивные соревнования фамилия спортсмена, имя, команда, вид спорта, зачетный результат, штрафные очки 12 Соревнование факультетов по успеваемости факультет,количество студентов, средний балл по факультету, число отличников, число двоечников 13 С/х работы фамилия студента, имя, отчество, факультет, вид работ, заработок 14 Сельхозработы наименование с/х предприятия, вид собственности, число работающих, основной вид продукции, прибыль 15 Сведения о семье фамилия студента, имя, отчество, факультет, специальность отца, специальность матери, количество братьев и сестер 16 Скотоводство вид животных, количество особей в стаде в возрасте до 1 года, количество особей 1 - 3 лет, свыше 3 лет, смертность в каждой группе, рождаемость 17 Микросхемы памяти обозначение, разрядность, емкость, время доступа, количество на схеме, стоимость 18 Описание изображения тип фигуры (квадрат, окружность и т.п.), координаты на плоскости, числовые характеристики (длина строрны, радиус и т.п.). 19 Лесное хозяйство наименование зеленого массива, площадь, основная порода, средний возраст, плотность деревьев на кв.км 20 Городской транспорт вид транспорта, номер маршрута, начальная остановка, конечная остановка, время в пути
5. Пример решения задачи 5.1 Индивидуальное задание Область: деканат. Атрибуты информации: фамилия студента; имя; отчество; год рождения; обозначение группы; средний балл в сессию. 5.2. Разработка алгоритма решения 5.2.1. Выбор метода. 1). Представление данных Очевидно, что заданная структура классификаторов объекта легко представима в виде записи (тип данных - record). Наиболее вероятными ключами для поиска в массиве объектов являются фамилия (алфавитный ключ) и средний балл (числовой ключ).Возможен также выбор по группе и номеру курса (последний может быть извлечен из обозначения группы). Запись может быть описана как тип данных: stud = record family : string[15]; { фамилия } name : string[15]; { имя } fname : string[15]; { отчество } yb : integer; { год рождения } group : string[6]; { обозначение группы } mark : real; { средний балл } end; 2). Модульная структура программы Описание типа данных "студент" выносится в отдельный файл (модуль). Сюда же включаются программные единицы, реализующие элементарные операции над объектами. 3). Инкапсуляция При разработке модуля применяется метод инкапсуляции: внешняя программа (программа пользователя) использует тип данных "студент", при этом она не имеет прямого доступа к внутренней структуре объекта этого типа. Все операции с данными этого типа, в том числе и операции над компонентами внутренней структуры программа выполняет через посредство процедур/функций, содержащихся в модуле. 4). Состав базовых функций Для работы с типом данных "студент" принимается следующий набор операций: • ввод значения объекта из текстового файла; • ввод значения объекта с консоли; • вывод значения объекта в текстовый файл; • вывод значения объекта на консоль; • присваивание объекту константных значений; • присваивание объектов; • сравнение объектов по фамилиям; • сравнение объектов по оценкам; • сравнение объектов по группам. 5.2.3. Структура программы Исходный текст программы состоит из двух модулей: модуль LAB4UNIT.PAS и модуль LAB5.PAS. Модуль LAB4UNIT.PAS иимеет заголовок Unit Lab4Unit. Этот модуль в секции INTERFACE содержит описание типа данных stud и функций, реализующих операции над этим типом данных: • ReadTStud - ввод значения объекта из текстового файла; • ReadStud - ввод значения объекта с консоли; • WriteTStud - вывод значения объекта в текстовый файл; • WriteStud - вывод значения объекта на консоль; • ConstStud - присваивание объекту константных значений; • AssgnStud - присваивание объектов; • CompName - сравнение объектов по фамилиям; • CompMark - сравнение объектов по оценкам; • CompGroup - сравнение объектов по группам; а также вспомогательных функций, используемых в вышеперечисленных: • ParseStud - разбор строки, содержащей значение объекта; • ParseString - выборка слова из строки. В секции IMPLEMENTATION - тексты перечисленных программных единиц. Модуль LAB4.PAS иимеет заголовок Program Lab4, оператором Uses к нему подключатся Unit Lab4Unit. Результатом его компиляции явится файл LAB4.EXE. В модуле помимо основной программы имеется процедура WriteArray - вывода массива. 5.2.4. Описание программы. 5.2.4.1. Модуль LAB4UNIT Процедура ReadTStud предназначена для ввода значения одного объекта из текстового файла Procedure ReadTStud (var a : stud; var tf : tfile); a - переменная, в которую процедура заносит значение; tf - файл, из которого производится ввод (файл д.б. открыт). Процедура производит ввод строки значения из файла tf в символьную строку Lab4Units (доступную всем программным единицам модула), а затем обращается к процедуре ParseStud, которая заносит в поля структуры a выбранные из строки значения. Процедура ReadStud предназначена для ввода значения одного объекта с консоли Procedure ReadStud (var a : stud); a - переменная, в которую процедура заносит значение. Процедура производит ввод строки значения c консоли в символьную строку Lab4Units, а затем обращается к процедуре ParseStud. Процедура WriteTStud предназначена для вывода значения одного объекта в текстовый файл Procedure WriteTStud(a : stud; var tf : tfile); a - переменная, значение которой выводится; tf - файл, в который производится вывод (файл д.б. открыт). Процедура производит вывод полей структуры a в файл tf, значения разделяются пробелами. Процедура WriteStud предназначена для вывода значения одного объекта на терминал Procedure WriteStud(a : stud); a - переменная, значение которой выводится. Процедура производит вывод полей структуры a на терминал, значения разделяются пробелами. Процедура WriteFStud предназначена для форматного вывода значения одного объекта на терминал Procedure WriteFStud(a : stud); a - переменная, значение которой выводится. Процедура производит вывод полей структуры a на терминал, при этом поля family, name, fname сцепляются в одну строку длиной 44. Эта строка и значения других полей выводятся на экран с фиксированной длиной экранного представления для каждого поля. Процедура ConstStud предназначена для присваивания значений полям записи stud Procedure ConstStud(var a : stud; f,n,fn:string; y: integer; g:string; m:real); a - переменная stud, полям которой присваиваются значения; f - присваиваемое значение поля фамилии, n - поля имени, fn - поя отчества, y - поля года, g - поля группы, m - поля оценки. Действия процедуры состоят в присваивании полям структуры значений параметров. Процедура AssgnStud предназначена для присваивания переменной типа stud значения другой переменной того же типа Procedure AssgnStud(var a : stud; b : stud); a - переменная-источник, b - переменная преемник. Присваивание выполняется простым оператором присваивания. Функция CompName предназначена для сравнение объектов по полю фамилии Function CompName(a, b : stud) : integer; a и b - сравниваемые переменные. Функция возвращает 1, если поле family в a больше (в алфавитном смысле), чем в b; 0, если поля family равны; -1, если поле family в a меньше, чем в b. Алгоритм функции состоит в проверке указанных условий и установке возвращаемого значения в зависимости от их выполнения. Функция CompMark предназначена для сравнение объектов по полю среднего балла Function CompMark(a, b : stud) : integer; a и b - сравниваемые переменные. Функция возвращает 1, если поле mark в a больше, чем в b; 0, если поля mark равны; -1, если поле mark в a меньше, чем в b. Алгоритм функции состоит в проверке указанных условий и установке возвращаемого значения в зависимости от их выполнения. Функция CompGroup предназначена для сравнение объектов по полю группы Function CompGroup(a, b : stud) : integer; a и b - сравниваемые переменные. Функция возвращает 1, если поле group в a равно полю group в b; 1, если поля group не равны. Алгоритм функции состоит в проверке указанных условий и установке возвращаемого значения в зависимости от их выполнения. Функция ParseString предназначена для выделение из строки очередного слова Function ParseString: string; К моменту вызова функции в переменной Lab4Units, описанной в секции INTERFACE, находится анализируемая строка. Функция находит длину строки Lab4Units и позицию в ней первого отличного от пробела символа. Если в начале строки есть пробелы, то Lab4Units корректируется таким образом, чтобы избавиться от ведущих пробелов. Затем определяется позиция конца слова (первого следующего за словом пробела или конца строки). Выделяется подстрока от первого символа Lab4Units до конца слова, а из Lab4Units выделенное слово удаляется. Выделенное слово является возвращаемым значением функции. Процедура ParseStud предназначена для разбора строки, содержащей значения полей структуры stud. Procedure ParseStud(var a : stud); a - переменная stud, полям которой присваиваются значения. Процедура вызывает функцию ParseString и выделенное ею первое слово присваивается полю family. При следующем вызове ParseString выделенное ею слово присваивается полю name. При следующем вызове - полю fname. При следующем вызове - строке s1, значение которой преобразуется в число и записывается в поле yb. При следующем вызове ParseString выделенное ею слово присваивается полю group. При следующем вызове - строке s1, значение которой преобразуется в число и записывается в поле mark. 5.2.4.2. Модуль LAB4 Процедура WriteArray предназначена для вывода значений элементов массива записей stud Procedure WriteArray; Внешний по отношению к процедуре мaccив записей a содержит введенные записи, переменная n - число записей в массиве. Процедура перебирает записи массива и для каждой выбранной записи обращается к процедуре вывода WriteFStud. После вывода каждых 15 записей (переменная l - счетчик по модулю 15) процедура делает паузу до нажатия клавиши Enter. Основная программа выполняет следующие действия. Открывает файл исходных данных и считывает из при помощи процедуры ReadTStud значения объектов - до тех пор, пока не дойдет до конца файла. Считанные значения записываются в массив a, одновременно в переменной n подсчитывается число введенных объектов. После ввода массив a выводится на печать при помощи процедуры WriteArray. Сортировка массива по фамилиям производится методом пузырьков. В каждой итерации признак перестановки k устанавливается в 0 а затем перебирается массив a, причем производится сравнение фамилий в соседних элемента при помощи функции CompName. Если фамилия в текущем элементе больше, чем в следующем, элементы меняются местами, а признак перестановки k взводится в 1. Переборы массива повторяются до тех пор, пока после очередного перебора не окажется, что признак k остался нулевым. После сортировки массив a выводится на печать при помощи процедуры WriteArray. Сортировка массива по оценкам отличается от сортировки по фамилиям только тем, что для сравнения элементов используется функция CompMark. 5.3. Исходные данные контрольного примера В файл LAB4.TDT заносятся исходные данные... Ризаев Роман Тимофеевич 1976 АП38б 3.33 Бижко Елена Евгеньевна 1974 АП38а 3.87 . . . . . . . . . ... ... ... 5.4. Текст программы {*************** Файл LAB4UNIT.PAS ****************} { Операции над структурой данных "студент" } Unit Lab4Unit; INTERFACE Type { тип данных - студент } stud = record family : string[15]; { фамилия } name : string[15]; { имя } fname : string[15]; { отчество } yb : integer; { год рождения } group : string[6]; { обозначение группы } mark : real; { средний балл } end; tfile = text; Var Lab4Units : string; { рабочая строка } { Ввод значения объекта из текстового файла } Procedure ReadTStud (var a : stud; var tf : tfile); { Ввод значения объекта с консоли } Procedure ReadStud (var a : stud); { Вывод значения объекта в текстовый файл } Procedure WriteTStud(a : stud; var tf : tfile); { Вывод значения объекта на консоль } Procedure WriteStud(a : stud); { Форматный вывод значения объекта на терминал } Procedure WriteFStud(a : stud); { Присваивание объекту константных значений } Procedure ConstStud(var a : stud; f,n,fn:string; y: integer; g:string; m:real); { Присваивание объектов } Procedure AssgnStud(var a : stud; b : stud); { Сравнение объектов по фамилиям } Function CompName(a, b : stud) : integer; { Сравнение объектов по оценкам } Function CompMark(a, b : stud) : integer; { Сравнение объектов по группам } Function CompGroup(a, b : stud) : integer; { Вспомогательные функции, не предъявляемые пользователю } { Разбор строки, содержащей значение объекта } Procedure ParseStud(var a : stud); { Выборка слова из строки } Function ParseString : string; IMPLEMENTATION {=== Ввод значения объекта из текстового файла ===} Procedure ReadTStud (var a : stud; var tf : tfile); c : integer; begin { Список значений полей вводится как строка } readln(tf,Lab4Units); ParseStud(a); end; {=== Ввод значения объекта с консоли ===} Procedure ReadStud(var a : stud); begin { Список значений полей вводится как строка } readln(Lab4Units); ParseStud(a); end; {=== Вывод значения объекта в текстовый файл ===} Procedure WriteTStud(a : stud; var tf : tfile); begin with a do begin writeln(tf,family,' ',name,' ',fname,' ',yb,' ',group,' ',mark:4:2); end; end; {=== Вывод значения объекта в текстовый файл ===} Procedure WriteStud(a : stud); begin with a do begin writeln(family,' ',name,' ',fname,' ',yb,' ',group,' ',mark:4:2); end; end; {=== Форматный вывод значения объекта на терминал ===} Procedure WriteFStud(a : stud); Var s : string[47]; i : integer; begin { ФИО превращается в одну строку длиной 44 } for i:=1 to 47 do s[i]:=' '; with a do begin s:=family+' '+name+' '+fname; s[0]:=Chr(44); write(s,' (',yb:4,'г.р.) гр.'); write(group:6,' ср.балл=',mark:4:2); end; end; {=== Присваивание константных значений ===} Procedure ConstStud(var a : stud; f,n,fn:string; y: integer; g:string; m:real); begin with a do begin family:=f; name:=n; fname:=fn; yb:=y; group:=g; mark:=m; end; end; {=== Присваивание объектов ===} Procedure AssgnStud(var a : stud; b : stud); begin a:=b; end; {=== Сравнение объектов по фамилиям ===} Function CompName(a, b : stud) : integer; { Возвращает -1, если фамилия в a <, чем в b; 0, если =; 1, если > } begin if a.family=b.family then CompName:=0 else if a.family>b.family then CompName:=1 else CompName:=-1 end; {=== Сравнение объектов по оценкам ===} Function CompMark(a, b : stud) : integer; { Возвращает -1, если оценка в a <, чем в b; 0, если =; 1, если > } begin if a.mark=b.mark then CompMark:=0 else if a.mark>b.mark then CompMark:=1 else CompMark:=-1 end; {=== Сравнение объектов по группам ===} Function CompGroup(a, b : stud) : integer; { Возвращает 0, если обозн.группы в а совпадает с b; 1, если не совпадает } begin if a.group=b.group then CompGroup:=0 else CompGroup:=1; end; {=== Разбор строки, содержащей значение объекта ===} Procedure ParseStud(var a : stud); Var s1 : string[80]; c : integer; begin with a do begin { из строки выделяются слова-значения полей } { фамилия } family:=ParseString; { имя } name:=ParseString; { отчество } fname:=ParseString; { год рожд. } s1:=ParseString; Val(s1,yb,c); if c<>0 then yb:=-1; { группа } group:=ParseString; { ср.балл } s1:=ParseString; Val(s1,mark,c); if c<>0 then mark:=-1; end; end; {=== Выделение из строки очередного слова ===} Function ParseString: string; Label L1; Var l, i, p : integer; m : string[20]; begin l:=Length(Lab4Units); { длина строки } { поиск 1-го символа, отличного от пробела } for i:=1 to l do begin if Lab4Units[i]<>' ' then goto L1; end; L1: { удаление ведущих пробелов } if i>1 then begin l:=l-i+1; Lab4Units:=Copy(Lab4Units,i,l); end; { определение позиции конца слова } p:=Pos(' ',Lab4Units); if p=0 then p:=l+1; { выделение слова } m:=Copy(Lab4Units,1,p-1); { удаление выделенного слова из строки } Lab4Units:=Copy(Lab4Units,p+1,l-p); ParseString:=m; end; END. {*************** Файл LAB4.PAS ****************} Program LAB4; uses Lab4Unit; Var a : array[1..100] of stud; { массив студентов } b:stud; { промежуточный студент } n : integer; { число студентов } k, i, l :integer; { счетчики } SrcFile : text; { файл исходных данных } { Вывод массива записей } Procedure WriteArray; Var i, l : integer; begin { Вывод результатов } l:=0; for i:=1 to n do begin WriteFStud(a[i]); { форматный вывод на консоль } l:=l+1; if l=15 then begin Write('=== Для продолжения нажмите Enter ==='); ReadLn; l:=1; end; end; WriteLn('=== Конец. Нажмите Enter ==='); ReadLn; end; begin { Открытие файла исходных данных } assign(SrcFile,'lab4.tdt'); reset(SrcFile); { Ввод данных } n:=0; l:=1; WriteLn('=== Исходные данные ==='); while not Eof(SrcFile) do begin n:=n+1; { подсчет записей } ReadTstud(a[n],SrcFile); { ввод из файла } end; close(SrcFile); WriteArray; { Сортировка массива по фамилиям (метод пузырьков) } k:=1; while k<>0 do begin k:=0; { признак перестановки сбрасывается } for i:=1 to n-1 do begin { перебор массива } { Сравнение соседних эл-тов } if CompName(a[i],a[i+1])>0 then begin { Если 1-й эл-т больше 2-го - перестановка } AssgnStud(b,a[i]); AssgnStud(a[i],a[i+1]); AssgnStud(a[i+1],b); k:=1; { признак перестановки взводится} end; end; end; { Вывод результатов } WriteLn('=== Отсортированный по фамилиям массив ==='); WriteArray; { Сортировка массива по оценкам. Отличается использованием функции CompMark вместо CompName } k:=1; while k<>0 do begin k:=0; for i:=1 to n-1 do begin if CompMark(a[i],a[i+1])>0 then begin AssgnStud(b,a[i]); AssgnStud(a[i],a[i+1]); AssgnStud(a[i+1],b); k:=1; end; end; end; WriteLn('=== Отсортированный по оценкам массив ==='); WriteArray; END.
|