C语言课程设计图书管理系统Word文档格式.docx
《C语言课程设计图书管理系统Word文档格式.docx》由会员分享,可在线阅读,更多相关《C语言课程设计图书管理系统Word文档格式.docx(32页珍藏版)》请在冰点文库上搜索。
![C语言课程设计图书管理系统Word文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/7/040ba4f0-acd6-492a-96bd-c3f80e8da9aa/040ba4f0-acd6-492a-96bd-c3f80e8da9aa1.gif)
5分
程序测试
基本功能20分
扩展功能10分
自述情况10分
答辩情况
30分
成绩评定教师:
1需求分析
经过大一上学期的理论学习,在基础实验的基础上,本学期我们继续开设了C语言程序设计实践课。
课程要求我们对已经学习的基础实验进行整合与衔接处理,并最终形成一个系统性质的规模较大的程序。
本次课程设计要求我们达到能独立完成一个图书管理系统,完成后要求实现的功能有对图书信息的录入、删除、修改,浏览(即输出),按某种方式查询(要求至少一种查询方式),按某种方式排序(要求至少一种排序方式)。
当然,我们可以根据自己的能力对系统进行完善性的拓展,例如自己加入简单的权限处理,统计功能,模糊查询等,甚至可以拓展为图书借阅系统。
通过整个程序的开发过程,最终使我们掌握利用计算机解决实际问题的基本方法,熟悉C语言开发的全过程,提高综合应用C语言的能力、编程和调试能力,为学习计算机和通信专业的后续课程打好专业基础。
2概要设计
(1)图书信息及数据格式
图书信息:
图书信息包括图书编号、图书类别、图书书名、作者、出版社、出版时间、图书价格。
数据格式:
本系统采用单向链表来对图书信息进行各项操作。
其中图书的编号为整型数据,价格为双精度浮点型,其余的类别、书名、作者、出版社与出版时间均为字符串类型
structtushu_node{
intnum;
charleibie[20];
charname[30];
charauthor[20];
charpress[20];
chartime[20];
doubleprice;
structtushu_node*next;
};
一个结点的示意图如下图所示:
num
leibie
name
author
press
time
price
next
(2)程序的整体框架
主菜单
退出
帮助
统计图书数目
按不同方式排序
浏览
按不同方式查询
录入(删除修改)
书名
出版时间
价格
编号
修改
删除
创建
子菜单
(3)模块划分
1、intquanxian();
核查权限的函数
2、intinputchioce();
显示主菜单的函数
3、voidsave();
保存链表为文件的函数覆盖以前的信息
4、voidsave1();
保存链表为文件的函数不覆盖以前的信息只在创建时调用
5、structtushu_node*wjtolb();
从文件中读取数据并建立图书信息的链表的函数
6、intluruxinxi();
录入学生信息的函数
7、structtushu_node*luruxinxi_chuangjian();
创建图书信息的函数
8、structtushu_node*luruxinxi_charu();
插入图书信息的函数
9、structtushu_node*luruxinxi_shanchu();
删除图书信息的函数
10、structtushu_node*luruxinxi_xiugai();
修改图书信息的函数
11、intliulantushu();
浏览图书信息的函数
12、intchaxuntushu();
查询图书信息的函数
13、voidchaxuntushu_num();
按编号查询图书
14、voidchaxuntushu_name();
按书名查询图书
15、voidchaxuntushu_price();
按价格查询图书
16、voidpaixutushu();
为图书排序的函数
17、structtushu_node*paixutushu_price();
为图书按价格排序的函数
18、structtushu_node*paixutushu_time();
为图书按出版时间排序的函数
19、voidsfjx();
写个函数判断是否继续排序中使用
20、inttongjitushu_shumu();
统计图书数目的函数
21、voidshiyongshuoming();
使用说明的函数
3详细设计
程序的主体设计思想是根据结构化程序设计思想分模块进行设计,有一个主函数和多个自定义函数构成。
主函数
对于本程序来说,主函数很简单,就是定义了一个变量chioce用来接受核查用户是否有使用该管理系统的权限的函数quanxian()函数返回的值,若为1(即用户获得了使用权限),则调出显示主菜单的函数进行具体操作
intmain()
{
intchioce;
chioce=quanxian();
核查用户是否有使用该管理系统的权限的函数
if(chioce==1)若取得权限则返回值为1
{
system("
cls"
);
inputchioce();
用来显示主菜单的函数
}
exit(0);
}
权限函数
核查用户权限的函数使用do-while语句来限制用户输入密码的次数仅为三次,并且为了使界面更具亲切感,会在用户输入密码错误时进行提示引起用户注意及提示剩余输入次数。
intquanxian()
intm=1,n=3,flag=0;
charmima[20];
do{
printf("
\n\n你好,欢迎使本图书信息管理系统!
\n"
printf("
\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
【现在进行权限核查】\n--------------------友情提醒:
你共有3次输入密码的机会!
printf("
\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
if(n==2||n==1){printf("
注意:
你已输入错误%d次剩余输入次数:
%d请输入密码:
"
3-n,n);
if(n==3)printf("
剩余输入次数:
n);
scanf("
%s"
mima);
//第一次输入和输错密码后再次输入显示的也卖弄不同
if(strcmp(mima,"
chenbo0916"
)==0)
flag=1;
returnflag;
}
m++;
n--;
}while(strcmp(mima,"
)!
=0&
&
m<
=3);
//限制输入次数在3次之内
\n\n对不起,你连续三次输入密码错误,没有使用该图书管理系统的权限!
exit(0);
显示主菜单的函数
本程序将主菜单单独作为一个函数是为了让用户进入一次系统可以进行多项操作(即为在每次用户完成一个具体的操作后,都会有对是否继续或返回主菜单有相应的询问,让用户在想退出系统时才退出),基本思路是通过函数的嵌套调用来实现多项操作。
这个函数的功能就是显示主菜单并对用户进行的选择调用不同的子菜单函数或进入具体功能
intinputchioce()/*主菜单*/
intmychioce,x=-1;
\n++++++++++++++欢迎你++++++++++++++++++\n\n"
**+++++++++++++主菜单+++++++++++++++++++++**\n"
**1--录入(删除修改)图书信息****2--(按规则)查询图书信息**\n"
**3--浏览图书信息****4--为图书(按规则)排序**\n"
**5--统计图书(数目)****6--帮助**\n"
**0--退出系统******\n"
**++++++++++++++++++++++++++++++++++++++++++++++++++++++++**\n"
\n恭喜你获得使用权限,请你选择:
%d"
&
mychioce);
switch(mychioce)
{
case1:
{luruxinxi();
break;
case2:
{chaxuntushu();
case3:
{liulantushu();
case4:
{paixutushu();
case5:
{tongjitushu_shumu();
printf("
\n\n是否继续操作?
请选择(继续-1/退出-0)"
x);
if(x==1){system("
if(x==0){
\n\n谢谢你的使用!
再见\n"
exit(0);
if(x!
=1&
x!
=0){
system("
printf("
选择有误,默认返回主菜单,请重新选择:
inputchioce();
case6:
{shiyongshuoming();
case0:
{printf("
\n\n谢谢你的使用!
!
再见\n\n"
}
default:
{system("
\n选择有误,请重新选择:
inputchioce();
}break;
}
关于一些录入(删除修改)、查询、排序等子菜单的原理及实现方法与主菜单那类似
创建(插入)函数
算法如下图:
p->
结束输入控制条件Num!
=0
Leibie
Name
Author
Press
Time
Head不为空
Tail->
next=p
Head为空
Head=p
保存为文件
Save()
将链表数据保存为文件的函数
首先打开文件以可读写(也可以只写的方式打开区别在于是否覆盖以前的信息)的方式,p1作为形参来接受实参head,只要不为空,写入p1后,下移一个节点
voidsave1(structtushu_node*p1){/*将链表保存为文件的函数不覆盖前面信息*/
if((fpp=fopen("
1.txt"
"
a"
))==NULL)
打开文件失败!
}
while(p1!
=NULL)
{
fprintf(fpp,"
%d%s%s%s%s%s%lf\n"
p1->
num,p1->
leibie,p1->
name,p1->
author,p1->
press,p1->
time,p1->
price);
p1=p1->
next;
if(fclose(fpp))
关闭文件失败!
从文件中读出数据并创建链表的函数
在调用从文件读取数据创建链表的函数前,先定义head链表指针并赋值为空作为实参。
打开文件后,从文件中读取一组数据赋给已经被动态分配内存的结点指针p
第一次head为空时
P
Head
p1
P1->
第二次以后headhead
p2p1
head
p2p1
删除函数
删除函数执行流程图及算法如下图所示:
Return
Head
调浏览函数浏览全部图书方便看需要删除那一本
Head=NULL
Head!
=NULL
head=head->
Head->
Numm比较
输入需要删除图书编号numm
相等(即删除头结点)
调用读取文件并形成链表的函数
不相等(删除其他结点)
Ptr1=head
Ptr2=head->
具体删除过程
Ptr2!
=NULL(即不是链表结尾循环结束条件)
Ptr2->
next=ptr1->
重新保存覆盖原来文件中数据
While循环相等
Ptr1=ptr2
选择是否继续操作返回主菜单
不相等
Ptr2=ptr1->
Save()函数
重新保存文件
修改函数
修改函数执行流程图如下:
先遍历所有图书信息
方便选择要修改编号
调用文件到链表函数
输出一个显示选择修改具体成分的界面
输入需要修改的图书编号
If(Head!
=Null)
while(p!
=NULL&
num!
=numm)
p=p->
}直到相等
Numm比较
相等
选择具体修改成分
Swith语句
输入新的成分替换原有图书信息的成分
保存至文件
返回主菜单
询问是否继续
是否
浏览遍历函数
重新定义一组变量num、leibie、name、author、press、time、price,将从文件中读取一组数据后赋给这组变量并输出它们,使用while(!
feof(fp)),一直执行上述过程实现遍历浏览全部文件中的图书信息。
浏览完成后,同样有对是否继续其他操作的询问,如果选择继续,则会返回主菜单。
intliulantushu()/*浏览图书信息的函数*/
{intnum;
charleibie[10];
charname[30];
charauthor[20];
charpress[20];
chartime[20];
doubleprice;
intx=-1;
if((fpp=fopen("
r"
打开文件失败!
"
else{
\n\n编号类别书名作者出版社出版时间价格\n"
while(!
feof(fpp)){fscanf(fpp,"
%d%s%s%s%s%s%lf"
num,leibie,name,autho
r,press,time,&
%d%s%s%s%s%s%lf\n",num,leibie,name,author,press,time,price);
{printf("
exit(0);
if(x==1)
{system("
inputchioce();
if(x==0)
=0)
{system("
inputchioce();
统计图书数目的函数
统计函数简单的实现了对图书数目的统计,其实现思路可以看做在浏览函数的基础上去掉一些不必要的输出而是另外加上一个变量n用在while中执行一次循环就n++一次,就能统计出图书的数目了,不再具体叙述。
由于feof()函数本身的原理,如果每次写入一行数据到文件中时最后有换行符号,则会出现n多加一问题或输出时最后一行复制,只要将n减一即为图书实际上的数目。
查询函数
查询函数算法如下图所示:
found=0flag=0
p=head
输入要查询的图书的编号/书名/价格
P
P!
比较P中相应的部分与要查询的是否相等
输出查询到的信息
found=1
相等
P=p->
如果found依然为0,则输出“未找到某图书”
排序函数
排序函数算法叙述如下:
排序函数使用冒泡排序的算法,定义了ij两个变量来控制实现双层循环,for(i=1;
i<
n;
i++)(n为调用统计函数统计的图书总数目)来实现外循环,一次外循环将链表中价格最高的(或出版时间最靠后的)图书移动至链表的最后,具体实现过程(即内循环)如下图所示:
内循环:
初始化状态为
P4P4->
C
B
A
辅助P3p1p2
比较p1与p2的排序项,如p1比p2小,上图所有指针的指针均后移一位
相反,若上图中p1比p2大,则变为
P3P3->
B
P2->
nextp1p2
简单的说———始终是p1与p2比较,其中一个为前一次比较中的的大的一个,另一个向后移动
内循环源程序
p4=(structtushu_node*)malloc(size);
p4->
next=head;
p3=p4;
p1=head;
p2=head->
for(j=0;
j<
n-i;
j++)
if(p2->
price>
p1->
price)
{
p3=p1;
p1=p2;
p2=p2->
}
else
p1->
next=NULL;
p1->
next=p2->
p3->
next=p2;
p2->
next=p1;
p3=p2;
p2=p1->
head=p4->
free(p4);
4调试分析
程序的编写过程中调试时遇到的问题及如何解决:
问题一界面不美观,进入一次系统只能进行一项操作的问题
解决方法通过将主菜单的显示作为一个独立的函数(inputchoice()),结合函数的嵌套调用实现,与清屏函数(system(“cls”))一起,在每次进行完一次具体操作都有以下询问
实现了每次操作完成后,使只显示主菜单可继续进行其他操作
问题二权限系统以前是输入学号后三位(int)进行验证并且只有一次输入机会,一次输入错误就退出系统
解决方法在权限函数中使用字符串变量(char)来作为密码,使用do-while语句来实现对输入次数的控制
问题三录入时以前的思路是想在输入的同时写入文件只有一组数据想存入文件
解决方法将保存文件作为一个独立的函数。
在创建函数中有一组另外的参数来接收用户输入的数据,然后再调用保存函数将数据存入文件
问题四文件的保存与读取问题
解决方法由于系统要求结合文件的知识使用户的数据在一次输入之后即使关闭退出系统后在次进入系统时原有数据依然能继续使用。
并且在对数据进行创建、删除、修改、排序等相关的操作之后要重新保存,所以将将链表保存到文件和从文件读取数据建立链表都重新写作单独的函数,在进行完相关的操作后都调用save()重新保存,在再次进行操作前就先调用wjtolb()函数从文件中读取数据创建链表,实现了对数据更及时的保存与利用
问题五保存数据时覆盖不覆盖原有数据的问题
解决问题由于以前没有注意细节问题导致虽然数据被修改或是删除后保存成功,但数据不覆盖原来的数据从而出现文件中数据重复保存的问题,解决方法很简单,只要将打开文件的方式由可读可写(a)改为只写方式打开(w)就行
问题六 输入时无法结束输入的问题
解决方法 由于在输入时时先输入图书的编号,所以在输入时除了输入第一本图书的信息,
即在输入第一本图书之后在输入时先输入图书的编号,加上一个判断