Текст программы (с комментариями)

Эта строка обозначает просто название программы. Это название BD_Book. В принципе эту строку можно убрать, она необязательная.

program BD_Book;

uses Crt, Graph; {подключаем модули для работы с текстом и графикой.

В модуле Crt содержатся процедуры для работы с экраном в текстовом режиме (это режим с разрешением 80 на 25). Работа с экраном – это например вывод строк или чисел на экран, установка разных цветов символов.

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

}

В программе есть база данных с информацией о книгах. Т. е. это произвольное количество книг, которые нужно каким-то образом разместить в памяти. В принципе, мы могли бы создать массив и хранить в каждом элементе массива информацию об одной книге. А уж перемещаться по массиву паскаль позволяет легко и без проблем. Т. е. в массиве нам не нужно было бы каким-то образом настраивать связи между соседними книгами. Т. е паскаль позволил бы нам легко перемещаться от одной книги к другой, не задумываясь о том как паскаль это делает. Но проблема в том, что в паскале массив может иметь размер не более чем 64000 байт. А если у нас очень много книг, как же мы запишем всю информацию в массив? Никак. К тому же вдруг у нас очень мало книг, зачем мы будем создавать огромный массив, который съест у нас кучу памяти (т. е. память для массива можно выделить только 1 раз в начале выполнения программы и потом ее нельзя уменьшить или увеличить). И еще: мАссивы размещаются в статической памяти, которая как раз и имеет максимальный размер 64000 байт. Выход есть: можно хранить книги в динамической памяти, которая имеет гораздо больший размер. И к тому же мы не будем занимать в динамической памяти место сразу для огромного количества книг, можно выделять память отдельно для каждой книги по мере необходимости. Мы будем хранить книги в списке, который сначала будет пустым, а потом по мере необходимости мы будем выделять в динамической памяти место для одной книги и добавлять эту книгу в список. Т. е. мы будем брать из динамической памяти ровно столько места, сколько нам необходимо. И мы будем читать из файла информацию о книгах по одной, выделять память для нее и привязывать эту книгу в список. И если нам нужно какую-то книгу выбросить из списка, то мы сначала освободим память, которую эта книга занимала, а потом удалим эту книгу из списка.

НЕ нашли? Не то? Что вы ищете?

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

Type

Информация о книге включает в себя 4 поля: название книги, автор книги, количество страниц в книге, стоимость книги. Если в инфомации не одно поле, а больше, то в паскале создается запись record для хранения всех полей. Все эти 4 поля первой книги будут храниться в нарисованном на схеме прямоугольнике “Информация о первой книге”. Запись для хранения информации о книге называется в этой программе Book.

Book = record {структура для представления записи БД}

Name: string; {название книги. строка}

Author: string; {автор книги. строка}

Page: integer;{количество страниц в книге. Целое число}

Price: real; {стоимость книги. Вещественное число}

end;

Далее идет указатель на элемент списка. На схеме нарисованы такие указатели. Указатель – это просто адрес следующего элемента списка в динамической памяти. А адрес – это какое-то число. Элемент списка называется Rec. Это на схеме 2 сцепленных прямоугольника (один сверху, другой снизу).

List = ^Rec; {структура "Список" для хранения записей}

Rec = record

Data: Book; {информация о книге, т. е. верхний прямоугольник элемента списка}

Next: List; {указатель на следующий элемент, т. е. нижний прямоугольник элемента списка. занимает 2 байта в памяти }

end;

var menu: integer; {номер выбранного пункта меню. В программе есть меню, в котором 7 элементов}

YesBD: boolean; {обозначает, имеется ли БД для работы. Т. е загрузили ли мы БД(базу данных) из файла. Если загрузили, то эта логическая переменная YesBD равна true, иначе - false}

BD: List; { это указатель на первую книгу. Самый главный указатель. На схеме нарисован}

procedure DelBD; {процедура уничтожения базы данных. Эта процедура должна удалить всю базу данных из памяти, т. е все книги. Но на самом деле в этой процедуре удаляется из памяти только первая книга. и указатель на первую книгу станет пустым, т. е nil. Это конечно не совсем верно сделано. Надо, чтобы программа пробежалась по всему списку и удалила из памяти все его элементы, т. е все книги}

begin

Dispose(BD); {процедура. удаляет из памяти первый элемент списка. BD – указатель на первый элемент списка}

YesBD:=false; {присваивание. После него знаем, что списка для работы нет. Об этой переменной можно прочитать выше}

GotoXY(4,7); процедура. передвигает курсор в позицию с координатами (4,7) 4 – по горизонтали, 7 – по вертикали.

