Программа обработки данных в библиотеке

Программа обработки данных в библиотеке 

Пояснительная записка к курсовой работе по дисциплине “Основы алгоритмизации и программирования”

Выполнил : студент гр. 96-ВВ3  Митиков Р.О.

Пензенский государственный университет, Кафедра  “Вычислительная Техника”

Пенза 1998

Введение

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

Интерес к персональным компьютерам постоянно растет,а круг их пользователей непрерывно расширяется.В число пользователей ПЭВМ вовлекаются как новички в компьютерном деле,так и специалисты по другим классам ЭВМ.  

Язык С++ - универсальный язык общего назначения, область приложений которого - программирование систем в самом широком смысле. Кроме этого, С++ успешно используется как во многих приложениях, так и в мощных операционных системах. Реализация С++ осуществлена для машин в диапазоне от самых простых персональных компьютеров до самых мощных суперкомпьютеров и для всех операционных систем.

1 Постановка задачи

Задача курсовой работы состоит в разработке на языке программирования С++ программы обработки данных в библиотеке , которая должна осуществлять следующие функции:

1) Ввод данных о книгах , имеющихся в библиотеке:название книги , автор , количество экземпляров , порядковый номер , стоимость книги 

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

3) Сбор статистики о книгах одного автора с разными названиями.

4) Построение графической диаграммы для пункта по выбору.

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

Программу разработать на языке С++ v.3.1.

2 Метод решения задачи

Анализируя постановку задачи становится ясно , что для её решения необходимо применить метод многофункционального программирования - этот метод основан на разбиении программы на отдельные функциональные модули , которые вызываются из основной программы в процессе её работы.

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

3 Описание логического представления данных

Входными данными в программе являются:

Файл базы данных , который записан на диске в файле librarym.dat.

Данные , которые в процессе работы программы можно добавить , удалить или отредактировать.

Выходными данными в программе являются:

Данные , сортированные по названию или автору 

Результат поиска по заданной маске 

График 

Файл базы данных , который записывается на диск в файл librarym.dat при завершении работы программы.

Данные об книге хранятся в массиве структур типа books:

Структура books:

Поле

Тип

Название

name

 строка 30 символов типа char 

Название

fio

строка 30 символов типа char

Автор

num

int

Количество

price

float

Стоимость

number

long

Порядковый номер

loc

int 

Расположение

ss

int

Тематика

nn

int 

Номер по названию

nf

int

Номер по автору

Глобальные переменные программы:

Поле

Тип

Название

cdt

массив переменных типа books на 501 элемент

Массив данных о странах

cnum

Int

Количество книг

sort

Char

тип сортировки

ftm

Char

Расположение

6 Спецификация на функциональные модули

6.1 Функция cmp

Строка вызова:

if (cmp(cdt[n].name,cdt[500].name)&&cmp(cdt[n].fio,cdt[500].fio)&&    (cdt[n].price>=cdt[500].price))

Назначение:

Осуществляет сравнение строки с маской

Функции:

Просматривает последовательно заданную строку , и если в ней найдена маска , то возвращается 1 , если нет - 0.

Логические 

переменные:

*a (char) - указатель на строку

*b (char) - указатель на маску для поиска

Внутренние 

переменные:

k (int) - результат сравнения

n (int) - счётчик

Вызывает функции:

нет

Вызывается из:

index , find

6.2 Функция output

Строка вызова:

output(sv,sk)

Назначение:

Осуществляет вывод на экран списка книг

Функции:

Очистка экрана , вывод 10 элементов , если элемент выбран , выделение цветом , вывод данных о книге на экран.

Логические 

переменные:

sv,sk (int) - координаты первого элемента на экране

Внутренние 

переменные:

n (int) - счётчик

m (int) - временная переменная 

nd (int) - порядковый номер данной книги

Вызывает функции:

нет

Вызывается из:

scroll

6.3 Функция menu

Строка вызова:

st=menu(30,5,"Добавить в список  "

          "Удалить из списка  "

          "Редактировать    "

          "По Автору      "

          "По Названию     "

          "Выход в главное меню"

          "\x0") 

st=menu(30,5," Список книг    "

        " Поиск по маске   "

        " Количество книг  "

        " Выход из программы "

        "\x0") 

