图书管理系统
一、系统功能
图书管理系统要求实现图书管理的基本功能,包括图书的录入、删除、查找和导入/导出等。图书的属性包括书号、书名、第一作者、版次、出版社、出版年等信息。
功能要求:
1.创建:创建图书管理系统,用逐条输入的方式;
2.显示:分屏显示图书管理系统中的所有记录;
3.插入:向图书管理系统中插入一条记录;
4.删除:删除一条已经存在的记录项;
5.排序:以编号为依据升序排列所有记录项;
6.查找:根据用户输入的属性值查找符合条件的记录项;
7.导入/导出:可以从文件读入已有的图书管理系统,也可将系统中的图书信息导出到文件;
8.反序:以编号为依据将按序排列的记录项反序排列;
9.删除相同记录。
构建如图菜单系统,程序执行过程为:循环显示主菜单,用户在Give your choice:处输入选项,即按照功能列表输入0~10中的任意一个数字,按回车后,执行相应的功能。功能执行完毕,返回菜单。
二、菜单功能
各菜单项功能如下:
(1)Input Records(建立有序表)
从键盘上一次输入一条图书记录(书号、书名、第一作者、版次、出版社、出版年),以“书号”为序建立有序表。插入一条记录后,显示提示信息:确认是否输入下一条记录,如确认,继续输入,否则,退出输入功能。
(2)Display All Records(显示所有结点记录)
按顺序显示表中所有记录,每屏显示10条记录,按<Enter>键继续显示下一屏。
(3)Insert a Record(插入一条结点记录)
在以“书号”为序排列的表中插入一条记录,插入后,表仍有序。输出插入成功的信息。
(4)Delete a Record(按“书号”查找,找到后删除该条结点记录)
输入待删除记录的“书号”,显示提示信息,让用户再次确认是否要删除。确认后,将该“书号”的记录删除。
(5) Sort(排序)
以“书号”为升序排列表中的记录。
(6)Query(查找并显示一个结点记录)
输入“书号”,查找该记录,找到后显示记录信息。
(7)Add Records from a Text File(从文件中添加数据到系统中)
用户可事前建立一个文件data.txt,存放多条待加入的记录。提示输入文件的文件名,然后从该文件中一次性加入多条图书记录。文件data.txt格式如下(可以使用英文或拼音表示中文信息):
注意:该文件中第一行的数字表示待添加的记录数,下面每行为图书记录。
(8)Write to a Text File(将系统中记录写入文件)
将图书管理系统中的全部记录写入文件records.txt,要求文件格式和文件data.txt相同。
(9)Reverse List(将表反序)
将表中的所有结点按“书号”反序存放。
(10)Delete the Same Records(删除相同记录)
删除书名、第一作者、版次、出版社、出版年均相同的记录。
(0)Quit(退出图书管理系统程序)
退出图书管理系统程序。
三、实现要求
1. 数据结构
用结构体数组实现图书信息的记录和管理。每个数组元素为一个结构体变量
在主函数中定义结构体数组Bookinfo books[NUM];用作记录存储,也可采用动态链表实现。
2. 各函数功能
以下函数原型说明中出现的函数为本课程设计的基本要求。请不要更改函数原型。
(1)数据输入
int Input(Bookinfo dictList[],int n);
从键盘输入若干条记录,依次存放到结构体数组dictList中,n为数组原有记录数,函数返回最后的记录数。
(2)输出数据
void Diplay(Bookinfo dictList[],int n);
显示所有图书信息,每10本暂停一次,n为数组元素个数。
(3)插入一条结点记录
int Insert(Bookinfo dictList[],int n, Bookinfo *s);
按书号序插入记录s,返回记录个数。
int Insert_a_record(Bookinfo dictList[],int n);
输入待插入的图书书号、书名、作者、版本号、出版社名、出版年等图书信息,调用Insert函数按书号作有序插入,输出插入成功信息,返回记录个数。
(4)删除一条结点记录
int Delete(Bookinfo dictList[],int n, char *book);
删除书名为book的第一条图书记录,返回数组中的记录数。
int Delete_a_record(Bookinfo dictList[],int n);
输入待删除的书名,经确认后调用Delete函数,同时列出同一书名的所有书目,输入待删除书目的书号,提示是否删除,确认后,输出删除成功与否的信息,返回数组中的记录数。
(5)排序
void Sort_by_ISBN(Bookinfo dictList[],int n);
数组按书号升序排列。
(6)查询数据
int Query(Bookinfo dictList[],int n, char *book);
查找并显示书名为book的所有记录,查找成功返回该书名记录个数,否则返回-1。
void Query_a_record(Bookinfo dictList[], int n);
输入待查找的书名,调用Query函数查找该书的记录,输出查找成功与否的信息和该书名的所有记录。
(7)从文件中整批输入数据
int AddfromText(Bookinfo dictList[],int n, char *filename);
从文件filename添加一批记录到数组中,调用Insert()函数作有序插入,返回添加记录后的新记录数。
(8)将记录写到文件
void WriteText(Bookinfo dictList[],int n,char *filename);
将数组中的记录全部写入文件filename中。
(9)将表反序存放
void Reverse(Bookinfo dictList[]);
按书号反序存放表。
(10)删除雷同记录
int DeleteSame(Bookinfo dictList[], int n);
删除数组中书名、作者、版本号、出版社名、出版年均相同的记录,n为数组原有记录数,函数返回最后的记录数。
(0)退出管理系统
void Quit(Bookinfo dictList[]);
退出系统时,释放动态存储空间。
其他函数
void Display_Main_Menu();
显示主菜单。
实验过程中可以根据需要适当增加函数,以使程序算法更清晰明了。
其中部分函数是我补充添加的(具体看代码标注)。
#include<stdio.h>
#include<windows.h>
#include<math.h>
typedef struct //定义数据类型
{
char ISBN[10]; //书号
char book[30]; //书名
char author[20]; //作者
int edition; //版本号
char press[50]; //出版社名
int year; //年份
}Bookinfo;
int Input(Bookinfo dictList[],int n) // 从键盘输入若干条记录,依次存放到结构体数组dictList中,返回最后的记录数
{
int m,i; //m:要输入的本数,i循环控制量
printf("请输入要输入图书的本数\n");
scanf("%d",&m);
getchar();
printf("\n");
for(i=0;i<m;i++)
{
printf("请输入第%d本:\n",i+1);
printf("书号:");
gets(dictList[n+i].ISBN);
printf("书名:");
gets(dictList[n+i].book);
printf("作者:");
gets(dictList[n+i].author);
printf("版本号:");
scanf("%d",&dictList[n+i].edition);
getchar();
printf("出版社名:");
gets(dictList[n+i].press);
printf("出版年份:");
scanf("%d",&dictList[n+i].year);
getchar();
printf("\n");
}
printf("输入完毕!请继续:");
return (n+m); //返回总的图书本数
}
void Display(Bookinfo dictList[],int n) //显示所有图书信息,每10本暂停一次
{
int i,js=1; //js:计数,统计已经输出的本数
char zt;
printf("\n");
printf("书号 书名 作者 版本号 出版社 出版年份\n");
printf("---------------------------------------------------------------------\n");
printf("\n");
for(i=0;i<n;i++,js++)
{
printf("%-8s",dictList[i].ISBN); //利用格式控制,表示向左对齐8个,默认也是向左对齐
printf("%-15s",dictList[i].book);
printf("%-13s",dictList[i].author);
printf("第%3d版 ",dictList[i].edition);
printf("%-14s",dictList[i].press);
printf("%d\n",dictList[i].year);
if((++js)%20==0) //每输出十本换行
{
printf("\n 任意键,继续输出\n"); //输出了10个之后,暂停+提示
system("pause");
zt=getchar();
}
}
printf("输出完毕!请继续:");
}
int Delete(Bookinfo dictList[],int n,char *book) //删除某一本书
{
int i,j,t;
char del[10],c,*zj; //del删除的目标书号
printf("请选择书号: ");
gets(del);
getchar();
for(i=0;i<n;i++) //通过遍历寻找是否有对应书号的书籍,找到便将其删除
{
for(j=0,zj=book;j<30 && dictList[i].book[j]!='\0';j++,zj++)
{
if(dictList[i].book[j]==*zj) t=1; //找到的时候,令t=1
else {t=0;j=30;}
}
if(t==1) //进入删除功能,将其删除
{
for(j=0;j<10 && dictList[i].ISBN[j]!='\0';j++)
{
if(dictList[i].ISBN[j]==del[j]) t=1;
else {t=0;j=10;}
}
printf("确定删除,请按回车键!");
c=getchar(); //万能getchar,加一个
if(c!='\n') t=0;
if(t==1)
{
for(;i<n-1;i++)
{
dictList[i]=dictList[i+1]; //删除了后将删除后面的往左边挪动一位
}
}
}
}
printf("成功删除");
return n-1;
}
int Delete_a_record(Bookinfo dictList[],int n)
{
int i,t,p;
char sm[30],*book,ch; //sm:书名,待删除书名
printf("请输入待删除书本的名字:");
getchar();
gets(sm);
book=&sm[0];
printf("是否删除?若要删除请按y;否则请按其他键 \n");
scanf("%c",&ch);
getchar();
if(ch=='y')
{
for(i=0;i<n;i++) //这部分是展示要删除的书籍
{
for(p=0;p<30 && dictList[i].book[p]!='\0';p++) //找一遍,找到了就让t为1,展示其信息,并调用删除函数
{
if(dictList[i].book[p]==sm[p]) t=1;
else {t=0;p=30;}
}
if(t==1)
{
printf("书号 书名\n");
printf("____________\n");
printf("%-8s",dictList[i].ISBN);
printf("%-8s\n",dictList[i].book);
}
}
n=Delete(dictList,n,book);
}
else
printf("删除失败! \n");
return n; //返回删除书籍的记录数
}
void Sort_by_ISBN(Bookinfo dictList[],int n) //数组按书号升序排列
{
int i,j,p,bj;
Bookinfo ls;
for(i=0;i<n-1;i++)
{
p=i;
for(j=i+1;j<n;j++)
{
bj=strcmp(dictList[i].ISBN,dictList[j].ISBN); //通过这个判断书号是否相等
if(bj>0) p=j; //当左边的大,则保持原来排序
}
if(p!=i) //当右边的大,则进行替换
{
ls=dictList[i];
dictList[i]=dictList[p];
dictList[p]=ls;
}
}
printf("排序完成\n");
}
void Sort_by_name(Bookinfo dictList[],int n) //数组按书名升序排列,同书号排序的逻辑
{
int i,j,p,bj;
Bookinfo ls;
for(i=0;i<n-1;i++) //同样采用选择比较进行排序
{
p=i;
for(j=i+1;j<n;j++)
{
bj=strcmp(dictList[i].book,dictList[j].book);
if(bj>0) p=j;
}
if(p!=i)
{
ls=dictList[i];
dictList[i]=dictList[p];
dictList[p]=ls;
}
}
printf("排序完成\n");
}
int Insert(Bookinfo dictList[],int n,Bookinfo *s) //有序插入
{
int i,j,p;
for(i=0;i<=n;i++)
{
p=strcmp(dictList[i].book,(*s).book); //将插入数据的放到第i个
if(i=n) //如果插入的在最后,则直接插入
{
dictList[i]=*s;
i=n+1;
j=n+1;
}
if(p>0)
{
for(j=n;j>i;j--) dictList[j]=dictList[j-1]; //如果插入的在中间,则将插入点之后的数据向右挪动一个位置
dictList[i]=*s;
i=n+1;
}
}
return(n+1);
}
int Insert_a_record(Bookinfo dictList[ ],int n) //有序插入
{
Bookinfo mmp,*s;
s=&mmp;
getchar();
printf("书号:");
gets(mmp.ISBN);
printf("书名:");
gets(mmp.book);
printf("作者:");
gets(mmp.author);
printf("版本号:");
scanf("%d",&mmp.edition);
getchar();
printf("出版社名:");
gets(mmp.press);
printf("出版年份:");
scanf("%d",&mmp.year);
getchar();
n=Insert(dictList,n,s);
Sort_by_ISBN(dictList,n);
printf("插入成功");
return n;
}
int Query(Bookinfo dictList[],int n,Bookinfo *book) //查找并显示书名为book的所有记录,查找成功返回该书记录个数,失败则返回0
{
int i,p,t,m=0;
for(i=0;i<n;i++) //利用for循环寻找是否有书名与之对应的
{
for(p=0;p<30 && dictList[i].book[p]!='\0';p++)
{
if(dictList[i].book[p]==(*book).book[p]) t=1;
else {t=0;p=30;}
}
if(t==1) //如果找到了,就将其定为1,并输出相关信息
{
printf("书号 书名 作者 版本号 出版社 出版年\n");
printf("__________________________________________________\n");
printf("%-8s",dictList[i].ISBN);
printf("%-8s",dictList[i].book);
printf("%-8s",dictList[i].author);
printf("第%3d版 ",dictList[i].edition);
printf("%-8s",dictList[i].press);
printf("%d\n",dictList[i].year);
m=m+1;
}
}
return m;
}
void Query_a_record(Bookinfo dictList[],int n) //输入待查书名
{
Bookinfo cz,*czz;
int a,i;
czz=&cz;
printf("请输入要查找的书名:");
getchar();
gets(cz.book);
a=Query(dictList,n,czz);
if(a>0)
printf("找到了%d本名为%s的书!",a,cz.book);
else
printf("没有找到名称为%s的书",cz.book);
}
void WritetoText(Bookinfo dictList[],int n,char *filename) //将记录写到文件里
{
int i;
FILE *fp;
fp=fopen(filename,"w");
if(fp==NULL)
{
printf("不能打开文件\n");
exit(1); //没打开成功就exit
}
fprintf(fp,"%d\n",n);
//fprintf(fp,"书号 书名 作者 版本号 出版社 出版年份\n");
//fprintf(fp,"--------------------------------------------------------------\n");
for(i=0;i<n;i++)
{
fprintf(fp,"%s %s %s %d %s %d",dictList[i].ISBN,dictList[i].book,dictList[i].author,dictList[i].edition,dictList[i].press,dictList[i].year);
printf("\n");
}
printf("成功记录到文件!");
fclose(fp);
}
int AddfromText(Bookinfo dictList[],int n,char *filename) //从文件中导入数据
{
int i;
Bookinfo s;
FILE *p;
system("cls");
p=fopen(filename,"r");
if(p==NULL)
printf("文档打开失败!\n");
else
printf("文档打开!\n");
fscanf(p,"%d",&i);
while(!feof(p)) //与写入数据那一段相对应
{
fscanf(p,"%s %s %s %d %s %d",s.ISBN,s.book,s.author,&s.edition,s.press,&s.year);
n=Insert(dictList,n,&s);
}
fclose(p);
printf("成功输入\n");
fclose(p);
return(n);
}
void Reverse(Bookinfo dictList[],int n) //反序排序,这里只不过把之前的程序改一个符号
{
int i,j,p,bj;
Bookinfo ls;
for(i=0;i<n-1;i++)
{
p=i;
for(j=i+1;j<n;j++)
{
bj=strcmp(dictList[i].ISBN,dictList[j].ISBN);
if(bj<0) p=j; //大于小于号改了,这个是选择排序
}
if(p!=i) //变为小于号,如果右边的小,则与左边的进行替换,用ls作为中间量
{
ls=dictList[i];
dictList[i]=dictList[p];
dictList[p]=ls;
}
}
printf("排序完成\n");
}
void copyBook(Bookinfo *a,Bookinfo b) //这个是给删除同一书的函数服务的函数
{
strcpy(a->author,b.author); //这个是将后面的赋给前面的a
strcpy(a->book,b.book);
a->edition = b.edition;
strcpy(a->ISBN,b.ISBN);
strcpy(a->press,b.press);
a->year = b.year;
}
int SameBook(Bookinfo a, Bookinfo b) //这个是判断是否为重复书籍的函数,删除同书的函数循环调用此函数
{
return !strcmp(a.author, b.author) //如果找到了作者、书名、出版社、出版编号、日期相同的书,则该书为相同书
&& !strcmp(a.book, b.book)
&& (a.edition == b.edition)
&& !strcmp(a.press, b.press)
&& (a.year == b.year);
}
int DeleteSame(Bookinfo dictList[], int n) //删除相同的书籍
{
int i, j;
int newLen = n;
for (i = 0; i < newLen - 1; i++)
{
for (j = i + 1; j < newLen; j++)
{
if (SameBook(dictList[i], dictList[j]))
{
for (int k = j; k < n - 1; k++)
{
dictList[k] = dictList[k + 1]; //向左挪动一个位置
}
--newLen,--j;
}
}
}
printf("已删除相同的书籍数据,返回记录数为: %d", newLen);
return newLen;
}
int menu_select() //我设计的菜单
{
int sn;
system("cls"); //清屏
printf(" The Book Manangement Systemm \n");
printf(" |--------------------------------------------------------------------|\n");
printf(" | Menu |\n");
printf(" |--------------------------------------------------------------------|\n");
printf(" | 1 Input Records |\n");
printf(" | 2 Display All Records |\n");
printf(" | 3 Insert a Record |\n");
printf(" | 4 Delete a Record |\n");
printf(" | 5 Sort |\n");
printf(" | 6 Query |\n");
printf(" | 7 Add Records from a Text File |\n");
printf(" | 8 Write to a Text File |\n");
printf(" | 9 Correct a record |\n");
printf(" | 10 Search author |\n");
printf(" | 11 Reverse |\n");
printf(" | 12 Delete The Same Records |\n");
printf(" | 13 Sort by name |\n");
printf(" | 0 Quit |\n");
printf(" |--------------------------------------------------------------------|\n");
printf(" Please enter your choice(0~13): ");
for(; ;) //用死循环判断用户是否输入的是13的数字,如果输入14则提示错误重输
{
scanf("%d",&sn);
if(sn<0||sn>13)
printf("\n输入错误,重选0~13:");
else
break;
}
return sn;
}
void Correct(Bookinfo dictList[],int n) //显示所有记录,并对其中某一个进行修改
{
char xg[30];
int i,bj,m;
Display(dictList,n);
system("pause");
printf("请输入所要修改图书记录的书号:\n");
scanf("%s",xg);
for(i=0;i<n;i++)
{
bj=strcmp(dictList[i].ISBN,xg);
if(bj==0) break;
}
printf("所要修改对象信息如下:\n");
printf("书号 书名 作者 版本号 出版社 出版年份\n");
printf("--------------------------------------------------------------\n");
printf("%-7s",dictList[i].ISBN);
printf("%-16s",dictList[i].book);
printf("%-8s",dictList[i].author);
printf("第%3d版 ",dictList[i].edition);
printf("%-14s",dictList[i].press);
printf("%d\n",dictList[i].year);
printf("请输入所要修改对内容的序号\n");
printf("1.书号\n2.书名\n3.作者4.版本号\n5.出版社\n6.出版年份\n");
scanf("%d",&m);
switch (m) //建立交互系统,确认要选择的修改部分
{
case 1:
{
printf("书号:");
scanf("%s",dictList[i].ISBN);
break;
}
case 2:
{
printf("书名:");
scanf("%s",dictList[i].book);
break;
}
case 3:
{
printf("作者:");
scanf("%s",dictList[i].author);
break;
}
case 4:
{
printf("版本号:");
scanf("%d",&dictList[i].edition);
getchar();
break;
}
case 5:
{
printf("出版社:");
scanf("%s",dictList[i].press);
break;
}
case 6:
{
printf("出版年份:");
scanf("%d",&dictList[i].year);
getchar();
for(; ;) //用死循环判断用户是否输入的是1到6的数字,如果输入7则提示错误重输
{
scanf("%d",&m);
if(m<1||m>6)
printf("\n输入错误,重选1~6:");
else
break;
}
}
}
}
void search_author(Bookinfo dictList[],int n) //查询作者在该管理系统有多少本书
{
int i,t,p,count=0;
char sm[30],*author;
printf("Input author_name\n");
getchar();
gets(sm);
author=&sm[0];
for(i=0;i<n;i++)
{
for(p=0;p<30 && dictList[i].author[p]!='\0';p++)
{
if(dictList[i].author[p]==sm[p]) t=1;
else {t=0;p=30;}
}
if(t==1)
{
count++;
}
}
printf("The number of books by the author: ");
printf("%d",count);
}
int play() //*符号为打印出的心形图案符号
{
float a,x,y;
for(y=1.5f; y>-1.5f; y-=0.1f)
{
for(x=-1.5f; x<1.5f; x+=0.05f)
{
a = x*x+y*y-1;
char c = a*a*a-x*x*y*y*y<=0.0f?'*':' ';
putchar(c);
}
printf("\n");
}
return 0;
}
int main()
{
system("color B5"); //将菜单变为浅紫色
int n=0;
char i;
Bookinfo dictList[50];
Bookinfo favorites[50];
for(;;)
{
switch(menu_select()) //老师给的交互系统
{
case 1:
{
n=Input(dictList,n);
system("pause");
break;
}
case 2:
{
Display(dictList,n);
system("pause");
break;
}
case 3:
{
n=Insert_a_record(dictList,n);
system("pause");
break;
}
case 4:
{
n=Delete_a_record(dictList,n);
system("pause");
break;
}
case 5:
{
Sort_by_ISBN(dictList,n);
system("pause");
break;
}
case 6:
{
Query_a_record(dictList,n);
system("pause");
break;
}
case 7:
{
char *filename,s[30];
printf("请输入文件名\n");
scanf("%s",s);
filename=s;
n=AddfromText(dictList,n,filename);
system("pause");
break;
}
case 8:
{
char *filename,s[30];
printf("请输入文件名\n");
scanf("%s",s);
filename=s;
WritetoText(dictList,n,filename);
system("pause");
break;
}
case 9:
{
Correct(dictList,n);
system("pause");
break;
}
case 10:
{
search_author(dictList,n);
system("pause");
break;
}
case 11:
{
Reverse(dictList,n);
system("pause");
break;
}
case 12:
{
n = DeleteSame(dictList,n);
system("pause");
break;
}
case 13:
{
Sort_by_name(dictList,n);
system("pause");
break;
}
case 0:
{
play();
printf(" Goodbye!");
printf("\n\n\n");
system("pause");
exit(0);
}
}
}
}