C语言数据结构

您所在的位置:网站首页 数据结构图书管理系统说明书怎么做的 C语言数据结构

C语言数据结构

2024-07-01 21:45| 来源: 网络整理| 查看: 265

实现图书管理系统功能:基本要求如下:

 

代码+QQ:3125841747

 https://docs.qq.com/doc/p/71239d69a76f56cf1521717ae6b22c27cf876f10

需要咨询、源码、定做、QQ扫码加:

 

 

管理图书信息化管理,使用对象为普通用户、管理员。实现对用户(普通用户、管理员)的账号管理、图书上新、图书查询、图书下架、图书信息修改等的功能。

用户信息导入:用户名、账号、密码、账号类型 图书信息导入:编号、书名、作者、出版商、出版日期、价格、库存 帐号登陆:登录成功调用对应函数、登陆失败错误处理 用户信息管理:

管理员:新增用户、删除用户、修改用户账号信息

用户:修改密码

书信息管理:

管理员:图书上架、图书下架、图书搜索、图书信息修改、图书列表浏览

用户:图书查询

 

具体分析如下:

程序功能图:

 

 

程序流程图:

 

运行操作 用户可以自行编译 main.c 文件,也可以直接运行可执行程序 main.exe。 帐号信息、图书信息均以明文存放分别存放在:userinfo.txt、bookinfo.txt。

 

代码分析:代码运行环境为:code blocks 或dev c++

数据导入

将以文件形式保存的用户信息、图书信息读入到内存中。这里采取的基于结构体的动态链表,存储导入的信息。加载信息完成后,输出字符画以及欢迎语。

帐号登录

为确保用户正确填写帐号密码信息,显示提示信息:“请输入用户名和密码或帐号和密码”。这里有两种情况:登录成功、登录失败(含输入信息错误)。当登录成功时,进入对应用户类型的操作界面。登录失败,则给出提示:“输入信息错误,退出请按0,再次输入按1”,以询问用户是否再次尝试登录。登录失败的异常处理,使用 while 循环,直到用户选择退出程序。和密码”。这里有两种情况:登录成功、登录失败(含输入信息错误)。当登录成功时,进入对应用户类型的操作界面。登录失败,则给出提示:“输入信息错误,退出请按0,再次输入按1”,以询问用户是否再次尝试登录。登录失败的异常处理,使用 while 循环,直到用户选择退出程序。

用户在看到提示信息输入用户信息之后,将获取到的信息传入密码校验函数,基于密码校验函数返回值,判断登录成功状态。查询登录用户结构体内的用户类型 type 的值,以此判断进入的用户操作界面。

管理员入口

输出操作选项类别:用户管理、图书信息管理、注销。获取管理员操作选项后,使用 switch 进入对应功能函数。进入对应的功能函数后,显示此选项下提供的功能。用户管理选项功能:添加账号、删除账号、输出已有账号、重置用户密码、返回上一层菜单。图书信息管理选项功能:新书上架、输出图书信息、查询、旧书下架、修改图书信息、返回上一层菜单。

用户管理 添加账号

进入函数后,首先以重新加载用户信息的方式,寻找到用户信息的链表的链尾内存地址。为确保用户正确填写新增用户信息,显示提示信息:“请依次输入用户名、账号、密码和类别,输入#表示输入结束”,以及给出示例模版:“输入示例:张三1 111111 用户”。

删除帐号

为确保用户正确填写删除用户信息,显示提示信息:“请输入待删除的读者用户名或账号信息”。获取到帐号信息后,进行校验帐号存在性,如果不存在,则输出错误提示:“查无读者信息,无法删除”。存在则进项该用户信息堆块脱链,并释放,完成后输出提示信息:“读者信息已删除”。结束操作后,将新的链表保存到文件中。

输出已有帐号

显示输出帐号功能菜单,用 switch 实现选择功能。while 循环输出直到链尾,其中加入判断条件 type 值,从而实现分别输出管理员、普通用户帐号信息。