st=menu(40,6," Расположение:   "

          "   Читальный зал "

          "     Абонемент "

          "     Хранилище "

          "\x0") 



Назначение:

Осуществляет обработку меню

Функции:

Вывод меню на экран , опрос клавиатуры , при нажатии клавиш управления курсором (вверх , вниз) перемещение цветового курсора по пунктам меню , выбор определённого пункта меню при нажатии клавиши с номером пункта меню , при нажатии клавиши Enter возвращается номер выбранного пункта меню , при нажатии клавиши Esc возвращается -1.

Логические 

переменные:

*capt (char) - указатель на текст меню

x,y - координаты вывода меню на экран

Внутренние 

переменные:

n,m (int) - Счетчики

num (int) - Количество пунктов

k (int) - Выбранный пункт

*pt (char) - Временный указатель на символ

c (char) - Считанный с клавиатуры символ

Вызывает функции:

нет

Вызывается из:

scroll , main

6.4 Функция sinput

Строка вызова:

SInput(cdt[ed].name,30,35,6) 

SInput(cdt[ed].fio,30,35,8) 

SInput(name,40,20,23) 



Назначение:

Осуществляет ввод строки.

Функции:

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

Логические 

переменные:

*s (char) - указатель на строку

lng (int) - максимальная длина

x,y - координаты ввода

Внутренние 

переменные:

rs[100] (char) - Временная строка

n (int) - Счетчик

c (char) - Введённый с клавиатуры символ

Вызывает функции:

нет

Вызывается из:

edit , find

6.5 Функция dinput

Строка вызова:

cdt[ed].price=DInput(35,10) 

cdt[ed].number=DInput(35,12) 

cdt[ed].num=DInput(35,14) 



Назначение:

Осуществляет ввод числа.

Функции:

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

Логические 

переменные:

*s (char) - указатель на строку

lng (int) - максимальная длина

x,y - координаты ввода

Внутренние 

переменные:

s[100] (char) - Временная строка

* сtpe (char) - указатель на сторку

rs (double) - Результат

n (int) - Счетчик

c (char) - Введённый с клавиатуры символ

Вызывает функции:

нет

Вызывается из:

edit

6.6 Функция graph

Строка вызова:

graph() 



Назначение:

Осуществляет построения столбчатой диаграммы по распределению книг .

Функции:

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

Логические 

переменные:

нет

Внутренние 

переменные:

drv,mode (int) - для инициализации графики

c (int) - Цвет

k1,k2,k3 (int) - количество книг

n (int) - Счетчик

m (int) - Масштаб

Вызывает функции:

нет

Вызывается из:

main

6.7 Функция index

Строка вызова:

index()

Назначение:

Осуществляет индексирование массива - назначение номеров элементов по алфавиту для каждого поля записи.

Функции:

Cтирание старых индексов , перебор всех возможных мест хранения , индексация по автору , поиск наименьшего , индексация по названию , поиск наименьшего.

Логические 

переменные:

нет

Внутренние 

переменные:

n,m (int) - счётчики

tm (int) - перебор тем

mxc (char[100]) - значение наименьшей строки

nm (int) - номер очередного элемента

Вызывает функции:

cmp

Вызывается из:

scroll

6.8 Функция edit

Строка вызова:

edit(cnum-1) 

edit(n) 

edit(500) 



Назначение:

Осуществляет редактирование элемента массива.

Функции:

Ввод данных , вывод одного из полей структуры , опрос клавиатуры , выбор действия - редактирование поля или выход (клавиша Esc).

Логические 

переменные:

ed (int) - номер элемента массива

Внутренние 

переменные:

n (int) - счётчик

en (int) - редактируемое поле

c (char) - Введённый с клавиатуры символ

Вызывает функции:

sinput , dinput

Вызывается из:

scroll

6.9 Функция find

Строка вызова:

find() 



Назначение:

Осуществляет поиск элемента в заданной строке по заданной маске.

Функции:

Поиск элемента , Возврат результатов в файл или на экран.

Логические 

переменные:

нет

Внутренние 

переменные:

n (int) - счётчик