TextColor(10); Процедура. устанавливает цвет символов 10 (светло-зеленый). Цветов всего 16. От 0 до 15

Write('БД удалена!'); Процедура. Выводит на экран сообщение “БД удалена!”

end;

procedure NewBD; {процедура. Делает подготовку к вводу новой базы данных. вызывает предыдущую процедуру удаления списка из памяти, если список есть}

begin

if YesBD then DelBD; {если база данных уже была введена, то вызываем процедуру DelBD для удаления базы}

BD:=nil; {указатель на первую книгу делаем пустым, т. е теперь нет базы данных}

end;

procedure NewEl(t: Book); {процедура добавления нового элемента в список. Процедура получает в качестве параметра переменную t, которая, содержит информацию о книге, т. е 4 поля. И эту информацию процедура теперь прицепит в конец списка}

var x: List; {указатель на элемент списка. необходим для выделения динамической памяти для нового элемента списка}

S: List; { указатель на элемент списка. необходим перемещения по списку от начала к концу. Т. е. для поиска конца списка}

begin

if BD=nil then {сравнение. если добавляется первый элемент в список, т. е если список пустой, то идем выполнять то, что написано ниже}

begin

new(x); {процедура. выделяет динамическую память под новый элемент списка. Переменная x имеет тип List, т. е. тип элемента списка. а значит в памяти выделяется место для информации о 4-х полях информации о книге и + место для указателя на следующую книгу}

x^.Data:=t; {присваивание. В поле Data указателя x копируется значение указателя t, который описан выше. Т. е. копируется указатель на информацию о книге. Пр указатели подробно можно прочитать в процедуре ViewDB}

x^.Next:=nil; {присваивание. В поле Next указателя x записывается nil (пусто), т. е. следующего элемента у вставляемого элемента пока нет}

BD:=x; {присваивание. В указатель на БД заносится адрес нового элемента списка. первого}

End

Вот что получится:

else {иначе, если добавление не первого элемента в список, то будем добавлять новый элемент в конец списка}

begin

S:=BD; {присваивание. Указатель s будет указывать на начало списка. }

while S^.Next<>nil do {цикл для перемещения в конец списка по указателям. Т. е. цикл пока адрес следующего элемента не пустой. Хотя если делать правильно, то должен быть указатель не только на начало списка, но и второй указатель на последний элемент списка, чтобы не нужно было каждый раз искать конец списка, начиная с его начала}

S:=S^.Next; присваивание. перемещаемся на следующий элемент списка, т. е. из текущего элемента списка берем адрес следующего элемента

new(x); {процедура. создает новой элемент в динамической памяти и присваивает указатель на него в переменную x}

x^.Data:=t; {присваивание. См. чуть выше в этой же процедуре}

x^.Next:=nil; {присваивание. См. чуть выше в этой же процедуре }

S^.Next:=x; {присваивание. добавление нового элемента в конец списка, т. е. присваиваем указатель на новый элемент в последний элемент списка}

end;

Вот что получится:

end;

procedure GraphInit; {процедура перехода в графический режим, чтобы нарисовать заставку в начале выполнения программы}

var

ErrorCode: Integer; это код ошибки, если не получится перейти в граф. режим

GrDriver, GrMode: Integer; GrDriver - номер графического драйвера и GrMode - номер графического режима

begin

GrDriver := Detect; присваивание. Присваиваем графическому драйверу значение Detect, т. е. автоопределение паскалем, т. е. мы не хотим сами выбирать какой-то конкретный графический драйвер пусть паскаль сам определит графический драйвер.

InitGraph(GrDriver, GrMode, ''); процедура. Переводит экран в графический режим. Параметр GrDriver описали уже, переменной GrMode вообще никакое значение не присвоили. Паскаль сам присвоит. А третий параметр '' – это строка - путь к файлу графического драйвера. Ставим пустую строку: паскаль сам найдет файл графического драйвера.

ErrorCode := GraphResult; {вызываем процедуру GraphResult, которая возвращает число - результат перехода в графический режим и это число присваиваем в переменную ErrorCode }

if ErrorCode <> grOk then { сравнение. grOk – это число, которое означает, что переход в графический режим был успешным. И если результат перехода в графический режим ErrorCode не равен этому числу grOk, то значит возникла ошибка при переходе в граф. режим }

begin

Writeln('Ошибка графики:'); процедура. выводит сообщение об ошибке

Writeln(GraphErrorMsg(ErrorCode));процедура. Выводит паскалевское сообщение об ошибке. Т. е. вызывается функция GraphErrorMsg, которая принимает код ошибки в параметре ErrorCode и возвращает строку – текст сообщения об ошибке. Это сообщение будет на английском языке.

