Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Stud_2_1 / Kurs_Rab / Metuk.doc
Скачиваний:
20
Добавлен:
03.03.2016
Размер:
523.78 Кб
Скачать

6. П р и м е р в ы п о л н е н и я з а д а н и я

Условие задачи.

Имеются следующие сведения о деятельности цехов некоторого предприятия: номер цеха (2 цифры), код изделия (6 цифр), наименование изделия, единица измерения, цена изделия, план выпуска и фактический выпуск изделия по полугодиям. Необходимо создать архив сведений о выпускаемых изделиях и сгруппировать документы архива по возрастанию кода изделия. В программе должны быть предусмотрены следующие виды коррекции архива:

- добавление документов;

- удаление документа;

- изменение в заданном документе последних четырех реквизитов (единица измерения, цена, плановый и фактический выпуски).

В обрабатывающей части программы предусмотреть:

- печать архива;

- определение для заданного цеха процента выполнения плана в стоимостном выражении по полугодиям и в целом за год;

- формирование списка изделий, по которым не выполнен годовой план производства.

Реализация задачи приведена в описываемой ниже программе Kursrab.

О п и с а н и е п р о г р а м м ы K u r s r a b

Программа Kursrab состоит из пяти модулей:

- DesUnit - глобальные описания констант, типов и переменных;

- BasUnit - сервисные процедуры и функции;

- InpUnit - ввод и контроль корректности текстовых файлов;

- WorkUnit - обрабатывающие процедуры и функции;

- Kursrab - основная программа.

Строке документа, приведенного в условии задачи, в программе (модуль DesUnit) соответствует запись типа ProductType. Некоторых пояснений требует представление в данной записи двух реквизитов: номера цеха NumberShop и кода изделия KodProduct.

В условии указано, что номер цеха изображается двумя цифрами. С этой точки зрения данный параметр можно трактовать как число. Однако это число обладает специфической особенностью: оно не может быть использовано для арифметических операций. Бессмысленно, например, говорить о сумме двух номеров цехов или об их произведении. Номер цеха при обработке в программе может использоваться лишь в операциях сравнения (например, при группировке записей по возрастанию номера цеха). Поскольку арифметические операции для номера цеха NumberShop недопустимы, то переменную NumberShop можно было бы представить как строку типа string[2], элементами которой являются цифры. В программе для переменной NumberShop выбран тип byte в основном с точки зрения экономии памяти (тип byte требует один байт памяти вместо трех байтов для типа string[2]).

По аналогичным соображениям для переменной KodProduct принят тип longint (максимальное значение переменной KodProduct по условию задачи равно 999999; максимальное значение для типа byte равно 255, для типа integer - 32767, типа word - 65535, типа longint - 2 147 483 647). Если бы по условию задачи для кода изделия использовался буквенно-цифровой шифр или же цифровой код занимал более 9 цифр, то переменная KodProduct должна была бы иметь представление в виде строки.

Соответствие между кодом изделия и его наименованием отображено в кодификаторе изделий, запись которого имеет тип KodifType. Наличие такого кодификатора позволяет при наборе исходных данных не указывать в документе наименование изделия, что ускоряет подготовку данных и уменьшает количество возможных ошибок. Использование кодификатора, как уже отмечалось выше, позволяет также экономить память при хранении и обработке информации на ЭВМ.

Количество хранимых и обрабатываемых документов в АУС является переменной величиной. В процессе эксплуатации АУС типичными операциями являются добавление новых документов к имеющемуся архиву, удаление части документов, изменение содержания некоторых документов. Кодификаторы, в отличие от основных файлов АУС, изменяются очень редко; в связи с этим в программе не предусмотрены операции по корректировке кодификатора. Максимальный размер кодификатора определен константой MaxKodif, его реальный размер – переменной nk. Архивный массив реализуется в виде очереди записей, компоненты которой имеют тип PointerProduct.

В программе Kursrab используются 6 файлов. В текстовом файле FileInput содержатся исходные документы (сведения об изделиях), в файле FileKodif - кодификатор изделий. Текстовый файл FileAdd предназначен для документов, добавляемых в архив; строки этого файла имеют такой же вид, как и строки файла FileInput. Файл FileOut является типизированным, его компоненты имеют тип записей ProductType. В текстовый файл FileRes могут быть записаны по указанию пользователя результаты обработки архива. В файл FileError, объявленный локально в модуле InpUnit, производится запись протокола проверки корректности исходных данных.

Информация для текстовых файлов подготавливается вручную с клавиатуры ПЭВМ, что заранее предполагает наличие в ней различного рода ошибок. Содержимое текстового файла легко изменить с помощью любого текстового редактора, что создает опасность внесения в исходную информацию умышленных или неумышленных искажений. Поэтому использоватъ текстовые файлы как непосредственный источник обрабатываемых данных в АУС нецелесообразно.