*F(file - файл ввода

name[50] (char) - Имя файла

Вызывает функции:

cmp , sinput

Вызывается из:

main

6.10 Функция scroll

Строка вызова:

scroll ()

Назначение:

Осуществляет обработку списка.

Функции:

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

Логические 

переменные:

нет

Внутренние 

переменные:

st (int) - номер выбранного пункта меню

n (int) - счётчик

c (char) - Введённый с клавиатуры символ

sv , sk (int) - первый элемент на экране и положение курсора

Вызывает функции:

output , menu , edit , index.

Вызывается из:

main

6.11 Функция load

Строка вызова:

load()

Назначение:

Осуществляет загрузку базы данных из файла.

Функции:

Открытие файла с именем librarym.dat , чтение количества строк в массиве , чтение данных в массив , закрытие файла.

Логические 

переменные:

нет

Внутренние 

переменные:

*f (file) - указатель на файл

Вызывает функции:

нет

Вызывается из:

main

6.12 Функция save

Строка вызова:

save()

Назначение:

Осуществляет запись базы данных в файл.

Функции:

Открытие файла librarym.dat , запись количества элементов , запись данных в файл , закрытие файла.

Логические 

переменные:

нет

Внутренние 

переменные:

*f (file) - указатель на файл



Вызывает функции:

нет

Вызывается из:

main

6.13 Основная программа - main

Назначение:

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

Функции:

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

Вызывает функции:

load , save , scroll , menu , find , graph.

7 Технические требования для использования

Для запуска данной программы необходимо наличие персонального компьютера IBM PC/XT c операционной системой MS-DOS.

Необходимый объем оперативной памяти -640 Кбайт.

Дла запуска программы необходимо сделать текущем каталог с программой kurs.exe и вызвать её на выполнение.

Программа работает в текстовом режиме 80х25 символов , построение диаграммы осуществляется в графическом режиме 640х480 точек 16 цветов.

Файл базы данных программы librarym.dat будет записываться и считываться из текущего каталога текущего диска.

Управление программой осуществляется с клавиатуры.

8 Руководство пользователя

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

При нажатии клавиши Enter на одном из элементов списка , то на экран будет вызванно меню:

1) Список книг

2) Поиск по маске

3) Количество книг

4) Выход из программы

При выборе первого пункта меню моявится следующее подменю:

1) Расположение:

2) Читальный зал

3) Абонемент

4) Хранилище



При нажатии пользователем клавиши Enter на выведенном списке книг появляется меню:

1) Добавить в список

2) Удалить из списка

3) Редактировать

4) По Автору

5) По Названию

6) Выход в главное меню

При нажатии на клавиши управления курсором (вверх , вниз) можно управлять курсором , если нажать клавишу Enter или клавишу с номером пункта меню , то произойдёт то или иное действие в соответствии с выбранным пунктом.

Отсортированная последовательность выводится на экран в виде списка книг. При выборе пункта "Поиск по маске" программа запрашивает данные для поиска книги: Название , Автор , Стоимость , Порядковый номер , Количество , Тематика (Не влияет).

После поиска , если такая книга имеется в списке , данные о найденной книги выводятся на экран.

При выборе пункта "Выход из программы" программа завершает свою работу.

9 Тестирование программы

Для полной проверки работоспособности программы необходимо её протестировать.

План тестирования программы учёта и выборки информации о странах состоит в следующем:

1) Загрузка программы

2) Ввод данных о книгах

3) Удаление книги из списка

4) Редактирование данных о книге

5) Сортировка 

6) Поиск по маске

7) Построение диаграммы

8) Выход из программы

Далее в пункте "Результаты работы программы" приводится распечатка тестирования программы по пунктам плана тестирования и результатов тестирования.

10 Результаты работы программы

2) Ввод данных о книгах

76             Автор2             Книга9  22 11.00р

11             Автор2             Книга8  28 21.00р

22            Автор65            Книга33  18 32.00р

55             Автор1             Книга3  12 22.00р

 2             Автор2             Книга2  10 55.00р

 1             Автор1            Книга 1  10 34.00р

3) Удаление книги из списка

76             Автор2             Книга9  22 11.00р

11             Автор2             Книга8  28 21.00р

22            Автор65            Книга33  18 32.00р

55             Автор1             Книга3  12 22.00р

 2             Автор2             Книга2  10 55.00р