重置用户密码

为确保用户正确填写删除用户信息,显示提示信息:“请输入待删除的读者用户名或账号信息”。获取到帐号信息后,遍历链表进行校验帐号存在性,如果不存在,则输出错误提示:“未找到对应的用户名或账号”。存在则进项该用户信息进行覆写,完成后输出提示信息:“已重置用户密码”。结束操作后,将新的链表保存到文件中。

图书管理 新书上架

进入函数后,首先以重新加载书籍信息的方式,寻找到数据信息的链表的链尾内存地址。为确保用户正确填写新增数据信息,显示提示信息:“请依次输入图书编号、书名、作者、出版社、类别、出版年月日、价格、库存,输入-1表示输入结束”,以及给出示例模版:“输入示例:201501 西游记 吴承恩 中华 名著 19580624 56 59”。使用 while 循环录入信息,直到用户结束输入。结束录入后,将新的链表保存到文件中。

输出图书信息

判断链表指针的 next 值,确定是否有图书信息存在链表中。

查询

显示输出查询功能菜单,用 switch 实现选择功能。遍历链表中的书名或作者名寻找书籍,并输出。当没有对应书籍信息时,输出错误提示:"该书信息不存在”。

旧书下架

显示输出查询功能菜单,用 switch 实现选择功能。遍历链表中的书名或编号寻找书籍,若存在则将该堆块脱链并释放,并输出修改后的新链表,保存链表到文件中;不存在给出错误提示信息:“该图书信息不存在”。

修改图书信息

为确保用户正确填写新增数据信息,显示提示信息:“请输入要修改图书的编号:”。获取编号后,先判断链表是否存在图书信息,然后开始遍历链表,若图书不存在,输出错误提示信息:“图书信息不存在”,若找到图书信息,则输出提示:“该图书的信息已查询到,信息如下”并输出修改书籍原始数据。修改书籍信息采取逐项询问、判断后确定修改信息。遍历询问全部信息后,输出修改后的图书信息。

用户入口 更换密码

为确保用户正确填写新增数据信息,显示提示信息:“请输入您的用户名或账号:”。获取到用户名或帐号后,进入到 while 循环。首先验证帐号的存在性,若帐号不存在,则显示错误提示信息:“账号信息不存在”;帐号存在则要求输入修改帐号的密码,并显示提示:“请输入您原来的密码”。获取密码之后,与当前堆块的 password 比对,正确则给出开始修改密码的提示:“输入您的新密码”,对堆块的 password覆写完成后,输出成功修改提示:“密码修改成功”。密码校验错误则询问是否再次验证:“密码错误,重新输入请按1, 退出请按2”,直到用户选择退出才返回上一级菜单。

查询图书信息

用户与管理员使用相同的查询图书函数。

详细设计

该程序中:共自定义2个结构体,25个函数;共使用4个全局变量。

main函数:

在主函数 main 中,按照图示顺序依次调用函数。欢迎语部分结构简单,因此直接集成在 main 中,不单独自定义子函数。帐号密码输入部分,利用 printf 给予用户操作提示,使用 scanf 收集用户的输入值保存到变量 id、password 中,传到到login 函数中进行密码校验等操作。当密码错误时,在 login 函数内部对错误进行处理。显示错误提示信息:“输入信息错误,退出请按0,再次输入按1”,询问用户是否重新输入帐号密码。

注销帐号,则程序流回到欢迎语,开启新一轮循环。

 

运行效果展示:(功能太多,不一 一展示!需要代码仔细看截图!)

管理员登录:(登录的账号密码均从文件中读取)

 

 

添加或删除读者用户:

 

显示用户或管理员:

 

 

查询所有图书:

 

添加图书:

  

删除图书:

 

账号注销:

  

代码实现:

//声明全局函数 void load(book_pointer book_head,student_pointer student_head);//将文件中的信息加载到链表中 void login(student_pointer k,char str1[],char str2[]);//检验账号信息函数 int compare(char k[],char m[], char n[], char str[], char password[]);//密码校验 void librarian(book_pointer book_head, student_pointer student_head);//管理员入口函数 void user_management_system(student_pointer student_head);//用户管理函数 void reader(book_pointer book_head, student_pointer student_head);//普通读者函数 void change(student_pointer student_head);//修改用户密码 void adduser(student_pointer student_head);//新增用户 void deleteuser(student_pointer student_head);//删除用户 void print(student_pointer student_head);//显示读者信息入口函数 void printuser(student_pointer student_head);//输出用户信息 void printadmin(student_pointer student_head);//输出管理员信息 void save(student_pointer student_head);//保存用户信息 void password(student_pointer student_head);//读者更改密码 void book_management_system(book_pointer book_head);//图书信息管理函数 void newbook(book_pointer book_head);//添加图书信息 void Save(book_pointer book_head);//将图书馆信息导入文件中 void Output(book_pointer book_head);//输出图书信息 void oldbook(book_pointer book_head);//旧书下架 void titledelete(book_pointer book_head);//按书名删除书籍 void iddelete(book_pointer book_head);//按编号删除书籍 void search(book_pointer book_head);//查询图书信息 void titlesearch(book_pointer book_head);//书名查找 void authorsearch(book_pointer book_head);//作者名查找 void modify(book_pointer book_head);//图书信息修改 void login(student_pointer k,char id[],char password[]) { while(k) { b=0;//复位帐号登录状态 b=compare(k->name,k->id,k->password,id,password); if(b==1) { if(strcmp(k->type,"管理员")==0) { librarian(book_head, student_head);//图书管理员函数 } if(strcmp(k->type,"用户")==0) { reader(book_head, student_head);//普通用户函数 } break;//直接跳出循环,实现帐号注销 } k=k->next; } int b1;//用于记录是否重新输入状态码 while(b!=1)//是否注销帐号状态码 { printf("输入信息错误,退出请按0,再次输入按1:\n"); scanf("%d",&b1); if(b1==1)//重新输入 { printf("请重新输入信息:\n"); printf("用户名或账号:"); scanf("%s",id);//id是字符串,即本身就是指针 printf("密码:"); scanf("%s",password); k=student_head;//重置指针 while(k) { b=0; b=compare(k->name,k->id,k->password,id,password); if(b==1)//重新输入 { if(strcmp(k->type,"管理员")==0) { librarian(book_head, student_head);//管理员函数 } if(strcmp(k->type,"用户")==0) { reader(book_head, student_head);//普通读者函数 } break;//实现帐号注销 } k=k->next; } } else if (b1==0)//退出 { exit(0); } else//异常处理 { printf("选择选项不存在\n\n"); } } } int compare(char k[],char m[], char n[], char str[], char password[]) { if((strcmp(str,k)==0||strcmp(str,m)==0)&&(strcmp(password,n)==0)) { printf("输入信息正确,即将进入系统\n\n"); return 1; } return 0; } void librarian(book_pointer book_head, student_pointer student_head)//图书管理员函数 { do{ printf("******************************************\n"); printf("* 1:用户管理 *\n"); printf("* 2:图书信息管理 *\n"); printf("* 3:注销 *\n"); printf("******************************************\n\n"); printf("请输入你要进行的项目选项\n"); scanf("%d", &select); switch(select) { case 1: user_management_system(student_head);//用户管理函数 break; case 2: book_management_system(book_head);//图书信息管理函数 break; case 3: printf("\n\n"); break; default: printf("输入选项不存在!\n\n"); }}while(select!=3); } void user_management_system(student_pointer student_head)//用户管理函数 { do{ printf("************************************\n"); printf("* 1:添加账号 *\n"); printf("* 2:删除账号 *\n"); printf("* 3:输出已有账号 *\n"); printf("* 4:重置用户密码 *\n"); printf("* 5:返回 *\n"); printf("************************************\n\n"); printf("请输入你要进行的项目选项\n"); scanf("%d", &select); switch(select) { case 1: adduser(student_head);//添加账号 break; case 2: deleteuser(student_head);//删除账号 break; case 3: print(student_head);//输出已有账号 break; case 4: change(student_head);//重置用户密码 break; case 5: printf("\n\n"); break; default: printf("输入选项不存在!\n"); }}while(select!=5); } void adduser(student_pointer student_head) { student_pointer p1,p2=student_head; char name[10]; char id[10];//char id[10]; char password[8];//char password[8]; char type[10]; FILE *fp; //以重新load用户信息方式找到链表末尾 //这种方式浪费内存空间 if((fp=fopen("userinfo.txt","r+"))==NULL) { printf("File Open Error!\n"); exit(0); } while(fscanf(fp,"%s %s %s %s",name,id,password,type)!=EOF) { p1=(student_pointer)malloc(sizeof(student)); strcpy(p1->name,name); strcpy(p1->id,id); strcpy(p1->password,password); strcpy(p1->type,type); p2->next=p1; p2=p1;//最后两个指针指向最后一个堆块 } printf("请依次输入用户名、账号、密码和类别,输入#表示输入结束\n"); printf("输入示例:张三 1 111111 用户\n"); while(scanf("%s",&name)!=EOF&&strcmp(name,"#")!=0) { p1=(student_pointer)malloc(sizeof(student)); scanf("%s",&id); scanf("%s",&password); scanf("%s",&type); strcpy(p1->name,name); strcpy(p1->id,id); strcpy(p1->password,password); strcpy(p1->type,type); p2->next=p1; p2=p1; } p2->next=NULL; printf("已有普通读者用户信息:\n"); printuser(student_head); save(student_head); } void print(student_pointer student_head)//显示已有读者信息 { do{ printf("************************************\n"); printf("* 1:输出管理员账号 *\n"); printf("* 2:输出用户账号 *\n"); printf("* 3:返回 *\n"); printf("************************************\n\n"); printf("请输入你要进行的项目选项\n"); scanf("%d", &select); switch(select) { case 1: printadmin(student_head);//输出管理员信息 break; case 2: printuser(student_head);//输出用户信息 break; case 3: printf("\n\n"); break; default: printf("输入选项不存在!\n"); break; }}while(select!=3); } void printadmin(student_pointer student_head)//输出管理员信息 { student_pointer p=student_head->next; int i=0; while(p) { if(strcmp(p->type,"管理员")==0) { printf("%s %s %s\n",p->name,p->id,p->password); i++; } p=p->next; } if(i==0) printf("没有管理员信息!"); } void printuser(student_pointer student_head)//输出用户信息 { student_pointer p=student_head->next; int i=0; while(p) { if(strcmp(p->type,"用户")==0) { printf("%s %s %s\n",p->name,p->id,p->password); i++; } p=p->next; } if(i==0) { printf("没有用户信息!"); } } void book_management_system(book_pointer book_head)//图书信息管理函数 { do{ printf("**********************************************\n"); printf("* 欢迎进入图书管理员界面 *\n"); printf("* 1:新书上架 *\n"); printf("* 2:输出图书信息 *\n"); printf("* 3:查询 *\n"); printf("* 4:旧书下架 *\n"); printf("* 5:修改图书信息 *\n"); printf("* 6:退出 *\n"); printf("**********************************************\n"); printf(" 请输入你的选择:\n"); scanf("%d",&select); switch(select) { case 1:newbook(book_head);//新书上架 break; case 2:Output(book_head);//图书输出 break; case 3:search(book_head);//图书查找 break; case 4:oldbook(book_head);//旧书下架 break; case 5:modify(book_head);//修改图书信息 break; case 6:printf("\n\n"); break; default: printf("选项不存在!\n"); }}while(select!=6); } void newbook(book_pointer book_head)//添加图书信息 { book_pointer p1,p2=book_head; char name[20],author[20],publisher[20],type[20]; int id,pubtime,price,Num; FILE *fp; if((fp=fopen("bookinfo.txt","r"))==NULL) { printf("File Open Error!\n"); exit(0); } while(fscanf(fp,"%d%s%s%s%s%d%d%d",&id,name,author,publisher,type,&pubtime,&price,&Num)!=EOF) { p1=(book_pointer)malloc(sizeof(book)); p1->id=id; strcpy(p1->name,name); strcpy(p1->author,author); strcpy(p1->publisher,publisher); strcpy(p1->type,type); p1->pubtime=pubtime; p1->price=price; p1->Num=Num; p2->next=p1; p2=p1; } printf("请依次输入图书编号、书名、作者、出版社、类别、出版年月日、价格、库存,输入-1表示输入结束\n"); printf("输入示例:201501 西游记 吴承恩 中华 名著 19580624 56 59\n"); while(scanf("%d",&id),id!=-1) { p1=(book_pointer)malloc(sizeof(book)); scanf("%s%s%s%s%d%d%d",&name,&author,&publisher,&type,&pubtime,&price,&Num); p1->id=id; p1->pubtime=pubtime; p1->price=price; p1->Num=Num; strcpy(p1->name,name); strcpy(p1->author,author); strcpy(p1->publisher,publisher); strcpy(p1->type,type); p2->next=p1; p2=p1; } p2->next=NULL; Save(book_head); printf("现在的图书信息为:\n"); Output(book_head); } void Save(book_pointer book_head)//将图书馆信息导入文件中 { FILE *fp; book_pointer p; if((fp=fopen("bookinfo.txt","w"))==NULL) { printf("File Open Error!\n"); exit(0); } for(p=book_head->next;p;p=p->next) { fprintf(fp,"%d%10s%10s%10s%10s%10d%8d%8d\n",p->id,p->name,p->author,p->publisher,p->type,p->pubtime,p->price,p->Num); } fclose(fp); } void Output(book_pointer book_head)//输出图书信息 { book_pointer p=book_head->next; if(p==NULL) { printf("没有图书信息\n"); } else { printf("编号 书名 作者 出版社 类别 出版年月日 价格 库存\n"); while(p) { printf("%d%8s%10s%8s%8s%10d%4d%8d\n",p->id,p->name,p->author,p->publisher,p->type,p->pubtime,p->price,p->Num); p=p->next; } } } void search(book_pointer book_head)//查询图书信息 { do{ printf("***********************************\n"); printf("* 1:按书名查找 *\n"); printf("* 2:作者名查找 *\n"); printf("* 3:返回 *\n"); printf("***********************************\n\n"); printf(" 请输入你要进行的项目选项\n"); scanf("%d", &select); switch(select) { case 1: titlesearch(book_head);//书名查找 break; case 2: authorsearch(book_head);//作者名查找 break; case 3: printf("\n\n"); break; default:printf("选项不存在\n"); }}while(select!=3); } 常见问题及解决方案 问题:提示“File Open Error!”。

解决方案:检查 main.exe 所在目录下是否存在 userinfo.txt、bookinfo.txt 这两个文件,如果没有请手动新建。

问题:忘记密码怎么找回。

解决方案:打开程序根目录下的 userinfo.txt ,密码以明文保存。

问题:源码 main.c 打开中文乱码。

解决方案:使用 gb2318 编码格式重新打开。

已知缺陷: 管理函数中的添加账号等需要获取链表链尾地址的函数,获取函数方式是重建链表,导致原有堆块未被释放而留存在内存中。如果多次进行操作,可能存在内存溢出风险。 帐号、图书信息以明文形式保存在本地文件中。 普通用户修改密码的功能函数,设计存在逻辑缺陷。假如 A 与 B 密码相同,A 登录后,在使用改密码功能时,输入 B 帐号与密码也能够操作成功。 登录、密码修改函数模块,均为设置尝试次数,可被爆破。 具有删除功能的函数模块,在释放堆块后,未将操作指针归零,或存在 UAF 漏洞。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3