В реальных системах исходные документы, содержащиеся в текстовых файлах, тщательно контролируются в программе с целью обнаружения возможных ошибок. После исправления обнаруженных ошибок содержимое текстового файла выдается на печать для визуального контроля; тщательно проверенные документы программно переписываются в типизированные файлы, представляющие собой архив системы.

С точки зрения машинной обработки типизированные файлы имеют ряд преимуществ по сравнению с текстовыми файлами:

- возможность прямого доступа;

- более экономное размещение данных в памяти;

- более быстрое выполнение операций ввода-вывода.

В текстовом файле информация имеет литерное представление (каждый символ текста или цифра числа занимают отдельный байт). В типизированном файле представление информации не отличается от внутримашинного. Поэтому при обращении к текстовому файлу затрачивается значительное машинное время на преобразование информации из внешнего представления во внутреннее (или наоборот).

В программе Kursrab для хранения архива предусмотрен файл FileOut. При переписи информации из файла FileInput в файл FileOut предварительно производится контроль корректности исходных данных. Контролю подвергается также содержимое текстовых файлов FileKodif и FileAdd. Результаты обработки архива выдаются на экран, а также по указанию пользователя могут печататься на принтере и записываться в выходной текстовый файл FileRes.

В программе Kursrab предусмотрены следующие режимы работы:

- контроль текстовых файлов;

- создание архива изделий;

- сортировка компонентов архива;

- печать архива изделий;

- печать кодификатора изделий;

- добавление компонентов в архив;

- удаление компонента из архива;

- изменение компонента в архиве;

- обработка архива.

Выбор режимов работы реализован в основной части программы. Вначале на экран выдается запрос о режиме; после ввода с клавиатуры ответа (0..9) оператор Case выполняет обращение к процедуре, определяющей соответствующий режим.

При вводе числового ответа с клавиатуры существует определенная вероятность ошибочного набора (например, буква вместо цифры). При вводе ответа с помощью оператора Read это вызвало бы прерывание программы и, как следствие, необходимость ее повторного запуска.

Чтобы блокировать такое прерывание, ввод переменной KeyRegime производится с помощью процедуры GetNumber, выполняющей контроль формата вводимого числа и допустимого диапазона его представления.

При ошибке ввода программа выдает соответствующее сообщение и предлагает пользователю повторить ввод.

Запрос режима работы повторяется оператором Repeat до тех пор, пока не будет получен ответ KeyRegime=0. Это дает возможность пользователю любое количество раз и в любом порядке задавать необходимые режимы работы программы.

Рассмотрим теперь отдельно каждый из режимов работы.

1. Контроль текстовых файлов (процедура CheckFiles).

В рассматриваемой задаче используются три текстовых файла: FileInput, FileAdd и FileKodif. Структура записей первых двух файлов одинакова, их проверка осуществляется одними и теми же процедурами. Для контроля параметров третьего файла применяются отдельные процедуры.

Для сообщений об ошибках используется типизированный файл FileError, в который последовательно заносится информация об обнаруженных ошибках. Индикатором наличия ошибок является булевская переменная FatalError. Если FatalError = true, то в качестве последней строки в файл FileError заносится фраза "Скорректируйте исходные файлы", в противном сдучае - фраза "В исходных файлах ошибок не обнаружено". В сообщениях об ошибках указывается имя проверяемого файла, тип ошибки и номер строки, содержащей ошибку. Чтение содержимого файла FileError производит процедура ReadFileError; при этом предварительно осуществляется сохранение экрана, а затем его восстановление (процедуры MoveFromScreen и MoveToScreen модуля BasUnit). В конечной стадии работы режима контроля файл FileError уничтожается.

Ошибки в текстовых файлах разделены на три группы:

- ошибки формата;

- ошибки диапазона;

- содержательные ошибки.

О ш и б к и ф о р м а т а.

Проверка осуществляется процедурами FormatFileProduct и FormatFileKodif.

В исходном текстовом файле могут быть пустые строки или строки, содержащие только пробелы. Наличие таких строк нецелесообразно относить к критическим ошибкам, поскольку эти строки легко устранить программным путем. Для этого содержимое текстового файла вводится в динамический массив строк Sf, из этого массива удаляются строки, не содержащие значащих символов, после чего массив Sf записывается в тот же текстовый файл. Эта работа выполняется процедурой ReadAndCheckSpaces, обращение к которой производится при старте процедур FormatFileProduct и FormatFileKodif.

В процедуре ReadAndCheckSpaces вначале проверяется наличие текстового файла. Отсутствие файла, естественно, блокирует дальнейшую работу по его проверке.