4) Редактирование данных о книге

       Название:                        Книга3

       Автор:                           Автор1

       Стоимость:                        20.00

       Порядковый номер:                   55

       Количество:                         20

       Тематика:                        Научная

5) Сортировка 

По автору:

22            Автор65            Книга33  18 32.00р

76             Автор2             Книга9  22 11.00р

 2             Автор2             Книга2  10 55.00р

11             Автор2             Книга8  28 21.00р

55             Автор1             Книга3  20 20.00р

По названию:

76             Автор2             Книга9  22 11.00р

11             Автор2             Книга8  28 21.00р

22            Автор65            Книга33  18 32.00р

55             Автор1             Книга3  20 20.00р

 2             Автор2             Книга2  10 55.00р

7) Построение диаграммы



Заключение

В данной курсовой работе решена задача разработки программы обработки данных в библиотеке.

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

Список литературы

1.Бьярн Страуструп. Язык программирования С++.в двух частях. Пер. с англ. Киев:"ДиаСофт",1993.-296 с.,ил.

2.Корриган Джон Компьютерная графика: Секреты и решения: Пер с англ. -М.:Энтроп, 1995. - 352 с., ил.

ПРИЛОЖЕНИЕ 1

Распечатка программы

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <graphics.h>

#include <conio.h>

// Структура - данные о одной книге

struct books {

char name[30] 

    // Название

char fio[30] 

     // Автор

int num 

       // Количество

float price 

     // Стоимость

long number 

     // Порядковый номер

// Расположение: 0-читальный зал, 1-абонемент, 2-хранилище

int loc 

int tem 

       // Тематика

int nn,nf 

      // Номер по названию, автору

} 

// Массив - 500 книг и маска для поиска

books cdt[501] 

     // Массив данных о книгах

int cnum 

        // Количество книг

// Сортировать по: 1-Названию, 2-автору

char sort 

// Расположение

char ftm 

const char location[3][15]={" Читальный зал\x0",

             "   Абонемент\x0",

             "   Хранилище\x0"} 

const char tema[5][15]={  "Художественная\x0",

             "  Техническая\x0",

             "    Научная\x0",

             "  Справочник\x0",

             " _Не влияет_ \x0"} 

// ПРОТОТИПЫ ФУНКЦИЙ

// Сравнение строки с маской

int cmp(char * a,char * b) 

// Вывод списка на экран

void output(int sv,int sk) 

// Обработка меню

int menu(int x,int y,char * capt) 

// Ввод строки

void SInput(char * s,int lng,int x,int y) 

// Ввод числа

double DInput(int x,int y) 

// Индексирование массива

void index() 

// Редактирование элемента

void edit(int ed) 

// Вывод данных по маске

void find() 

// Вывод графика

void graph() 

// Обработка списка

void scroll() 

// Чтение массива

void load() 

// Запись массива

void save() 

// ТЕЛА ФУНКЦИЙ

// Сравнение строки с маской

// a- строка, b- маска

int cmp(char * a,char * b) {

int k 

int n 

k=1 

for (n=0 

n<strlen(b) 

n++)

 if (a[n]!=b[n]) k=0 

return k 

}

// Вывод списка на экран

void output(int sv,int sk) {

int n 

int m 

int nd 

m=sv 

// Очистка экрана

textcolor(15) 

textbackground(1) 

clrscr() 

// Вывод двадцати элементов

for (n=1 

n<20 

n++) {

// Если элемент выбран, изменение цветов

 if (n==sk) {

  textbackground(14) 

 } else {

  textbackground(1) 

 }

 if (m<(cnum+1)) {

  nd=0 

  // Поиск элемента с данным индексом

  switch (sort) {

   case(1):

    while (((cdt[nd].nn!=m)||(cdt[nd].loc!=ftm))&&(nd<cnum+1)) nd++ 

    break 

   case(2):

    while (((cdt[nd].nf!=m)||(cdt[nd].loc!=ftm))&&(nd<cnum+1)) nd++ 

    break 

  }

  switch (sort) {

   case(1):

    if ((cdt[nd].nn!=m)||(cdt[nd].loc!=ftm)) nd=-1 

    break 

   case(2):

    if ((cdt[nd].nf!=m)||(cdt[nd].loc!=ftm)) nd=-1 

    break 

  }

  m++ 

  // Вывод данных о стране на экран

  gotoxy(1,m-sv) 

  if (nd!=-1)

   cprintf("%4ld %30s %30s %4d %6.2fр",cdt[nd].number,cdt[nd].fio,

               cdt[nd].name,cdt[nd].num,cdt[nd].price) 

 }

}

textbackground(1) 

}

