# 基于C语言实现的超市管理系统 # 1 需求分析 超市随着市场经济和现代信息技术的的发展,不可必要的要卷入信息现代化的大潮,如何使用现代化的工具,使企业和经营者个人在最小的投入下获取最大的回报,成为每一个人的梦想。因此,在超市管理中引进现代化的办公软件,就成为时下最好的解决办法。使用软件办公,不仅能使经营者的劳力资本减少,同时能使超市的管理更规范更合理,解决了超市中用于管理进出货以及购买、库存等众多繁琐、工作量巨大从而导致耗费人员过多,超市经营紊乱等众多问题。 ## 1.1 主要功能 - 超级管理员模块:(需帐号登录) - 添加管理员 - 删除管理员 - 管理员模块:(需帐号登录) - 商品信息录入(编号、名称、单价、库存) - 商品信息修改(修改商品的各种信息) - 商品信息查询(根据所输入的商品名字,编码查询库存信息) - 商品信息删除(从商品文件中删除商品信息) - 商品信息排序(按编号,单价,库存3种模式进行排序) - 输出商品全部库存信息 - 删除普通用户功能(管理员有权限删除普通用户帐号) - 普通用户模块:(需帐号登录) - 新用户注册 - 用户登录: - 商品查询 - 商品排序 - 输出商品全部库存信息 - 购买商品(通过用户余额来进行购买) - 充值(通过输入充值卡卡号对用户余额充值) - 修改用户密码 # 1.2 运行环境 - 操作系统:Windows NT/2000/XP/VISTA/WIN7/WIN8/WIN10 - 开发平台:Microsoft Visual Studio 2012 ## 1.3 文件说明 - 程序源代码(超市管理系统.cpp) - 程序运行文件(超市管理系统.exe) - 管理员信息(管理员信息.txt) - 普通用户信息(普通用户信息.txt) - 商品信息(商品信息.txt) # 2 总体方案设计 ## 2.1 设计方案 整个超市管理系统分为3个模块,超级管理员+管理员+普通用户,其中: - 管理员可以实现商品信息的录入,修改,查询等管理操作,同时还拥有对普通用户帐号的管理 - 超级管理员是最高执行者,拥有对管理员帐号的操作权限,可以对管理员帐号进行添加或删除 - 普通用户模块,由于考虑到该程序的真实性,所以实现了普通用户的注册和登录功能,用户要进行购物,必须使用帐号(可自行注册,无须经过管理员),其中普通用户具有商品查询等一部分功能。特色功能是具有帐号余额功能,同时购物可以进行充值功能(输入充值卡卡号,类似于购买充值卡来充值) ## 2.2 主要结构 - 超级管理员模块:(需帐号登录) - 添加管理员 - 删除管理员 - 管理员模块:(需帐号登录) - 商品信息录入(编号、名称、单价、库存) - 商品信息修改(修改商品的各种信息) - 商品信息查询(根据所输入的商品名字,编码查询库存信息) - 商品信息删除(从商品文件中删除商品信息) - 商品信息排序(按编号,单价,库存3种模式进行排序) - 输出商品全部库存信息 - 删除普通用户功能(管理员有权限删除普通用户帐号) - 普通用户模块:(需帐号登录) - 新用户注册 - 用户登录: - 商品查询 - 商品排序 - 输出商品全部库存信息 - 购买商品(通过用户余额来进行购买) - 充值(通过输入充值卡卡号对用户余额充值) - 修改用户密码 ## 2.3 程序功能和流程图 由于本程序模块功能较多,有超级管理员,管理员和普通用户,共3个模式的功能,流程图较大,因此分为3个子图。 **超级管理员模块 ** ![](http://www.writebug.com/myres/static/uploads/2021/10/19/7eeff0e6ed8a6195b1cf44076fd0d3ba.writebug) **管理员模块 ** ![](http://www.writebug.com/myres/static/uploads/2021/10/19/051c5b4ed76e506f7779590dc9b74d14.writebug) **普通用户模块 ** ![](http://www.writebug.com/myres/static/uploads/2021/10/19/05f422d8943bbaa6f4d21581f1a14469.writebug) ## 2.4 数据结构和算法的设计说明 本程序有3个数据结构:管理员,普通用户,商品共3个结构体。其中程序拥有超级管理员、管理员和普通用户共3种身份,运用链表来存储和读取所保存的信息。 ### 2.4.1 结构体类型 一开始选择模块,输入帐号和密码,进行验证,是否正确。正确就进入功能模块。 ```c++ typedef struct custom* cpointer;//结点指针类型 struct custom{ string custom_ID;//帐号 string custom_name;//姓名 string custom_mima;//密码 double money;//账户余额 cpointer next; }; typedef cpointer clklist;//单链表类型,即头指针类型 ``` 其中,管理员、普通用户、商品都是定义结构体,而后进入系统,一开始便定义相对应的链表进行存储和获取已保存的信息。 ### 2.4.2 算法设计 **排序算法** ```c++ for(int i=0;i=i+1;j--){ if(Go.Good[j].Good_IDcustom_ID==ID&&p->custom_mima==mima) return 1; else p=p->next; } cout<<"用户帐号不存在!"<>ID; p=head->next; while(p!=NULL){ if(p->custom_ID==ID) flat=0; p=p->next; } if(flat==0) { cout<<"用户帐号已存在,请重新输入"<>mima; cout<<"请输入用户姓名"<>name; s=new custom; s->custom_ID=ID; s->custom_name=name; s->custom_mima=mima; s->money=0; s->next=head->next;//使用头插法建表 head->next=s; buyernum++;//输入一个用户信息,buyernum自加1 custom_save(head); cout<<"是否继续注册?<继续>请按1 <结束>请按0"<>sign;//while循环判断条件,所以不需要用if } } ``` **custom\_get函数:从文件获取用户信息函数**。先定义一个普通用户结构体类型cpointer对象p,把包含普通用户全部信息的单链表head赋值给p, 而后运用一个for循环,将用户信息从“普通用户信息.txt“全部导入到p链表中,返回给系统。 ```c++ clklist custom_get(clklist &buyer){ cpointer s,p;//s用于存储用户信息,p用于buyer的连接 string numname; string ID,name,mima; double money; buyer->next=NULL; p=buyer; ifstream ifile("C:\\普通用户信息.txt",ios::in); if(!ifile){ cerr<<"用户信息查询出错"<>numname; ifile>>buyernum;//从文件中提取用户个数,用于for循环 for(int i=1;i<=buyernum;i++){ ifile>>ID; ifile>>name; ifile>>mima; ifile>>money; s=new custom; s->custom_ID=ID; s->custom_name=name; s->custom_mima=mima; s->money=money; s->next=p->next; p->next=s; } buyer=p; ifile.close(); return buyer; } ``` **Good\_add函数:商品信息录入函数**。把包含商品信息的链表Goods传入该函数,输入商品编号,if(Good_ender1(Goods,ID)==0)进行检索是否商品已存在,存在就提示重新输入,不存在就继续录入商品信息,导入到Goods链表中,最后运用Good\_save(Goods)保存全部信息到“商品信息.txt”文件中。 ```c++ void Good_add(sqlist &Goods){ string ID,name; double piece; int last,sign,flat=1;//last为商品库存,sign用于判断选择 fstream ifile("C:\\商品信息.txt",ios::in); for(;flat!=0;) { cout<<"请输入商品编号:"; cin>>ID; if(Good_ender1(Goods,ID)==0) { cout<<"请输入商品名称:"; cin>>name; if(Good_ender2(Goods,name)==0) { cout<<"请输入商品单价:"; cin>>piece; cout<<"请输入商品数量:"; cin>>last; Goods.Good[Goodnum].Good_ID=ID; Goods.Good[Goodnum].Good_name=name; Goods.Good[Goodnum].piece=piece; Goods.Good[Goodnum].last=last; Goodnum++;//添加完信息就自加1 Good_save(Goods);//添加完就保存至商品信息.txt cout<<"是否继续录入?<继续>请按1 <结束>请按0"<>sign; if(sign==0) break; } else {cout<<"商品名称已存在!<重新输入>请按1 <结束>请按0"<>flat;} } else {cout<<"商品编号已存在!<重新输入>请按1 <结束>请按0"<>flat;} } } ``` **Good\_change函数:商品信息修改函数**。把包含商品信息的链表Goods传入该函数,考虑到用户可能只记得商品编号或者商品名称,因此编写了2种修改模式(按编号检索修改,还是按名称检索修改)。如果选择按编号检索修改,同样对编号进行检索,如果在Goods链表中找到该商品编号,就运用 sign=Good\_locate1(Goods,ID);定位记录下该商品在文件中的位置,而后输入修改后的商品信息,保存至文件中;按名称检索修改类似。最后修改完后,会提示是否继续修改,如果不继续就返回用户功能界面,执行其他功能。 ```c++ void Good_change(sqlist &Goods){ string ID,name; int sign;//sign用于定位要修改商品的位置 int a,flat=1;//a用于switch for(;flat!=0;){ cout<<"<输入要修改的商品编号>请按1 <输入要修改的商品名称>请按2"<>a; if(a!=1&&a!=2) {cout<<"选择有误,请重新输入"<>ID; if(Good_ender1(Goods,ID)==1) { sign=Good_locate1(Goods,ID); cout<<"商品编号:"<>Goods.Good[sign].Good_ID; cout<<"商品名称:"; cin>>Goods.Good[sign].Good_name; cout<<"商品单价:"; cin>>Goods.Good[sign].piece; cout<<"商品库存:"; cin>>Goods.Good[sign].last; Good_save(Goods);//保存信息 cout<<"修改成功"<请按1 <退出>请按0"<>flat; }//for循环的 } ``` **Good_inquire函数:商品信息查询函数**。把包含商品信息的链表Goods传入该函数,考虑到用户可能只记得商品编号或者商品名称,因此编写了2种查询方式(按编号检索查询,还是按名称检索查询)。如果选择按编号检索查询,同样对编号进行检索,如果在Goods链表中找到该商品编号,就运用 sign=Good\_locate1(Goods,ID);定位记录下该商品在文件中的位置,而后输出该商品信息的全部信息;按名称检索查询类似。最后查询完后,会提示是否继续查询,如果不继续就返回用户功能界面,执行其他功能。 ```c++ void Good_inquire(sqlist &Goods){ string ID,name; int a,sign,flat=1; for(;flat!=0;){ cout<<"<按商品编号查询>请按1 <按商品名称查询>请按2"<>a; if(a!=1&&a!=2) {cout<<"选择有误,请重新输入"<>ID; if(Good_ender1(Goods,ID)==1) { sign=Good_locate1(Goods,ID); cout<<"商品编号:"<请按1 <结束>请按0"<>flat; if(flat==0) break; }//for循环的 } ``` **Good\_delete函数:商品信息删除函数**。把包含商品信息的链表Goods传入该函数,考虑到用户可能只记得商品编号或者商品名称,因此编写了2种删除方式(按编号检索删除,还是按名称检索删除)。如果选择按编号检索删除,同样对编号进行检索,如果在Goods链表中找到该商品编号,就运用 sign=Good\_locate1(Goods,ID);定位记录下该商品在文件中的位置,而后使用for(int i=sign; i\请按1 <输入要删除的商品名称>请按2"<>a; if(a!=1&&a!=2) {cout<<"选择有误,请重新输入"<>ID; if(Good_ender1(Goods,ID)==1){ sign=Good_locate1(Goods,ID); for(int i=sign;i请按1 <结束>请按0"<>sign; if(sign==0) break; }//for循环的 } ``` **Good\_range函数:商品信息排序函数**。把包含商品信息的链表Go传入该函数,选择排序模式(按编号,单价,库存进行排序),运用2层for循环,使用冒泡法进行排序,从尾部向头部进行对比检索,小的放前面,大的放后面,排序完之后就将排序后的商品信息显示给用户;3种模式大致相同。最后排序完后,会提示是否继续执行,如果不继续就返回用户功能界面,执行其他功能。 ```c++ void Good_range(sqlist Go){ Goods p; p.piece=0; p.last=0; int a,flag=0,flat=1; for(;flat!=0;){ cout<<"<按商品编号排序>请按1 <按商品单价排序>请按2 <按库存数量排序>请按3 <退出>请按0"<>a; if(a!=0&&a!=1&&a!=2&&a!=3) {cout<<"选择有误,请重新输入"<=i+1;j--){ if(Go.Good[j].Good_ID请按1 <输入商品名称购买>请按2"<>a; if(a!=1&&a!=2) {cout<<"输入有误,请重新输入"<>ID; if(Good_ender1(Goods,ID)==1) { sign=Good_locate1(Goods,ID); cout<<"请输入购买数量:"; cin>>shu; if(shu<=Goods.Good[sign].last){ if(p->money请按1 <否>请按0"<>flat; if(flat==0) break; if(flat==1) return;} Goods.Good[sign].last=Goods.Good[sign].last-shu; cout<<"购买成功"<money=p->money-Goods.Good[sign].piece*shu;//账户余额减少,扣费成功 custom_save(head); cout<<"账户余额:"<money<请按1 <结束>请按0"<>flat; if(flat==0) break; }//for的 } ``` **custom\_addmoney函数:余额充值函数**。余额是用户帐号中的一个成员,初始为0,用户在购物的时候余额会减少,如果余额不足就无法进行购物,需要进行充值,充值是输入系统给定的充值卡卡号进行充值,这是本系统的一大亮点。把包含用户信息的链表head传入该函数,运用 p=custom\_locate(head,ID);定位是哪个用户的帐号要进行充值,其中,系统设定了2种充值卡“asd500”和“asd1000”分别可以充值500和1000元,这类似与用户购买不同的充值卡给自己的账户进行充值。用户输入充值卡卡号,进行检索是否与系统设定的充值卡卡号相同,如果相同就充值相应的金额;如果不同,就提示“充值卡无效”。最后充值后,用户可以选择继续充值或者返回用户功能界面进行购物等其他操作。 ```c++ void custom_addmoney(clklist &head,string ID){ cpointer p; int sign=1; p=custom_locate(head,ID); string acard,card1="asd500",card2="asd1000"; while(sign!=0){ cout<<"请输入您获得的充值卡卡号:"; cin>>acard;//acard是用户获得的充值卡 if(acard!=card1&&acard!=card2) cout<<"充值卡无效"<money+=500; cout<<"充值成功!"<money<money+=1000; cout<<"充值成功!"<money<请按1 <结束>请按0"<>sign;//while循环判断条件,所以不需要用if } ``` # 3 程序功能测试 一开始进入系统,初次使用会提示文件打开失败,是正常的,不影响功能。由于原本的“管理员信息.txt”“普通用户信息.txt”“商品信息.txt”是空的,当录入信息就不会有提示了。进入身份选择(都要帐号和密码) ![](http://www.writebug.com/myres/static/uploads/2021/10/19/c4c2ba8985e77b4986c71e442ba7818c.writebug) 选择1进入超级管理员,(帐号:asd,密码123),先添加管理员。 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/6a9ddca0365858414f595bb497462730.writebug) 选择1,添加管理员信息(帐号+密码+姓名),添加完后可以选择继续添加或返回 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/c233fc894dd39fba84887e7dcc943157.writebug) 选择2,输入要删除的管理员帐号,直接删除管理员 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/51122b1ca294ae9234aa0256f69849a6.writebug) 添加完管理员后,可返回主菜单,进入管理员模式,输入刚刚添加的管理员帐号+密码,进入管理员模式 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/747730cb4f6801fdf5c491a947061177.writebug) 功能1,进入商品录入功能,输入商品的信息(编号,名称,单价,库存),当录入成功之后,管理员可以选择继续录入或返回(该模块当录入编号和名称和已录入的信息相同会提示出错,重新录入) ![](http://www.writebug.com/myres/static/uploads/2021/10/19/e8d13ebc8de2c2aa43d578587bd8893a.writebug) 功能2,可进行商品修改,有2种模式进行选择,输入商品编号101后,显示“商品信息.txt“文件中的商品信息,而后管理员可以输入修改后的信息 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/1c2cf3bab14dd352ce888c039d5abbe2.writebug) 功能3,可以进行商品信息查询,可以查询到刚刚修改的联想笔记本 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/391f03ccdc0686533afd0c456741077f.writebug) 功能4,可以进行删除已录入的商品信息,例如,删除刚录入的联想笔记本 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/e2349a0627be0d00385943725ec4f12f.writebug) 删除后,进入查询功能查看联想笔记本,不存在,表明删除成功~ ~ ![](http://www.writebug.com/myres/static/uploads/2021/10/19/46be669d7a77767258f1fb8a7e01b142.writebug) 功能5,进行已录入商品信息排序,可选择(编号,单价,库存)进行从小到大排序,编号也是可以的 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/85fd6b619d34939392888de2399a8a9d.writebug) 功能6,输出全部商品信息 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/d3b05bccbf5fabf6615030b925cb7c04.writebug) 功能7,删除普通用户,如果已经有普通用户,只需要输入普通用户的帐号就可以直接删除 进入普通用户模块,如果没有帐号是无法查看和购物的,因此消费者可以自行注册 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/9e540e26d4ae2d0c4a15e5a6e18baf96.writebug) 注册完,就可以登录进入用户模块进行购物了 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/fd83fa5ea8936c0623f2cb39c8228bb6.writebug) 其中,商品查询,排序,库存是和管理员一样的,就不展示了 功能4,购买商品,一开始,由于没充值时,用户余额为0,余额不足,无法购买,用户可以返回,进行充值后购买。如果充值后,余额充足就可以购买了,购买后,余额相应减少 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/0f039d1903fd6b2fe06a69d67fbbaa05.writebug) 这里我先前往充值2000元,后购买如下,主机单价50,购买后余额为1950,扣费成功 ![](http://www.writebug.com/myres/static/uploads/2021/10/19/8ae5f25d94d511ee7f33e656a0aef798.writebug) 功能5,用户可以随时修改自己的账户密码,保护自己的财产 功能6,就是充值了,输入系统给定的充值卡卡号,有(asd500和asd1000) ![](http://www.writebug.com/myres/static/uploads/2021/10/19/88fba27768211a067570e11467298e9f.writebug) 由于刚余额1950,现在输入卡号asd1000,成功充值1000,剩余2950 # 4 总结 这次选择了做“超市管理系统”,在完成基本功能之后,觉得要真正实现成功的超市管理系统,必须要有个人的帐号,因此增加了普通用户注册和帐号模式,同时管理员和超级管理员也都是用帐号+密码进入。普通用户可以自行注册,拥有自己的私人帐号。同时,超市管理系统普通用户在进行购买之后,应该是要有余额的,因此添加了余额成员。拥有余额成员之后,就想到,用户需要购买东西,余额不足就需要进行充值,为了实现真实性,就选定,用户需要输入充值卡卡号进行充值。最终完美实现。 这个系统,是使用链表实现的,由于之前的大作业是使用文件流,不是使用链表,因此这次的大作业就决定说要使用链表来实现。在编程过程中,也发现了很多的bug,最终还是一一解决。感觉自己的编程能力在不断的提高,无论是什么bug都可以自行调试解决。 同时,在思考程序的框架功能时,也逐渐重视用户体验,人机交互。编写大作业,不再只是仅仅满足基本功能,在基本功能上,还添加其余用户体验好的功能(比如帐号登录,充值等等功能),感觉大作业让我学会了很多。