Если текстовый файл имеется, то выполняется чтение его строк в массив Sf. При этом проверяется, не является ли файл пустым (количество строк nf = 0), а также, не превышает ли его размер максимально допустимый (nf > Nmax). В том и другом случае дальнейшая проверка файла не производится.

После успешного завершения работы процедуры ReadAndCheckSpaces выполняется непосредственная проверка форматов параметров. В процедуре FormatFileProduct проверяется:

- количество параметров в строке файла (меньше или больше 8);

- длина строки текстового параметра;

- корректность форматов числовых параметров (возможные ошибки: буква вместо цифры, точка в целочисленном параметре и др.).

Процедура FormatFileKodif работает аналогично, но с учетом структуры записи кодификатора.

При отсутствии форматных ошибок будут сформированы динамические массивы Products^ и AddProducts^, а также статический массив KodifProducts.

Если обнаружена хотя бы одна ошибка формата, дальнейший контроль текстовых файлов не производится.

О ш и б к и д и а п а з о н а.

Проверку допустимых диапазонов числовых параметров осуществляют процедуры CheckProdDiapason и CheckKodifDiapason. Здесь в цикле просматриваются массивы Products^, AddProducts^ и KodifProducts. Если какой-либо числовой параметр меньше заданного минимального значения или больше заданного максимального значения, то формируется сообщение об ошибке.

Если обнаружена хотя бы одна ошибка диапазона, дальнейший контроль текстовых файлов не производится.

С о д е р ж а т е л ь н ы е о ш и б к и.

Проверка этого типа ошибок производится процедурами ProdParameters (массивы Products^ и AddProducts^) и KodifParameters (массив KodifProducts). В первой из них проверяется:

- имеет ли место дублирование кода изделия KodProduct;

- задано ли значение кода KodProduct в кодификаторе;

- соответствует ли единица размерности списку допустимых значений.

В процедуре KodifParameters проверяется лишь дублирование кода изделия в кодификаторе.

2. Создание архива изделий (процедура CreatArchive).

В процедуре CreateArchive производится чтение строк файла FileInput, формирование записи Product (с помощью процедуры ReadProduct) и передача этой записи в типизированный файл FileOut. Здесь следует обратить внимание на то, что из текстового файла читается отдельно каждый компонент записи Product, а в типизированный файл передается целиком вся эта запись.

3. Сортировка компонентов архива (процедура SortArchive);

В начале работы процедуры SortArchive производится формирование очереди при чтении файла FileOut в процедуре CreateDynProduct. Для группировки компонент по возрастанию реквизита KodProduct применяется метод прямой выборки. Однако в отличие от группировки массива вместо индекса максимального элемента при просмотре очереди запоминается указатель такого элемента Pmax.

4. Печать архива изделий (процедура PrintArchive).

Работа процедуры PrintArchive вполне очевидна из ее текста. Некоторые замечания следует высказать лишь по поводу использования процедуры Str.

Предположим,что нам требуется выдать на экран и на принтер (при IndPrinter = true) значения вещественных переменных x и y в формате 8:2. Тогда можно написатъ

Writeln('x=',x:8:2,' y=',y:8:2);

If IndPrinter then

Writeln(Lst,'x=',x:8:2,' y=',y:8:2);

Процедура Writeln всегда преобразует численные значения в строковые (одна цифра - один байт), после чего передает общую строку на выходное устройство. В данном примере переменные x и y будут дважды преобразованы из числовых в строковые значения – для передачи на экран и на принтер. В процедуре PrintArchive используется более эффективная методика. Здесь преобразование с помощью процедуры Str выполняется лишь один раз, после чего суммарная строка процедурой WritelnString (модуль BasUnit) передается на соответствующее выходное устройство.

Выбор устройства вывода производится по запросу программы при ее старте (процедура UsesDevice, вызываемая в начальной стадии работы основной программы). При этом предусмотрены три альтернативы вывода:

- только экран;

- экран и магнитный диск;

- экран и принтер.

5. Печать кодификатора изделий (процедура PrintKodif).

В данном режиме производится чтение текстового файла FileKodif, формирование записи KodifProduct и выдача ее на экран и на принтер.

6. Добавление компонентов в архив (процедура AddArchive).

На завершающем этапе работы процедуры SortArchive элементы очереди, сгруппированные по возрастанию реквизита KodProduct, переписываются процедурой WriteFileProduct в типизированный файл FileOut и, естественно, сохраняют в этом файле упорядоченность по возрастанию. При старте процедуры AddArchive компоненты файла FileOut переписываются в архивную очередь процедурой CreateDynProduct.

В процессе работы процедуры AddArchive последовательно читаются записи из файла FileAdd. Включение этих записей в очередь производится внутренней процедурой Addition.