// Обработка меню

int menu(int x,int y,char * capt) {

int n,m 

// Счетчики

int num 

// Количество пунктов

int k 

// Выбранный пункт

char * pt 

// Временный указатель на символ

char c 

// Считанный с клавиатуры символ

// Вычисляем количество пунктов

num=strlen(capt)/20 

// Курсор на нулевой элемент

k=0 

// Бесконечный цикл обработки

for ( 

) {

// Вывод меню

 pt=capt 

 for (n=0 

n<num 

n++) {

  gotoxy(x,y+n) 

// Закраска пункта, на который указывает курсор

  if (n==k) {

  // Закраска

textbackground(12) 

textcolor(14) 

  } else {

  // Нормальный

textbackground(3) 

textcolor(1) 

  }

  cprintf("%d) ",n+1) 

  for (m=0 

m<20 

m++) cprintf("%c",*(pt++)) 

 }

 textbackground(3) 

 textcolor(1) 

// Опрос клавиатуры

 c=getch() 

 if (!c) c=getch() 

// Проверка, не нажата ли клавиша с цифрой

 if (((c-'1')>=0)&&((c-'1')<num)) {

// Установка указателя в зависимости от нажатой цифры

  k=c-'1' 

// Запись в буфер клавиатуры символа ENTER

  ungetch(13) 

 } else {

 // Анализ

  switch(c) {

   // Вверх

   case (72):

 if (k>0) k-- 

else k=num-1 

 break 

   // Вниз

   case (80):

 if (k<(num-1)) k++ 

else k=0 

 break 

   // Выход по ESC - возвращается -1

   case (27):

 return -1 

   // Выход по ENTER - возвращается номер пункта

   case (13): return k 

  }

 }

}

}

// Ввод строки

// s - указатель на строку

// lng - Максимальная длинна

// x,y - координаты

void SInput(char * s,int lng,int x,int y) {

lng-- 

char rs[100] 

    // Временная строка

strcpy(rs,s) 

    // Копирование резерва строки

int n 

       // Счетчик

char c 

       // Символ

_setcursortype(_NORMALCURSOR) 

// Вывод пустой строки

textbackground(2) 

textcolor(15) 

gotoxy(x,y) 

for (n=0 

n<lng 

n++) cprintf(" ") 

n=strlen(s) 

    // Положение курсора

do {

// Вывод строки

 gotoxy(x,y) 

 cprintf("%s ",s) 

 gotoxy(x+n,y) 

 c=getch() 

    // Считывание символа с клавиатуры

 if ((c!=13)&&(c!=27)&&(c!=8)) {

 // Нажата символьная клавиша

  if (n<(lng-1)) {

  // Добавление символа

   s[n+1]=0 

   s[n]=c 

   n++ 

  }

 } else {

  if (c==8) {

  // Нажата клавиша BackSpace

   if (n>0) {

    n-- 

    s[n]=0 

   }

  }

 }

// Выход, если ESC или ENTER

} while ((c!=27)&&(c!=13)) 

if(c==27) strcpy(s,rs) 

   // Восстановление строки

// Стирание строки

textbackground(0) 

textcolor(7) 

gotoxy(x,y) 

for (n=0 

n<lng+1 

n++) cprintf(" ") 

_setcursortype(_NOCURSOR) 

}

// Ввод числа

// x,y - координаты

