МГТУ имени Баумана
Пояснительная записка по курсовому проекту на тему:
”Разработка базы данных для расписания занятий”
МОСКВА 2006
Содержание
1. Введение
Постановка задачи
Описание работы
2. Алгоритмы используемые в процессе выполнения проекта
Приложение
Литература
1. Введение
Постановка задачи
Задачей данной курсовой работы является написание базы данных применимой для расписания занятий в университете.
Программа реализована на языках программирования “C++”.База данных содержит список предметов. С расписанием занятий ведётся такая основная работа как:
ввод новой записи
изменение базы данных
просмотр базы данных
поиск данных и т.д.
1.2 Описание работы
Реализация базы данных включает в себя следующие компоненты:
— Вводиться группа, подгруппа,
— Вводятся неделя, день недели и время
— Вводятся предмет и фамилия преподавателя
— Выбирается аудитория
2. Алгоритмы используемые в процессе выполнения проекта
В данной программе использовались стандартные приемы программирования, характерные для написания баз данных. Использовался структурный тип для описания одной записи:
struct zap
{
char fio_teacher[20];
int n_pdgrup;
char n_audit[6];
char predmet[10];
struct ti
{
int n_ned;
char den_ned[11];
struct wat
{
int fst_time,scd_time;
}watch;
}time;
char n_group[6];
};
struct spisok
{
zap zip[1];
struct spisok *a;
};
Поиск записи происходит по следующему алгоритму:
void outzap()
{
int h,time_zip,time_zip_end,time_zill,x_up,p;
char chose;
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textcolor(WHITE);
window(27,5,50,20);
if (kolzap==0)
{
puts(«Записей нет!»);
getche();
exit(0);
}
window(1,1,80,23);gotoxy(10,3);
gotoxy(27,6); puts(«Введите группу:»); scanf("%s",zill[1].n_group);
gotoxy(27,7); puts(«Введите подгруппу:»); scanf("%d",zill[1].n_pdgrup);
gotoxy(27,8); puts(«Введите неделю:»); scanf("%d",zill[1].time.n_ned);
gotoxy(27,9); puts(«Введите день недели:»); scanf("%s",zill[1].time.den_ned);
gotoxy(20,10); puts(«Вывести расписание на день или по времени(y/n)»);
chose=getche();
switch (chose)
{
case 'y':
{
u2=u1;
clrscr();
x_up=5;
p=0;
while (u2!=NULL)
{
if ((u2->zip[1].n_group==zill[1].n_group)&&(u2->zip[1].n_pdgrup==zill[1].n_pdgrup)&&
(u2->zip[1].time.n_ned==zill[1].time.n_ned)&&(u2->zip[1].time.den_ned==zill[1].time.den_ned))
{
gotoxy(20,x_up);
if (u2->zip[1].time.watch.scd_timezip[1].time.watch.fst_time,":0",u2->zip[1].time.watch.scd_time);
else printf("%d",u2->zip[1].time.watch.fst_time,":",u2->zip[1].time.watch.scd_time);
gotoxy(27,x_up); printf("%s",u2->zip[1].predmet);
gotoxy(39,x_up); printf("%s",u2->zip[1].n_audit);
x_up=x_up+1;
p=1;
}
u2=u2->a;
}
if (p==0)
{
gotoxy(20,6);
puts(«Возможно группа задана неверно или у нее нет пар.»);--PAGE_BREAK--
}
scanf("%d",&a);
getche();
exit(0);
}
case 'n':
при нажатии клавиши “n” запись ищется по времени.
3. Приложение
#include
#include
#include
#include
FILE *f;
typedef char arr_string[7][25];
struct zap
{
char fio_teacher[20];
int n_pdgrup;
char n_audit[6];
char predmet[10];
struct ti
{
int n_ned;
char den_ned[11];
struct wat
{
int fst_time,scd_time;
}watch;
}time;
char n_group[6];
};
struct spisok
{
zap zip[1];
struct spisok *a;
};
struct zap zill[1];
struct spisok *sled,*u1,*u2,*pred,*pred2;
int i,j,col_pr,col_pn,kolzap,l,pl,b;
char kbd,kod,yes,a;
char dg[20],fm[20],filename[20];
int p;
arr_string s,d;
void outdone();
void menu();
void newzap();
void delzap();
void outzap();
//-----------------------------------------------------------------------------
void schet()
{
kolzap=0;
u2=u1;
while (u2!=NULL)
{
kolzap=kolzap+1;
u2=u2->a;
}
}
//-------------------------------------------------------------------------------------
void formir_spisok()
{
u1=NULL;
u2=NULL;
if (!feof(f)) exit(0);
u1=(struct spisok *)malloc(sizeof(struct spisok));
fread(u1->zip,sizeof u1->zip,1,f);
u1->a=NULL;
u2=u1;
while (feof(f)!=0)
{
u2->a=(struct spisok *)malloc(sizeof(struct spisok));
u2=u2->a;
fread(u2->zip,sizeof u1->zip,1,f);
u2->a=NULL;
}
pred=u2;
fclose(f);
}
//------------------------------------------------------------------------------
void menudiag()
{
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textbackground(BLACK);
window(27,5,47,5);
textbackground(RED);
textcolor(GREEN);
printf(d[1]);
window(27,7,47,7);
textbackground(BLACK);
textcolor(GREEN);
printf(d[2]);
window(27,9,47,9);
textbackground(BLACK);
textcolor(GREEN);
printf(d[3]);
i=5;j=1;p=1;
col_pr=GREEN;
col_pn=RED; продолжение
--PAGE_BREAK--
}
//-------------------------------------------------------------------------------
void quit()
{
outdone();
exit(0);
}
//---------------------------------------------------------------------------
void quit2()
{
exit(0);
}
//---------------------------------------------------------------------------
void move_line(int kol_proced,void (*proced)(),void (*proced1)(),void (*proced2)(),void (*proced3)(),void (*proced4)(), arr_string string_arr)
{
proced();
do
{
kbd=getche();
if ((kbd!=27)&&(kbd!=13)&&(kbd!=0))
{
kbd=getche();
switch (kbd)
{
case 72:
{
window(27,i,47,i);
textbackground(BLACK);
textcolor(col_pr);
clreol();
printf("%s",string_arr[j]);
if (i==5)
{
i=5+kol_proced*2-2;
j=kol_proced;
}
else
{
i=i-2;
j=j-1;
}
window(27,i,47,i);
textbackground(col_pn);
textcolor(col_pr);
clreol();
printf("%s",string_arr[j]);
}
case 80:
{
window(27,i,47,i);
textbackground(BLACK);
textcolor(col_pr);
clreol();
printf("%s",string_arr[j]);
if (i==5+kol_proced*2-2)
{
i=5;
j=1;
}
else
{
i=i+2;
j=j+1;
}
window(27,i,47,i);
textbackground(col_pn);
textcolor(col_pr);
clreol();
printf("%s",string_arr[j]);
}
}
}
switch (kbd)
{
case 27:exit(0);
case 13:{
switch (j)
{
case 1:proced1();
case 2:proced2();
case 3:proced3();
case 4:{
proced4();
exit(0);
}
}
proced();
}
}
}while (p==0);
}
//----------------------------------------------------------------------------------
void open()
{
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textbackground(BLACK);
window(20,5,78,5);
clrscr();
gotoxy(20,5);
textcolor(WHITE);
printf(«Введите путь и имя файла:»); продолжение
--PAGE_BREAK--
gets(filename);
if((f=fopen(filename,”wb"))==NULL)
{
textbackground(BLACK);
window(1,1,80,23);
clrscr();
gotoxy(27,5);
textcolor(WHITE);
printf(«Файл отсутствует!»);
getche();
exit(0);
}
formir_spisok();
schet();
move_line(4,menu,newzap,outzap,delzap,quit,s);
}
//----------------------------------------------------------------------------------
void newfile()
{
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textbackground(BLACK);
window(20,5,78,5);
clrscr();
gotoxy(20,5);
textcolor(WHITE);
printf(«Введитe путь и имя файла:»);
gets(filename);
f=fopen(filename,«wb»);
formir_spisok();
schet();
move_line(4,menu,newzap,outzap,delzap,quit,s);
}
//-------------------------------------------------------------------------------
void menu()
{
textbackground(BLACK);
clrscr();
textbackground(BLACK);
window(27,5,46,5);
textbackground(RED);
textcolor(GREEN);
puts(s[1]);
window(27,7,46,7);
textbackground(BLACK);
textcolor(GREEN);
puts(s[2]);
window(27,9,46,9);puts(s[3]);
window(27,11,46,11);puts(s[4]);
window(27,13,46,13);puts(s[5]);
window(27,15,46,15);puts(s[6]);
window(27,17,46,17);puts(s[7]);
window(27,5,46,5);
i=5;j=1;p=1;
col_pr=GREEN;
col_pn=RED;
}
//----------------------------------------------------------------------------------
void newzap()
{
char a;
if (kolzap==0)
{
u1=(struct spisok *)malloc(sizeof(struct spisok));
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textcolor(WHITE);
gotoxy(27,5); puts(«Заполните новую запись»);
gotoxy(27,6); puts(«Введите группу:»); scanf("%s",zill[1].n_group);
gotoxy(27,7); puts(«Введите подгруппу:»); scanf("%d",&zill[1].n_pdgrup);
gotoxy(27,8); puts(«Введите неделю:»); scanf("%d",zill[1].time.n_ned);
gotoxy(27,9); puts(«Введите день недели:»); scanf("%s",zill[1].time.den_ned);
gotoxy(27,10); puts(«Введите время: :»);
gotoxy(41,10); a=getche(); printf("%d",a); b=(ord(a)-48)*10;
gotoxy(42,10); a=getche(); printf("%d",a); b=b+(ord(a)-48);
zill[1].time.watch.fst_time=b;
gotoxy(44,10); a=getche(); printf("%d",a); b=(ord(a)-48)*10;
gotoxy(45,10); a=getche(); printf("%d",a); b=b+(ord(a)-48);
zill[1].time.watch.scd_time=b;
gotoxy(27,12); puts(«Введите предмет:»); scanf("%s",zill[1].predmet);
gotoxy(27,13); puts(«Введите фамилию преподавателя:»); scanf("%s",zill[1].fio_teacher);
gotoxy(27,14); puts(«Введите аудиторию:»); scanf("%s",zill[1].n_audit);
u1->zip[1]=zill[1];
u1->a=NULL;
u2=u1;
pred=u1;
}
else
{
textbackground(BLACK);
window(1,1,80,23);
clrscr(); продолжение
--PAGE_BREAK--
textcolor(WHITE);
gotoxy(27,5); puts(«Заполните новую запись»);
gotoxy(27,6); puts(«Введите группу:»); scanf("%s",zill[1].n_group);
gotoxy(27,7); puts(«Введите подгруппу:»); scanf("%d",zill[1].n_pdgrup);
gotoxy(27,8); puts(«Введите неделю:»); scanf("%d",zill[1].time.n_ned);
gotoxy(27,9); puts(«Введите день недели:»); scanf("%s",zill[1].time.den_ned);
gotoxy(27,10); puts(«Введите время: :»);
gotoxy(41,10); a=getche(); printf("%d",a); b=(ord(a)-48)*10;
gotoxy(42,10); a=getche(); printf("%d",a); b=b+(ord(a)-48);
zill[1].time.watch.fst_time=b;
gotoxy(44,10); a=getche(); printf("%d",a); b=(ord(a)-48)*10;
gotoxy(45,10); a=getche(); printf("%d",a); b=b+(ord(a)-48);
zill[1].time.watch.scd_time=b;
gotoxy(27,12); puts(«Введите предмет:»); scanf("%s",zill[1].predmet);
gotoxy(27,13); puts(«Введите фамилию преподавателя:»); scanf("%s",zill[1].fio_teacher);
gotoxy(27,14); puts(«Введите аудиторию:»); scanf("%s",zill[1].n_audit);
u2=pred;
u2->a=(struct spisok *)malloc(sizeof(struct spisok));
u2=u2->a;
u2->zip[1]=zill[1];
u2->a=NULL;
pred=u2;
}
kolzap=kolzap+1;
}
//---------------------------------------------------------------------------------
void delzap()
{
int h,x,y,p;
char c,key,a;
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textcolor(WHITE);
window(1,1,80,23);
if (kolzap==0)
{
gotoxy(27,6);
puts(«Записей нет!»);
getche();
exit(0);
}
gotoxy(27,6); puts(«Введите группу:»); scanf("%s",zill[1].n_group);
gotoxy(27,7); puts(«Введите подгруппу:»); scanf("%d",zill[1].n_pdgrup);
gotoxy(27,8); puts(«Введите неделю:»); scanf("%d",zill[1].time.n_ned);
gotoxy(27,9); puts(«Введите день недели:»); scanf("%s",zill[1].time.den_ned);
gotoxy(27,10); puts("Введитевремя: :");
gotoxy(41,10); a=getche();printf("%d",a);b=(ord(a)-48)*10;
gotoxy(42,10); a=getche();printf("%d",a);b=b+(ord(a)-48);
zill[1].time.watch.fst_time=b;
gotoxy(44,10); a=getche();printf("%d",a);b=(ord(a)-48)*10;
gotoxy(45,10); a=getche();printf("%d",a);b=b+(ord(a)-48);
zill[1].time.watch.scd_time=b;
gotoxy(27,12); puts(«Введите предмет:»); scanf("%s",zill[1].predmet);
gotoxy(27,13); puts(«Введите фамилию преподавателя:»); scanf("%s",zill[1].fio_teacher);
gotoxy(27,14); puts(«Введите аудиторию:»); scanf("%s",zill[1].n_audit);
u2=u1;
pred2=u2;
p=0;
while ((u2!=NULL)&&(p==0))
{
if ((u2->zip[1].n_group==zill[1].n_group)&&(u2->zip[1].n_pdgrup==zill[1].n_pdgrup)&&
(u2->zip[1].time.n_ned==zill[1].time.n_ned)&&(u2->zip[1].time.den_ned==zill[1].time.den_ned)&&
(u2->zip[1].time.watch.fst_time==zill[1].time.watch.fst_time)&&(u2->zip[1].time.watch.scd_time==zill[1].time.watch.scd_time)&&
(u2->zip[1].predmet==zill[1].predmet)&&(u2->zip[1].fio_teacher==zill[1].fio_teacher)&&
(u2->zip[1].n_audit==zill[1].n_audit))
{
p=1;
gotoxy(10,20);
puts(«Вы хотели бы изменить или удалить запись?(y-изменить/n-удалить):»);
c=getche();
switch (c)
{
case 'y':{
clrscr();
gotoxy(10,2); puts(«Для изменения нажмите клавишу Y, далее-клавишу N: „);
x=wherex();
y=wherey();
gotoxy(10,4); puts(“Не забывайте переключать раскладку клавиатуры (Англ\Рус)»);
gotoxy(15,6); printf(«Группа:%s»,zill[1].n_group);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{ продолжение
--PAGE_BREAK--
gotoxy(15,6);
puts(«Группа: „);
gotoxy(22,6);
scanf(“%s»,u2->zip[1].n_group);
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,7);
printf(«Подгруппа:%s»,zill[1].n_pdgrup);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{
gotoxy(15,7);
puts(«Подгруппа: „);
gotoxy(25,7);
scanf(“%d»,&u2->zip[1].n_pdgrup);
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,8);
printf(«Неделя:%d»,zill[1].time.n_ned);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{
gotoxy(15,8);
puts(«Неделя: „);
gotoxy(22,8);
scanf(“%d»,&u2->zip[1].time.n_ned);
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,9);
printf(«День недели:%s»,zill[1].time.den_ned);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{
gotoxy(15,9);
puts("Деньнедели: ");
gotoxy(27,9);
scanf("%s",u2->zip[1].time.den_ned);
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,10);
if (zill[1].time.watch.scd_time
else printf(«Время:%d»,zill[1].time.watch.fst_time,":%d",zill[1].time.watch.scd_time);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{
gotoxy(15,10);
puts(«Время:: „);
gotoxy(21,10); a=getche();printf(“%d»,a); b=(ord(a)-48)*10;
gotoxy(22,10); a=getche();printf("%d",a); b=b+(ord(a)-48);
u2->zip[1].time.watch.fst_time=b;
gotoxy(24,10); a=getche(); printf("%d",a); b=(ord(a)-48)*10;
gotoxy(25,10); a=getche(); printf("%d",a); b=b+(ord(a)-48);
u2->zip[1].time.watch.scd_time=b;
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,11);
printf(«Предмет:%s»,zill[1].predmet);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{
gotoxy(15,11);
puts(«Предмет: „);
gotoxy(23,11);
scanf(“%s»,u2->zip[1].predmet);
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,12);
printf(«Фамилия преподавателя:%S»,zill[1].fio_teacher);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н'))
{
gotoxy(15,12);
puts(«Фамилия преподователя: „);
gotoxy(37,12);
scanf(“%s»,u2->zip[1].fio_teacher);
}
gotoxy(x-1,y);
puts(" ");
gotoxy(15,13);
printf(«Аудитория:%s»,zill[1].n_audit);
gotoxy(x,y);
key=getche();
if ((key=='y')||(key=='н')||(key=='Y')||(key=='Н')) продолжение
--PAGE_BREAK--
{
gotoxy(15,13);
puts(«Аудитория: „);
gotoxy(25,13);
scanf(“%s»,u2->zip[1].n_audit);
}
}
case 'n':
{
if (kolzap==1)
{
free(u2);
u1=NULL;
u2=NULL;
kolzap=kolzap-1;
exit(0);
}
if (kolzap!=1)
{
h=1;u2=u1;
while (u2!=NULL)
{
if ((u2->zip[1].n_group==zill[1].n_group)&&(u2->zip[1].n_pdgrup==zill[1].n_pdgrup)&&(u2->zip[1].time.n_ned==zill[1].time.n_ned)&&(u2->zip[1].time.den_ned==zill[1].time.den_ned)&&
(u2->zip[1].time.watch.fst_time==zill[1].time.watch.fst_time)&&(u2->zip[1].time.watch.scd_time==zill[1].time.watch.scd_time)&&(u2->zip[1].predmet==zill[1].predmet)&&(u2->zip[1].fio_teacher==zill[1].fio_teacher)&&
(u2->zip[1].n_audit==zill[1].n_audit))
{
sled=u2->a;
free(u2);
if (h==1)
{
u1=sled;
kolzap=kolzap-1;
exit(0);
}
if (sled==NULL)
{
pred2->a=NULL;
pred=pred2;
kolzap=kolzap-1;
exit(0);
}
pred2->a=sled;
kolzap=kolzap-1;
exit(0);
}
pred2=u2;
h=h+1;
u2=u2->a;
}
}
}
}
}
u2=u2->a;
}
if (p==0)
{
gotoxy(27,15);
puts(«Такой записи нет!»);
getche();
exit(0);
}
}
//---------------------------------------------------------------------------------
void outzap()
{
int h,time_zip,time_zip_end,time_zill,x_up,p;
char chose;
textbackground(BLACK);
window(1,1,80,23);
clrscr();
textcolor(WHITE);
window(27,5,50,20);
if (kolzap==0)
{
puts(«Записей нет!»);
getche();
exit(0);
}
window(1,1,80,23);gotoxy(10,3);
gotoxy(27,6); puts(«Введите группу:»); scanf("%s",zill[1].n_group);
gotoxy(27,7); puts(«Введите подгруппу:»); scanf("%d",zill[1].n_pdgrup);
gotoxy(27,8); puts(«Введите неделю:»); scanf("%d",zill[1].time.n_ned);
gotoxy(27,9); puts(«Введите день недели:»); scanf("%s",zill[1].time.den_ned);
gotoxy(20,10); puts(«Вывести расписание на день или по времени(y/n)»);
chose=getche();
switch (chose)
{
case 'y':
{
u2=u1;
clrscr();
x_up=5;
p=0;
while (u2!=NULL)
{
if ((u2->zip[1].n_group==zill[1].n_group)&&(u2->zip[1].n_pdgrup==zill[1].n_pdgrup)&&
(u2->zip[1].time.n_ned==zill[1].time.n_ned)&&(u2->zip[1].time.den_ned==zill[1].time.den_ned)) продолжение
--PAGE_BREAK--
{
gotoxy(20,x_up);
if (u2->zip[1].time.watch.scd_timezip[1].time.watch.fst_time,":0",u2->zip[1].time.watch.scd_time);
else printf("%d",u2->zip[1].time.watch.fst_time,":",u2->zip[1].time.watch.scd_time);
gotoxy(27,x_up); printf("%s",u2->zip[1].predmet);
gotoxy(39,x_up); printf("%s",u2->zip[1].n_audit);
x_up=x_up+1;
p=1;
}
u2=u2->a;
}
if (p==0)
{
gotoxy(20,6);
puts(«Возможно группа задана неверно или у нее нет пар.»);
}
scanf("%d",&a);
getche();
exit(0);
}
case 'n':
{
gotoxy(20,10);puts(" ");
gotoxy(27,10);puts(«Введите время: :»);
gotoxy(41,10);a=getche();printf("%d",a);b=(ord(a)-48)*10;
gotoxy(42,10);a=getche();printf("%d",a);b=b+(ord(a)-48);
zill[1].time.watch.fst_time=b;
gotoxy(44,10);a=getche();printf("%d",a);b=(ord(a)-48)*10;
gotoxy(45,10);a=getche();printf("%d",a);b=b+(ord(a)-48);
zill[1].time.watch.scd_time=b;
u2=u1;h=1;
time_zill=zill[1].time.watch.fst_time*60;
time_zill=time_zill+zill[1].time.watch.scd_time;
while (u2!=NULL)
{
if ((u2->zip[1].n_group==zill[1].n_group)&&(u2->zip[1].n_pdgrup==zill[1].n_pdgrup)&&
(u2->zip[1].time.n_ned==zill[1].time.n_ned)&&(u2->zip[1].time.den_ned==zill[1].time.den_ned))
{
time_zip=u2->zip[1].time.watch.fst_time*60;
time_zip=time_zip+u2->zip[1].time.watch.scd_time;
time_zip_end=time_zip+90;
if ((time_zill>=time_zip)&&(time_zill
{
gotoxy(27,12); printf(«Предмет:%s»,u2->zip[1].predmet);
gotoxy(27,13); printf(«Фамилия преподователя:%s»,u2->zip[1].fio_teacher);
gotoxy(27,14); printf(«Аудитория:%s»,u2->zip[1].n_audit);
scanf("%d",&a);
getche();
exit(0);
}
}
u2=u2->a;
}
gotoxy(20,14);
puts(«Вероятно у группы нет пары в это время»);
scanf("%d",a);
getche();
}
}
}
//-----------------------запись записи в файл------------------------------
void outdone()
{
f=fopen(filename,«wb»);
u2=u1;
while (u2!=NULL)
{
fwrite(u2->zip,sizeof u2->zip,1,f);
u1=u2->a;
free(u2);
u2=u1;
}
fclose(f);
}
//-------------------------------------------------------------------------------
void main()
{
move_line(3,menudiag,open,newfile,quit2,quit2,d);
}
4. Литература
1. Березин Б.И., Березин С.Б. Б48 Начальный курс С и С++. – М.: ДИАЛОГ-МИФИ, 2000.-288 с.
2. Франка П. Ф83 С++: учебный курс — СПб: ЗАО ”Издательство ”Питер”, 1999. – 528 с.: ил.