Writeln('Невозможно показать красивую заставку :-('); процедура выводит на экран строку 'Невозможно показать красивую заставку :-('

ReadKey;процедура. ждет нажатия любой клавиши

end;

end;

procedure Zastavka; {процедура для вывода заставки на экран в графическом режиме}

var i: integer; переменная. Предназначена для вывода прямоугольных рамок, вернее для хранения номера текущей рисуемой рамки. От 0 до 15

begin

GraphInit; {вызываем процедуру GraphInit. Для инициализации графики. Это написанная нами процедура. Находится чуть выше

SetBkColor(1); {процедура. устанавливает цвет фона. 1 - синий}

ClearDevice; {процедура. очищает экран и закрашивает его цветом фона символов, т.е. в данном случае синим цветом}

for i:=0 to 15 do {цикл для рисования рамок из прямоугольников. Переменная I описана выше. Принимает значения от 0 до 15}

begin

SetColor(i); процедура. устанавливает цвет с номером I для рисования (т. е. рамка с номером 1 будет рисоваться цветом 1. рамка с номером 2 будет рисоваться цветом 2. И т. д.)

Rectangle(0+i*2, 0+i*2, GetMaxX-i*2, GetMaxY-i*2); процедура. рисует прямоугольник (т. е. рамку). Принимает 4 параметра. 0+i*2 – координата x левого верхнего угла рамки, 0+i*2 - координата y левого верхнего угла рамки,

GetMaxX-i*2 - координата x правого нижнего угла рамки,

GetMaxY-i*2 - координата y правого нижнего угла рамки,

GetMaxX – это функция. возвращает максимальный размер экрана по горизонтали. Это обычно число 640.

GetMaxY – это функция. возвращает максимальный размер экрана по вертикали. Это обычно число 480.

Каждая последующая рамка становится меньше по размеру.

end;

SetColor(4); процедура. устанавливает цвет с номером 4 для рисования. 4 - красный

SetTextStyle(DefaultFont, HorizDir, 3); процедура. устанвливает стиль выводимого текста. Принимает параметры:

DefaultFont – константа для выбора шрифта по умолчанию, HorizDir – горизонтальный вывод текста.

3 – это размер шрифта.

OutTextXY(200, 130, 'БД КНИГИ'); процедура. Выводит строку 'БД КНИГИ' в место с координатами x = 200 ,y = 130

SetColor(14); процедура. устанавливает цвет с номером 14 для рисования. Я не помню какой это цвет. Да их и не нужно помнить наизусть.

OutTextXY(110, 230, 'Выполнил ПУПКИН'); процедура. Выводит строку 'Выполнил ПУПКИН' в место с координатами x = 110 ,y = 230

SetColor(13); процедура. устанавливает цвет с номером 13 для рисования.

SetTextStyle(DefaultFont, HorizDir, 2); процедура. устанвливает стиль выводимого текста. Принимает параметры:

DefaultFont – константа для выбора шрифта по умолчанию, HorizDir – горизонтальный вывод текста.

2 – это размер шрифта.

OutTextXY(80, 330, 'студент группы №07'); процедура. Выводит строку 'студент группы №07' в место с координатами x = 80 ,y = 330

SetColor(2); процедура. устанавливает цвет с номером 2 для рисования.

SetTextStyle(DefaultFont, HorizDir, 1); процедура. устанвливает стиль выводимого текста. Принимает параметры:

DefaultFont – константа для выбора шрифта по умолчанию, HorizDir – горизонтальный вывод текста.

1 – это размер шрифта.

OutTextXY(250, GetMaxY-50, 'Нажмите любую клавишу'); процедура. Выводит строку 'Нажмите любую клавишу' в место с координатами x = 250 ,y = GetMaxY-50. GetMaxY – это функция. возвращает максимальный размер экрана по вертикали. Это обычно число 480.

ReadKey;процедура. ждет нажатия любой клавиши

CloseGraph; {процедура. закрывает графический режим}

end;

procedure LoadBD; {процедура Чтения БД из файла}

var FileName: string; {переменная. строка - имя файла, из которого будем читать БД}

F: file of Book; {файловая переменная. Предназначена для ввода из файла структур, т. е это типизированный файл, в котором записана информация только о книгах, в которой обязательно 4 поля. Если вдруг в файле информация в другом виде, то мы ее прочитать таким способом не сможем. Т. е. кто-то заранее подготовил этот типизированный файл с информацией О книгах в нужном нам формате путем тоже программного его формирования и мы теперь будем из этого файла информацию читать}

tmp: Book;вспомогательная переменная для чтения в нее информации об одной книге

begin

ClrScr;процедура. очищает экран

NewBD; {процедура. Вызываем ее для создания нового списка для хранения БД. Это написанная нами процедура}

TextColor(14); процедура. Устанавливает цвет символов. 14 – желтый цвет

GotoXY(4,2);процедура. Перемещает курсор в позицию с координатами 4 по горизонтали и 2 по вертикали

Процедура. Выводит сообщение 'Задайте имя файла: '

Write('Задайте имя файла: ');

Процедура. Заносит имя файла в переменную FileName, которое вводит пользователь.

ReadLn(FileName);

Продедура. Связывает нашу файловую переменную F с конкретным файлом, имя которого FileName только что ввели. Потом с помощью этой файловой переменной сможем читать инфор. Из файла

Assign(F, FileName);

{$I-} {директива. отключить проверку ошибок. Если не отключим, то паскаль, если не сможет открыть файл, выдаст нам ошибку и завершит выполнение программы}

Reset(F); {процедура. открывает файл c файловой переменной F для чтения}

{$I+} {директива. включить проверку ошибок снова. Т. е. только временно отключали}

if IOResult <> 0 then {если была ошибка при открытии файла. Если результат открытия неудачный. IOResult – функция, которая возращает результат открытия файла. Если открытие было удачным, то вернет число 0}

begin

TextColor(12); процедура. Устанавливает цвет символов. 12 – светло-красный цвет

WriteLn('Указанный Вами файл не найден!!!');процедура. Выводи строку 'Указанный Вами файл не найден!!!' на экран

WriteLn('Создан новый файл и создана пустая БД');прцедура. Выводит еще одну строку на экран

Rewrite(F); {процедура. перезаписывает файл, который связан с файловой переменной F. Т. е открываем файл для перезаписи. Тот же самый. В принципе никакого смысла в этом я не вижу. Просто создается пустой файл в папке программы и больше ничего}

end

else {если файл был найден, то выполняем дальнейшие действия}

begin

while not eof(F) do {цикл пока не конец файла. Функция eof возвращает True, если при чтении дошли до конца файла F или False, если не дошли}

begin

Read(F, tmp); {процедура. читает из файла F запись в переменную tmp, т. е. все 4 поля информации о книге}

NewEl(tmp); {вызываем написанную нами процедуру для добавления записи tmp в список}

end;

TextColor(10); процедура. Устанавливает цвет символов. 10 – светло-зеленый цвет

GotoXY(4,7); процедура. Перемещает курсор в позицию с координатами 4 по горизонтали и 7 по вертикали

WriteLn('БД успешно прочитана'); процедура. Выводи строку 'БД успешно прочитана' на экран

end;

YesBD:=true; {присваивание в логическую переменную значения True. Т. е. БД имеется, загружена}

Close(F); {процедура. закрывает файл F}

end;

procedure ViewBD; {процедура вывода БД на экран, т. е. просмотра БД}

var S: List; указатель на текущий элемент списка, т. е. на текущую книгу. Сначала установим этот указатель на первый элемент списка, потом на второй, и т. д. до конца списка. Используется для прохода по всему списку, чтобы вывести всю информацию на экран.

i: integer; переменная - номер элемента списка. принимает значения 1, 2 и т. д. используется для вывода на экран номера каждой книги по порядку.

begin

TextBackground(7); процедура. устанавливает цвет фона символов 7 – светло-серый.

ClrScr; процедура. очищает весь экран и закрашивает его текущим цветом фона символов 7.

Window(4,3,78,21); процедура. рисует окно на экране с координатами 4,3,78,21. По горизонтали с позиции 4 до позиции 78. По вертикали с позиции 3 до позиции 21.

TextBackGround(0); процедура. устанавливает цвет фона символов 0 – черный.

ClrScr; процедура. Очищает в данном случае не весь экран, а только окно, созданное последним, т. е.с координатами 4,3,78,21 и закрашивает его текущим цветом фона символов 0.

Window(3,2,77,20); процедура. рисует окно на экране. Про параметры см. выше.

TextBackground(1); процедура. устанавливает цвет фона символов 1 – синий.

ClrScr; процедура. Очищает в данном случае не весь экран, а только окно, созданное последним, т. е.с координатами 3,2,77,20 и закрашивает его текущим цветом фона символов 1.

Чтобы понять, зачем мы рисовали все эти окна, надо посмотреть на скриншот. Сначала закрасили весь экран светло-серым цветом (видим его вне окна), потом нарисовали большое черное окно (при этом светло-серый цвет остался только вне окна), потом нарисовали синее окно (и от черного окна остались только 2 полоски снизу и справа синего окна. Таким образом, черное окно рисовали только для того, чтобы потом из него получилась тень для синего окна. Ну типа для солидности)

{процедура WriteLn. Выводит указанную в качестве параметра строку и переходит на следующую строку экрана. Используем здесь для рисования шапки таблицы}

WriteLn(' +----+---+-+------++');

WriteLn(' |№п\п| Название | Автор | Стр. | Цена |');

WriteLn(' +----+---+-+------++');

S:=BD; описание указателя s см. выше. Устанвливаем указатель s на начало БД, т. е. на первый элемент списка

i:=1; описание переменной i см. выше. Присваиваем ей номер 1 – первая запись.

while S<>nil do {цикл пока s не равно nil, т. е. пока не дошли до последнего элемента списка. на схеме я рисовал}

begin

Теперь нужно получить доступ ко 4-м полям книги. Чтобы получить название книги надо записать так: S^.Data. Name, где s – это указатель на текущую книгу.

^. - это операция разыменования указателя. Объясню сейчас. Указатель содержит адрес какой-то переменной или структуры, и чтобы получить значение этой переменной или структуры (в нашем случае структура Data), надо записать так: S^.Data, т. е. мы получаем доступ ко всей информации о книге, а чтобы потом получить название книги дополняем S^.Data. Name, т. е. чтобы из структуры Data получить название книги, нужно написать. Name, т. е. поставить после названия структуры точку и написать название поля, в котором содержится название книги).