double DInput(int x,int y) {

char s[100] 

    // Временная строка

char *stpe 

double rz 

s[0]=0 

int n 

       // Счетчик

char c 

       // Символ

// Вывод пустой строки

_setcursortype(_NORMALCURSOR) 

textbackground(2) 

textcolor(15) 

gotoxy(x,y) 

for (n=0 

n<15 

n++) cprintf(" ") 

n=strlen(s) 

    // Положение курсора

do {

// Вывод строки

 gotoxy(x,y) 

 cprintf("%s ",s) 

 gotoxy(x+n,y) 

 c=getch() 

    // Считывание символа с клавиатуры

 if ((c!=13)&&(c!=27)&&(c!=8)) {

 // Нажата символьная клавиша

  if (n<14) {

  // Добавление цифры или точки

   if ((c>='0')&&(c<='9')||(c=='.')) {

    s[n+1]=0 

    s[n]=c 

    n++ 

   }

  }

 } else {

  if (c==8) {

  // Нажата клавиша BackSpace

   if (n>0) {

    n-- 

    s[n]=0 

   }

  }

 }

// Выход, если ESC или ENTER

} while ((c!=27)&&(c!=13)) 

if(c==27) return 0 

// Стирание строки

textbackground(0) 

textcolor(7) 

gotoxy(x,y) 

for (n=0 

n<15 

n++) cprintf(" ") 

rz=strtod(s,&stpe) 

_setcursortype(_NOCURSOR) 

return rz 

}

// Индексирование массива - Назначение номеров элементов

void index() {

int tm 

           // Перебор тем

int n,m 

          // Счетчики

char mxc[100] 

       // Значение наименьшей строки

int nm 

           // Номер очередного элемента

// Стирание старых индексов

for (n=0 

n<cnum 

n++) {

 cdt[n].nn=0 

 cdt[n].nf=0 

}

// Перебор всех возможных мест хранения

for (tm=0 

tm<3 

tm++) {

// Индексация по автору

 for (m=0 

m<cnum 

m++) {

 // Поиск наименьшего

  strcpy(mxc,"\x0") 

  nm=-1 

  for (n=0 

n<cnum 

n++)

   if ((cdt[n].nf==0)&&(cdt[n].loc==tm))

    if (strcmp(cdt[n].fio,mxc)>0) {

    strcpy(mxc,cdt[n].fio) 

    nm=n 

  }

  if (nm!=-1) cdt[nm].nf=m+1 

 }

// Индексация по названиям

 for (m=0 

m<cnum 

m++) {

 // Поиск наименьшего

  strcpy(mxc,"\x0") 

  nm=-1 

  for (n=0 

n<cnum 

n++)

   if ((cdt[n].nn==0)&&(cdt[n].loc==tm))

    if (strcmp(cdt[n].name,mxc)>0) {

    strcpy(mxc,cdt[n].name) 

    nm=n 

  }

  if (nm!=-1) cdt[nm].nn=m+1 

 }

}

}

// Редактирование элемента массива

void edit(int ed) {

clrscr() 

// Обработка

int n 

       // Счетчик

int en=0 

      // Редактируемое поле

char c 

       // Символ с клавиатуры

for( 

) {

// Вывод данных

 for (n=0 

n<6 

n++) {

 // Изменение цвета если элемент выбран

  if (n==en) {

   textbackground(12) 

   textcolor(15) 

  } else {

   textbackground(1) 

   textcolor(7) 

  }

  gotoxy(15,6+2*n) 

 // Вывод одного из полей структуры

  switch(n) {

   case 0:

    cprintf(" Название:     %45s",cdt[ed].name) 

    break 

   case 1:

    cprintf(" Автор:      %45s",cdt[ed].fio) 

    break 

   case 2:

    cprintf(" Стоимость:    %45.2f",cdt[ed].price) 

    break 

   case 3:

    cprintf(" Порядковый номер: %45d",cdt[ed].number) 

    break 

   case 4:

    cprintf(" Количество:    %45d",cdt[ed].num) 

    break 

   case 5:

    cprintf(" Тематика:     %45s",tema[cdt[ed].tem]) 

  }

 }

// Опрос клавиатуры

 c=getch() 

 if (!c) c=getch() 

 switch(c){

 // Вверх

  case (72):

   en-- 

   if (en<0) en=5 

   break 

 // Вниз

  case (80):

   en++ 

   if (en>5) en=0 

   break 

 // ENTER - Редактирование поля или выход

  case (13):

  // Выбор действия

   switch(en) {

    case 0:

     SInput(cdt[ed].name,30,35,6) 

     break 

    case 1:

     SInput(cdt[ed].fio,30,35,8) 

     break 

    case 2:

     cdt[ed].price=DInput(35,10) 

     break 

    case 3:

     cdt[ed].number=DInput(35,12) 

     break 

    case 4:

     cdt[ed].num=DInput(35,14) 

     break 

    case 5:

    // Изменение тематики

     cdt[ed].tem=(cdt[ed].tem+1)%4 

     break 

   }

  break 

  case(27):

   return 

 }

}

}