В начальной части процедуры Addition для локального указателя PAdd выделяется поле памяти процедурой New. В информационную часть этого поля памяти заносится добавляемая запись Product. Если код изделия добавляемой записи (Product.Kod) меньше кода изделия первой компоненты очереди (Lp^.Inf.KodProduct), то поле, адресуемое указателем PAdd, вставляется в начало очереди; в противном случае производится просмотр в цикле оставшихся компонентов очереди. Если Product.Kod больше кода изделия последнего компонента очереди (Rp^.Inf.KodProduct), то новая запись добавляется к концу очереди; при этом соответственно переносится правый указатель Rp. В противном случае в цикле While просматриваются все элементы очереди, начиная со второго, до обнаружения элемента, код которого больше значения Product.Kod.

7. Удаление компонента из архива (процедура DeleteArchive).

В процедуре DeleteArchive производится последовательный просмотр компонентов очереди. Если при этом будет обнаружено, что реквизит KodProduct очередного компонента очереди равен значению Kod, заданному с клавиатуры ПЭВМ, этот компонент процедурой Dispose удаляется из памяти, а указатель предыдущего компонента Run^.Next принимает значение адреса Run^.Next^.Next компонента, следующего после исключаемого. При этом учтены случаи, когда удалению подлежит первый или последний элементы очереди, что связано с изменением значений левого Lp или правого Rp указателей.

8. Изменение компонента в архиве (процедура ChangeArchive).

Если при последовательном просмотре компонентов очереди обнаружится, что реквизит KodProduct очередного компонента равен введенному значению Kod, то заменяемым реквизитам данного компонента присваиваются значения, вводимые с клавиатуры.

9. Обработка архива (процедура WorkUpArchive).

В данном режиме дважды просматривается архивная очередь изделий. В первом случае по заданному пользователем номеру цеха Shop выбираются из очереди соответствующие компоненты и суммируются плановые и фактические показатели. В результате первого просмотра печатается таблица сведений о выполнении плана по цеху Shop. Во втором просмотре в таблицу выдается список изделий, по которым не выполнен годовой план производства. Наименование изделия выбирается из кодификатора (массив KodifProducts), для поиска компонента в массиве KodifProducts применяется метод двоичного поиска (процедура SearchKodif).

10. Ввод реквизита с клавиатуры.

В режимах удаления и изменения компонента пользователь по запросу программы вводит с клавиатуры реквизит, по которому должен осуществляться поиск соответствующей записи в архивной очереди.

Реквизиты могут быть числовые и строчные. Ввод числового реквизита производится процедурами Read и Readln обычным образом. Примером может служить ввод кода изделия в процедурах DeleteArchive и ChangeArchive.

Некоторую особенность имеет ввод текстового реквизита (или в общем случае строки). Здесь его выполнение зависит от того, была ли непосредственно перед этим вводом использована процедура Read или процедура Readln.

Процедура Read очищает буфер ввода от введенной переменной, но не переводит указатель буфера на его начало. Процедура Readln полностью очищает буфер ввода и переводит его указатель на начало буфера.

Пусть мы имеем:

Var k : integer;

S : string;

..............

Read(k);

Readln(S);

Поскольку после срабатывания процедуры Read указатель буфера ввода находился не в его начале, то строка S получит пустое значение вне зависимости от того, что было набрано на клавиатуре. Такая ситуация могла бы возникнуть в программе Kursrab при выполнении процедуры ChangeArchive, если бы в процедуре GetNumber было записано Read вместо Readln.

В связи с вышесказанным рекомендуется при вводе строк всегда использовать процедуру Readln. Если же с помощью процедуры Read вводится одна или несколько числовых переменных, то после такого ввода записывать процедуру Readln без параметров.

11. Использование переменной SignArchive.

В программе Kursrab предусмотрено 9 режимов работы, выбор которых осуществляет переменная KeyRegime. Конечно, пользователь может активизировать их в любом порядке, тем не менее режимы 3..9 могут выполняться лишь после создания архива изделий. Это обстоятельство учитывается переменной SignArchive, которая принимает значение true лишь при создании архивного файла. Если SignArchive = false, то активизация других режимов блокируется с выдачей на экран соответствующего сообщения.

12. Использование процедуры FillString.

Предположим, что в текстовом массиве есть строка

St[i] = ‘abcdefgh’;

По запросу программы пользователем было указано найти индекс этой строки в массиве. При этом было введено для сравнения значение

S = ‘abcdefgh ‘ (3 пробела после символа “h”).

При сравнении двух строк неодинаковой длины более короткая дополняется символами #0. Так как символ пробела имеет номер #32, то программа будет считать, что строки St[i] и S неодинаковы, а это приводит к ошибкам в работе программы.

Чтобы этого не случилось, с помощью процедуры FillString каждая из введенных строк дополняется пробелами до объявленной длины.

Соседние файлы в папке Kurs_Rab