:23 означает, что мы выделяем названию книги на экране 23 позиции, и название книги будет прижиматься к правому краю этих 23-х позиций (т. е. если название книги занимает допустим 15 позиций, то на экран будет выведено 8 пробелов и потом название книги на 15-ти позициях). То же самое относится и ко всем остальным выделениям количества позиций :3, :21, :4. Но цена представляет собой вещественное число (т. е. рубли и в дробной части копейки), поэтому для ее вывода используется формат :7:2. Это значит, что для всего числа мы выделяем на экране 7 позиций и из них 2 позиции для дробной части.

WriteLn(' |',i:3,' | ',S^.Data. Name:23,' | ',S^.Data. Author:21,' | ',S^.Data. Page:4,' | ',S^.Data. Price:7:2,' |');

S:=S^.Next; {переход на следующую запись, т. е на следующий элемент списка, т. е. из текущего элемента списка берем адрес следующего элемента списка и записываем его в s}

inc(i); {увеличиваем номер текущего элемента списка}

end;

Процедура. Выводит строку, завершающую таблицу.

WriteLn(' +----+---+-+------++');

TextColor(10); процедура. Устанавливает цвет символов. 10 – светло-зеленый цвет

Write(' Нажмите любую клавишу'); процедура. Выводит строку на экран