// Вывод по маске

void find() {

int n 

       // Счетчик

FILE * f 

      // Файл вывода

char name[50] 

   // Имя файла

strcpy(name,"CON") 

 // Изначально - CON, т.е. экран

// Ввод имени файла вывода

textbackground(0) 

clrscr() 

gotoxy(1,23) 

cprintf(" Введитеимя файла: ") 

SInput(name,40,20,23) 

// Открывается файл на запись

f=fopen(name,"wb") 

if (f==NULL) return 

fprintf(f,"\n\r Список книг, выбранных по маске \n\r") 

// Перебор всех элементов

for (n=0 

n<cnum 

n++)

// Если удовлетворяет условию

 if (cmp(cdt[n].name,cdt[500].name)&&

   cmp(cdt[n].fio,cdt[500].fio)&&

   (cdt[n].price>=cdt[500].price)) {

// Вывод в файл

 fprintf(f,"%4ld %30s %30s %4d %6.2fр\n\r",cdt[n].number,cdt[n].fio,

               cdt[n].name,cdt[n].num,cdt[n].price) 

}

// Закрывается файл

fclose(f) 

printf("\n\n Нажмите любую клавишу для продолжения") 

getch() 

}

// Вывод графика

void graph() {

// Ингициализация графики

int c 

        // Цвет

int drv,mode 

    // Для инициализации графики

int k1,k2,k3 

    // Количество книг

int n 

        // Счетчик

int m 

        // Масштаб

drv=DETECT 

initgraph(&drv,&mode,"") 

// Подсчет количества книг

k1=k2=k3=0 

for (n=0 

n<cnum 

n++) {

 switch(cdt[n].loc) {

  case (0):

   k1++ 

   break 

  case (1):

   k2++ 

   break 

  case (2):

   k3++ 

   break 

 }

}

// Определение максимального

if (k1>k2) m=k1 

else m=k2 

if (m<k3) m=k3 

// Определение масштаба

m=400/m 

// Вывод столбчатой диаграммы

line(0,470,640,470) 

line(10,0,10,480) 

outtextxy(100,20," Распределение книг ") 

// Рассчет цвета столбца - 12 - максимальное значение

c=12 

if (k2>k1) c-- 

if (k3>k1) c-- 

setfillstyle(9,c) 

bar3d(20,470-m*k1,120,470,10,1) 

// Рассчет цвета столбца - 12 - максимальное значение

c=12 

if (k1>k2) c-- 

if (k3>k2) c-- 

setfillstyle(9,c) 

bar3d(140,470-m*k2,240,470,10,1) 

// Рассчет цвета столбца - 12 - максимальное значение

c=12 

if (k1>k3) c-- 

if (k2>k3) c-- 

setfillstyle(9,c) 

bar3d(260,470-m*k3,360,470,10,1) 

// Вывод поясняющих надписей

setcolor(14) 

outtextxy(30,450-m*k1,"Читальный зал") 

outtextxy(150,450-m*k2,"Абонемент") 

outtextxy(270,450-m*k3,"Хранилище") 

// Ожидание нажатия клавиши

getch() 

closegraph() 

_setcursortype(_NOCURSOR) 

}

// Обработка списка