ReadKey;процедура. ждет нажатия любой клавиши

TextBackground(7); процедура. устанавливает цвет фона символов 7 – светло-серый.

ClrScr; процедура. очищает весь экран и закрашивает его текущим цветом фона символов 7.

Window(32,3,78,21); процедура. рисует окно на экране. Про параметры см. выше в этой же процедуре.

TextBackground(0); процедура. устанавливает цвет фона символов 0 – черный.

ClrScr; процедура. Очищает в данном случае не весь экран, а только окно, созданное последним, т. е.с координатами 32,3,78,21 и закрашивает его текущим цветом фона символов 0.

Т. е. это все нужно только для рисования тени, как и выше в этой же процедуре.

Window(31,2,77,20); процедура. рисует окно на экране. Про параметры см. выше.

TextBackground(1); процедура. устанавливает цвет фона символов 1 – синий.

ClrScr; процедура. Очищает в данном случае не весь экран, а только окно, созданное последним, т. е.с координатами 31,2,77,20 и закрашивает его текущим цветом фона символов 1.

end;

procedure AddRec; {процедура. добавляет новую запись в БД}

var tmp: Book;вспомог. Переменная tmp для размещения в ней всех 4-х полей новой книги

begin

TextColor(12); процедура. Устанавливает цвет символов. 12 – светло-красный цвет

GotoXY(4,4); процедура. Перемещает курсор в позицию с координатами 4 по горизонтали и 4 по вертикали

WriteLn('Введите данные о книге:');процедура. Выводит строку на экран

WriteLn;процедура. Переводит курсор на новую строку на экране

TextColor(14); процедура. Устанавливает цвет символов. 14 – желтый цвет

Далее запрашиваем у пользователя ввод всех 4-х полей информ. О книге.

Write(' Название: '); процедура. Выводит строку на экран

ReadLn(tmp. Name);процедура. вводит название книги в поле Name переменной tmp

Write(' Автор: '); процедура. Выводит строку на экран

ReadLn(tmp. Author); процедура. вводит автора в поле Author переменной tmp

Write(' Страниц: '); процедура. Выводит строку на экран

ReadLn(tmp. Page); процедура. вводит количество страниц в поле Page переменной tmp

Write(' Стоимость: '); процедура. Выводит строку на экран

ReadLn(tmp. Price); процедура. вводит цену в поле Price переменной tmp

NewEl(tmp); {вызываем написанную нами процедуру для добавления нового элемента tmp в список. }

TextColor(10); процедура. Устанавливает цвет символов. 10 – светло-зеленый цвет

WriteLn; процедура. Переводит курсор на новую строку на экране

WriteLn(' Новая запись добавлена!'); процедура. Выводит строку на экран

end;

procedure FindRec; {процедура. Выполняет поиск конкретной книги в списке}

var tmp: Book; вспомог. Переменная tmp для размещения в ней всех 4-х полей новой книги, если книгу нашли

S: List; указатель на текущий элемент списка, т. е. на текущую книгу. Сначала установим этот указатель на первый элемент списка, потом на второй, и т. д. до конца списка. Используется для прохода по всему списку

b1,b2,b3,b4: boolean; {логические переменные для определения успеха поиска по частям. По каждому из 4- полей инф. О книге.

b1 = True, если в текущей записи БД название книги совпадает с искомым;

b2 = True, если в текущей записи БД автор совпадает с искомым;

b3 = True, если в текущей записи БД количество страниц совпадает с искомым;

b4 = True, если в текущей записи БД цена совпадает с искомым;}

begin

TextColor(12); процедура. Устанавливает цвет символов. 10 – светло-красный цвет

GotoXY(4,2); процедура. Перемещает курсор в позицию с координатами 4 по горизонтали и 2 по вертикали

WriteLn('Введите данные для поиска:'); процедура. Выводит строку на экран

WriteLn('(если поле не участвует в поиске,'); процедура. Выводит строку на экран

WriteLn('(введите в него "0")'); процедура. Выводит строку на экран

WriteLn; процедура. Переводит курсор на новую строку на экране

TextColor(14); процедура. Устанавливает цвет символов. 14 – желтый цвет

Далее идут несколько строк, которые абсолютно одинаковы со строками из процедуры AddRec. Можно там почитать

Write(' Название: '); ReadLn(tmp. Name);вводим с экрана название книги для поиска

Write(' Автор: '); ReadLn(tmp. Author);вводим автора

Write(' Страниц: '); ReadLn(tmp. Page);вводим колич. страниц

Write(' Стоимость: '); ReadLn(tmp. Price);вводим цену

S:=BD; описание указателя s см. выше. Устанвливаем указатель s на начало БД, т. е. на первый элемент списка

while S<>nil do цикл пока не дошли до конца списка, т.е. пока адрес в s не пустой

begin

сравнение. если ввели 0 вместо названия книги (т. е. tmp. Name = ‘0’), то название не ищем, а сразу ставим b1:=true, т. е типа книга с любым названием подойдет

if tmp. Name='0' then b1:=true else

Далее сравнение tmp. Name=S^.Data. Name. Если введенное название tmp. Name равно названию из текущего элемента списка S^.Data. Name, то паскаль присвоит b1:=true, т. е книга с таким названием найдена, иначе паскаль присвоит b1:=False

b1:=(tmp. Name=S^.Data. Name);

дальше аналогичные операции с остальными 3-мя полями

if tmp. Author='0' then b2:=true else b2:=(tmp. Author=S^.Data. Author);

if tmp. Page=0 then b3:=true else b3:=(tmp. Page=S^.Data. Page);

if tmp. Price=0 then b4:=true else b4:=(tmp. Price=S^.Data. Price);

Далее сравнение. если все 4 переменные b1, b2, b3, b4 равны true, то книгу нашли и вызываем оператор break, чтобы выйти из цикла прохода по списку.

if b1 and b2 and b3 and b4 then break;

S:=S^.Next; присваивание. перемещаемся на следующий элемент списка, т. е. из текущего элемента списка берем адрес следующего элемента списка

end;

TextColor(10); процедура. Устанавливает цвет символов. 10 – светло-зеленый цвет

WriteLn; процедура. Переводит курсор на новую строку на экране

Сравнение. Если S не равно nil, т. е. если мы нашли подходящую книгу. А если не нашли, то S равно nil, т. к. дошли до последнего элемента списка, который ни на кого не указывает

if S<>nil then

begin

WriteLn(' Найденная запись:'); процедура. Выводит строку на экран

WriteLn(' Название: ',S^.Data. Name); процедура. Выводит строку ' Название: ' и название книги S^.Data. Name