void scroll() {

char c 

       // Считанный с клавиатуры символ

static int sv=1,sk=1 

// Первый элемент на экране и положение курсора

int st 

       // Выбранный пункт меню

int n 

       // Счетчик

// Цикл обработки

do {

// Вывод списка на экран

 output(sv,sk) 

// Ввод символа

 c=getch() 

 if (!c) c=getch() 

// Обработка символа

 switch (c) {

 // Вверх

  case (72):

   if (sk>1) sk-- 

else if (sv>1) sv-- 

   break 

 // Вниз

  case (80):

   if (sk<7) {

    if (sk<(cnum-sv+1)) sk++ 

   } else if (sv<(cnum-7)) sv++ 

   break 

 // Меню

  case (13):

   st=menu(30,5,"Добавить в список  "

          "Удалить из списка  "

          "Редактировать    "

          "По Автору      "

          "По Названию     "

          "Выход в главное меню"

          "\x0") 

   switch(st) {

    case (0):

     if (cnum<299) {

      cdt[cnum].name[0]=0 

      cdt[cnum].fio[0]=0 

      cdt[cnum].price=0 

      cdt[cnum].number=0 

      cdt[cnum].num=0 

      cdt[cnum].tem=0 

      cdt[cnum].loc=ftm 

      cnum++ 

      edit(cnum-1) 

     }

     index() 

     break 

    case (1):

    // Удаление элемента

     if (cnum>1) {

      n=0 

      switch (sort) {

       case (1):

        while (((cdt[n].nn!=sk+sv-1)||(cdt[n].loc!=ftm))&&(n<cnum+1)) n++ 

        break 

       case (2):

        while (((cdt[n].nf!=sk+sv-1)||(cdt[n].loc!=ftm))&&(n<cnum+1)) n++ 

        break 

      }

      if (n!=(cnum+1)) {

       strcpy(cdt[n].name,cdt[cnum-1].name) 

       strcpy(cdt[n].fio,cdt[cnum-1].fio) 

       cdt[n].price=cdt[cnum-1].price 

       cdt[n].num=cdt[cnum-1].num 

       cdt[n].number=cdt[cnum-1].number 

       cdt[n].loc=cdt[cnum-1].loc 

       cdt[n].tem=cdt[cnum-1].tem 

       cnum-- 

       index() 

      }

     }

     break 

   // Редактирование элемента

    case (2):

     n=0 

     switch (sort) {

      case (1):

       while (((cdt[n].nn!=sk+sv-1)||(cdt[n].loc!=ftm))&&(n<cnum+1)) n++ 

       break 

      case (2):

       while (((cdt[n].nf!=sk+sv-1)||(cdt[n].loc!=ftm))&&(n<cnum+1)) n++ 

       break 

     }

     edit(n) 

     index() 

     break 

    case (3):

    case (4):

     sort=5-st 

     break 

    case (5):

// Выход в предыдущее меню

     return 

   }

   break 

 }

} while(c!=27) 

}

// Чтение массива

void load() {

// Открытие файла на чтение

FILE * f 

f=fopen("librarym.dat","rb") 

if (f==NULL) return 

// Чтение количества книг

fread(&cnum,1,2,f) 

// Чтение массива

fread(cdt,cnum,sizeof(books),f) 

// Закрытие файла

fclose(f) 

}

// Запись файла

void save() {

// Открытие файла на запись

FILE * f 

f=fopen("librarym.dat","wb") 

if (f==NULL) {

 printf(" !!! ОШИБКА ПРИ ЗАПИСИ БАЗЫ ДАННЫХ !!! \n") 

 return 

}

// Запись количества элементов в массив

fwrite(&cnum,1,2,f) 

// Запись массива

fwrite(cdt,cnum,sizeof(books),f) 

// Закрытие файла

fclose(f) 

}

// Основная программа

void main() {

int st 

// Установка начальных значений

_setcursortype(_NOCURSOR) 

cnum=0 

sort=1 

ftm=0 

// Чтение массива

load() 

index() 

// Обработка

do {

// Основное меню

 textcolor(15) 

 textbackground(0) 

 clrscr() 

 st=menu(30,5," Список книг    "

        " Поиск по маске   "

        " Количество книг  "

        " Выход из программы "

        "\x0") 

 switch(st) {

  case (0):

  // Подменю для вывода списка

   st=menu(40,6," Расположение:   "

          "   Читальный зал "

          "     Абонемент "

          "     Хранилище "

          "\x0") 

   if (st!=0) {

    ftm=st-1 

    scroll() 

    st=0 

   }

   break 

  case (1):

  // Поиск

   cdt[500].name[0]=0 

   cdt[500].fio[0]=0 

   cdt[500].price=0 

   cdt[500].number=0 

   cdt[500].num=0 

   cdt[500].tem=4 

   edit(500) 

   find() 

   break 

  case (2):

  // Вывод графика

   graph() 

   break 

 }

} while (st!=3) 

// Выход из программы

textcolor(7) 

textbackground(0) 

clrscr() 

// Запись массива

save() 

_setcursortype(_NORMALCURSOR) 

}