WriteLn(' Автор: ',S^.Data. Author); процедура. Выводит строку ' Автор: ' и автора S^.Data. Author

WriteLn(' Страниц: ',S^.Data. Page); процедура. Выводит строку ' Страниц: ' и количество страниц S^.Data. Page

WriteLn(' Стоимость: ',S^.Data. Price); процедура. Выводит строку ' Стоимость: ' и цену S^.Data. Price

end

else

WriteLn(' Запись на найдена!!!'); процедура. Выводит строку на экран

end;

procedure BDInFile; {процедура сохранения БД в файле}

var FileName: string; {переменная. имя файла}

F: file of Book; {файловая переменная. типизированный файл из структур. Т. е мы будем все элементы списка записывать в файл, в котором будут храниться только с информацией о 4-х полях информации о книгах. Подробнее в процедуре LoadDB}

Y: char; переменная для ввода ответа пользователя (Y/N)

S: List; указатель на текущий элемент списка, т. е. на текущую книгу. Сначала установим этот указатель на первый элемент списка, потом на второй, и т. д. до конца списка. Используется для прохода по всему списку

begin

ClrScr;процедура. очищает экран

TextColor(14); процедура. Устанавливает цвет символов. 14 – Желтый цвет

GotoXY(4,2); процедура. Перемещает курсор в позицию с координатами 4 по горизонтали и 2 по вертикали

Write('Задайте имя файла: '); процедура. Выводит строку на экран

ReadLn(FileName);процедура. вводит с экрана имя файла в переменную FileName.

Полное описание следующих нескольких строк можно прочитать в процедуре LoadDB. Они одинаковые

Assign(F, FileName); {связать с файлом на диске. Тот же самый механизм как и при чтении из файла}

{$I-} {отключить проверку ошибок}

Reset(F); {попытка открыть файл}

{$I+} {включить проверку ошибок}

if IOResult <> 0 then {если была ошибка при открытии файла}

begin

TextColor(12); процедура. Устанавливает цвет символов. 12 – светло-красный цвет

WriteLn(' Создан новый файл'); процедура. Выводит строку на экран

Rewrite(F); {процедура. если файл F не существует, то она создает такой файл на диске и открывает его для записи в него}

end

else {если файл был найден}

begin

Close(F);процедура. закрывает файл F

WriteLn(' Файл уже существует!'); процедура. Выводит строку на экран

Write(' Перезаписать его (Y/N)?'); процедура. Выводит строку на экран

Y:=ReadKey; ReadKey – процедура, которая возвращает код нажатой клавиши. запрашиваем ответ пользователя. Пользователь должен ответить ввести букву Y или N. Этот ответ записываем в переменную Y

if (Y='Y') or (Y='y') then сравнение. если пользователь ввел букву Y или y, то

begin

WriteLn(' Файл был перезаписан!'); процедура. Выводит строку на экран

Rewrite(F); {процедура. открывает файл F для записи в него}

end

else

begin

WriteLn(' Сохранение отменено!!!'); процедура. Выводит строку на экран

exit;процедура. Вызывает выход из данной процедуры BDInFile совсем, если пользователь не хочет файл перезаписывать

end;

end;

S:=BD; описание указателя s см. выше. Устанвливаем указатель s на начало БД, т. е. на первый элемент списка

while S<>nil do цикл пока не дошли до конца списка, т.е. пока адрес в s не пустой. тот же самый механизм перемещения по всему списку, начиная с начала списка и до конца

begin

Write(F, S^.Data); {процедура. записает в файл F запись S^.Data из текущего элемента списка. Т. е. Все 4 поля информации о книге сразу одним вызовом процедуры в файл}

S:=S^.Next; присваивание. перемещаемся на следующий элемент списка, т. е. из текущего элемента списка берем адрес следующего элемента списка

end;

TextColor(10); процедура. Устанавливает цвет символов. 10 – светло-зеленый цвет

GotoXY(4,7); процедура. Перемещает курсор в позицию с координатами 4 по горизонтали и 7 по вертикали

WriteLn('БД успешно сохранена!!!'); процедура. Выводит строку на экран

Close(F); {процедура. закрывает файл F}

end;

begin {главная программа}

Zastavka; {вызываем процедуру графической заставки}

YesBD:=false; {в логическую переменную присваиваем False. Т. е. БД пока нет}

TextBackground(7); процедура. Устанавливает цвет символов. 7 – светло-серый цвет

ClrScr;процедура. очищает экран

Repeat {цикл для меню. В котором будем крутиться пока пользователь не введет цифру 7, т. е. пока не выберет выход из программы}

Window(4,3,30,21); процедура. рисует окно слева на экране. Про параметры см. в процедуре ViewBD.

TextBackground(0); процедура. устанавливает цвет фона символов 0 – черный.

ClrScr; процедура. Очищает в данном случае не весь экран, а только окно, созданное последним, т. е.с координатами 4,3,30,21 и закрашивает его текущим цветом фона символов 0.

Это все было сделано для создания тени у окна с меню.

Window(3,2,29,20); процедура. рисует окно слева на экране. Про параметры см. в процедуре ViewBD.

TextBackground(1); процедура. устанавливает цвет фона символов 1 – синий.

ClrScr; процедура. Очищает в данном случае не весь экран, а только окно, созданное последним, т. е.с координатами 3,2,29,20 и закрашивает его текущим цветом фона символов 1.

TextColor(12); процедура. Устанавливает цвет символов. 12 – светло-красный цвет

GotoXY(6,2); процедура. Перемещает курсор в позицию с координатами 6 по горизонтали и 2 по вертикали

WriteLn('МЕНЮ:'); процедура. Выводит строку на экран

WriteLn; процедура. Переводит курсор на новую строку на экране

if YesBD then сравнение. Если логическая переменная YesBD равна True, т. е. база загружена, то выполняем TextColor(7)

TextColor(7) процедура. Устанавливает цвет символов. 7 – светло-серый цвет

else

TextColor(14); процедура. Устанавливает цвет символов. 14 – желтый цвет

WriteLn(' 1. Загрузка БД из файла'); процедура. Выводит строку на экран

Если база загружена уже, то цвет символов желтый, иначе-белый (аналогично, как и выше. Только цвета меняются местами)

if YesBD then TextColor(14) else TextColor(7);

выводим все остальные пункты меню

WriteLn(' 2. Просмотр БД'); процедура. Выводит строку на экран

WriteLn(' 3. Добавить запись'); процедура. Выводит строку на экран

WriteLn(' 4. Поиск записи'); процедура. Выводит строку на экран

WriteLn(' 5. Сохранение БД в файл'); процедура. Выводит строку на экран

WriteLn(' 6. Удаление БД'); процедура. Выводит строку на экран

TextColor(14); процедура. Устанавливает цвет символов. 14 – желтый цвет

WriteLn(' 7. Выход'); процедура. Выводит строку на экран

WriteLn; процедура. Переводит курсор на новую строку на экране

TextColor(12); процедура. Устанавливает цвет символов. 12 – светло-красный цвет

Write(' Ваш выбор: '); процедура. Выводит строку на экран

Запрашиваем у пользователя номер выбранного пункта меню

ReadLn(menu);процедура. вводит номер выбранного пункта меню в переменную menu

Далее идут 6 строк, аналогичных строкам, которые были строк 25 выше. Здесь мы тоже рисуем сначала черную тень для окна, потом само окно. Только это будет окно, расположенное справа на экране.

Window(32,3,78,21);

TextBackground(0);

ClrScr;очищаем окно

Window(31,2,77,20);

TextBackground(1);

ClrScr; очищаем окно

case menu of {оператор выбора case. организует работу меню, т. е вызывает разные процедуры в зависимости от выбранного пункта меню, т. е. в зависимости от значения переменной menu}

если выбрали пункт меню 1, и БД уже была загружена (логическая переменная YesBD = True), то вызываем процедуру WriteLn вывода сообщения 'BD уже есть!', иначе вызываем написанную нами процедуру LoadBD – загрузка БД.

1: if YesBD then WriteLn('BD уже есть!') else LoadBD;

если выбрали пункт меню 2, и БД уже была загружена (логическая переменная YesBD = True), то вызываем написанную нами процедуру ViewBD. Иначе вызываем процедуру WriteLn вывода сообщения 'Нет БД для работы!'

2: if YesBD then ViewBD else WriteLn('Нет БД для работы!');

И так далее аналогичные проверки и вызовы:

3: if YesBD then AddRec else WriteLn('Нет БД для работы!');

4: if YesBD then FindRec else WriteLn('Нет БД для работы!');

5: if YesBD then BDInFile else WriteLn('Нет БД для работы!');

6: if YesBD then DelBD else WriteLn('Нет БД для работы!');

7: WriteLn(' Спасибо за работу!'); процедура. Выводит строку ' Спасибо за работу!' на экран перед выходом из программы

Если пользователь ввел не цифру от 1 до 7 то вызываем процедуру WriteLn вывода сообщения

else WriteLn('Неверный ввод!!! Повторите выбор!!!');

end;

until menu=7; цикл пока пользователь не выберет выход из программы, т. е. пока переменная menu не равна 7.

end.