程序的新增功能使程序不再感到“将就”
第一次实验指南——逆向软件设计与开发
学号:1832410 班级:19级软工2班 姓名:赵凯悦
题目:关于网上购书系统的功能扩展(c++)
一、 系统环境:
Windows xp以上版本,电脑
二、 设计内容:
程序一共定义五个类,继承关系如图所示
首先是主菜单的主函数,以及一些相关的功能:会员登录,书记信息查看,购书,管理员。又在这些主菜单上进行相对应的子菜单的函数。
主函数如下:
int main()
{
int k;
num_layfolk=num_member=num_honoured_guest=num_book=0;
read_book();
read_buyer();
cout<<"欢迎使用网上购书系统"<<endl;
cout<<"****************************"<<endl;
while(1)
{
menu();
cin>>k;
cout<<endl;
switch(k)
{
case 1: options_1();break; //会员登录
case 2: options_2();break; //显示所有书籍信息及库存
case 3: options_3();break; //购物车
case 4: options_4();break; //管理员登录
case 0: options_0();cout<<"************欢迎下次光临************";return 0; //退出
}
}
return 0;
}
在这几个函数中添加了一些我自己的想法,比如用户的注册,用户信息的排查以及管理系统。
原函数代码本来是这样的:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#define LL long long
using namespace std;
class buyer{
protected:
string name;
LL buyerID;
string password;
string address;
double pay;
public:
buyer();
buyer(string n,LL b,string pas,string a,double p);
string getbuyname();
string getaddress();
string getpassword();
double getpay();
LL getid();
virtual void display()=0;
virtual void setpay(double=0)=0;
};
class Member:public buyer{
int leaguer_grade;
public:
Member():buyer(){leaguer_grade=0;}
Member(string n,LL b,string pas,string a,double p,int l):buyer(n,b,pas,a,p){leaguer_grade=l;}
void display();
int getleaguer_grade(){return leaguer_grade;}
void setpay(double p);
};
class Honoured_guest:public buyer{
double discount_rate;
public:
Honoured_guest():buyer(){discount_rate=0;}
Honoured_guest(string n,LL b,string pas,string a,double p,double r):buyer(n,b,pas,a,p){discount_rate=r;}
void display();
double getdiscount_rate(){return discount_rate;}
void setpay(double p);
};
class Layfolk:public buyer{
public:
Layfolk():buyer(){}
Layfolk(string n,LL b,string pas,string a,double p):buyer(n,b,pas,a,p)
{ }
void display();
void setpay(double p);
};
buyer::buyer()
{
name="";
buyerID=0;
address="";
pay=0;
}
buyer::buyer(string n,LL b,string pas,string a,double p)
{
name=n;
buyerID=b;
password=pas;
address=a;
pay=p;
}
double buyer::getpay()
{return pay;}
string buyer::getaddress()
{return address;}
string buyer::getpassword()
{return password;}
string buyer::getbuyname()
{return name;}
LL buyer::getid()
{return buyerID;}
void Member::display()
{
cout<<"购书人名字:"<<name<<"\n";
cout<<"购书人编号:"<<buyerID<<"\n";
cout<<"购书人为会员,级别:"<<leaguer_grade<<"\n";
cout<<"地址:"<<address<<"\n";
}
void Member::setpay(double p)
{
if(leaguer_grade==1)
pay=.95*p+pay;
else if(leaguer_grade==2)
pay=.90*p+pay;
else if(leaguer_grade==3)
pay=.85*p+pay;
else if(leaguer_grade==4)
pay=.8*p+pay;
else if(leaguer_grade==5)
pay=.7*p+pay;
else
cout<<"级别错误!";
}
void Honoured_guest::display()
{
cout<<"购书人名字:"<<name<<"\n";
cout<<"购书人编号:"<<buyerID<<"\n";
cout<<"购书人为贵宾!折扣率:"<<discount_rate*100<<"%\n";
cout<<"地址:"<<address<<"\n\n";
}
void Honoured_guest::setpay(double p)
{
pay=pay+(1-discount_rate)*p;
}
void Layfolk::display()
{
cout<<"购书人名字:"<<name<<"\n";
cout<<"购书人编号:"<<buyerID<<"\n";
cout<<"购书人为普通用户:"<<"\n";
cout<<"地址:"<<address<<"\n";
}
void Layfolk::setpay(double p)
{
pay=pay+p;
}
class book{
protected:
string book_ID;
string book_name;
string author;
string publishing;
double price;
public:
book();
book(string b_id,string b_n,string au,string pu,double pr);
void display();
string getbook_ID();
string getbook_name();
string getauthor();
string getpublishing();
double getprice();
};
book::book(string b_id,string b_n,string au,string pu,double pr)
{book_ID=b_id;
book_name=b_n;
author=au;
publishing=pu;
price=pr;
}
book::book()
{
book_ID="";
book_name="";
author="";
publishing="";
price=0;
}
void book::display()
{
cout<<"书号:"<<book_ID<<endl;
cout<<"书名:"<<book_name<<endl;
cout<<"作者:"<<author<<endl;
cout<<"出版社:"<<publishing<<endl;
cout<<"定价:"<<price<<endl;
cout<<endl;
}
string book::getbook_ID()
{
return book_ID;
}
string book::getbook_name()
{
return book_name;
}
string book::getauthor()
{
return author;
}
string book::getpublishing()
{
return publishing;
}
double book::getprice()
{
return price;
}
//--一些变量的定义-------------------------------------------------------------
int num_layfolk; //普通用户的数量
int num_member; //会员用户的数量
int num_honoured_guest; //贵宾用户的数量
int num_book; //图书数量
int flag; //标记是否登录和用户类型
double turnover; //总营业额
book goods[1000]; //储存图书信息
Layfolk lf[100]; //储存普通用户的信息
Layfolk p1; //当前为普通用户登录
Member mb[100]; //储存会员用户的信息
Member p2; //当前为会员用户登录
Honoured_guest hg[100]; //储存贵宾用户的信息
Honoured_guest p3; //当前为贵宾用户登录
//-----图书信息的保存与读取-----------------------------------------------------
void write_book() //图书信息的保存
{
int k; //因为string类型初始内存是4,但是实际上string类型可以拓展内存
string temp; //所以 sizeof(book)=24 是无法实现文件的存储
FILE *fp; //这里是把string内字符串所占内存算出来,然后将所占内存数和字符串保存
fp=fopen("C:\\Users\\ASUS\\Desktop\\c++程序\\网上购书 赵凯悦\\图书信息.txt","wb");
fwrite(&turnover,sizeof(double),1,fp); //保存营业额
fwrite(&num_book,sizeof(int),1,fp); //保存图书数量 fwrite(&a,b,c,d) a是要存的东西,b是内存,c是数量,d是文件指针
for(int i=0;i<num_book;i++)
{
temp=goods[i].getbook_ID(); //将图书编号存在temp
k=temp.size()+1; //求出图书编号占多少内存
fwrite(&k,sizeof(int),1,fp); //保存所占内存数
fwrite(temp.data(),k,1,fp); //保存字符串 这里用temp.data()是把string转化成字符数组 直接用string这个出现了乱码
temp=goods[i].getbook_name();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
temp=goods[i].getauthor();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
temp=goods[i].getpublishing();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
double f=goods[i].getprice();
fwrite(&f,sizeof(double),1,fp); //double类型直接sizeof(double)就可以求出所占内存数
}
fclose(fp);
}
void read_book() //图书信息的读取
{
int k;
char temp[100]; //读取的话和保存对应起来
string b_ID;
string b_name;
string author;
string publishing;
double price;
FILE *fp;
fp=fopen("C:\\Users\\ASUS\\Desktop\\c++程序\\网上购书 赵凯悦\\图书信息.txt","rb");
fread(&turnover,sizeof(double),1,fp); //先把营业额读出
fread(&num_book,sizeof(int),1,fp); //然后是图书数量
for(int i=0;i<num_book;i++)
{
fread(&k,sizeof(int),1,fp); //接着读出图书编号所占内存数
fread(&temp,k,1,fp); //temp是一个字符数组,读取相应内存的字符
b_ID=temp; //将temp转换成string
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
b_name=temp;
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
author=temp;
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
publishing=temp;
fread(&price,sizeof(double),1,fp); //double类型是直接存直接读的,不需要读取内存数什么的
goods[i]=book(b_ID,b_name,author,publishing,price);
}
fclose(fp);
}
//----用户信息的保存与读取----------------------------------------------------------------
void read_buyer() //用户信息的读取
{
int k; //原理和上面的一样
char temp[100]; //因为有三种用户类型,这里分成三段读取
string name;
LL buyerID;
double r;
string password;
string address;
FILE *fp;
fp=fopen("C:\\Users\\ASUS\\Desktop\\c++程序\\网上购书 赵凯悦\\用户信息.txt","rb");
fread(&num_layfolk,sizeof(int),1,fp);
for(int i=0;i<num_layfolk;i++)
{
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
name=temp;
fread(&buyerID,sizeof(LL),1,fp);
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
password=temp;
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
address=temp;
lf[i]=Layfolk(name,buyerID,password,address,0);
}
fread(&num_member,sizeof(int),1,fp);
for(int i=0;i<num_member;i++)
{
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
name=temp;
fread(&buyerID,sizeof(LL),1,fp);
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
password=temp;
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
address=temp;
fread(&k,sizeof(int),1,fp);
mb[i]=Member(name,buyerID,password,address,0,k);
}
fread(&num_honoured_guest,sizeof(int),1,fp);
for(int i=0;i<num_honoured_guest;i++)
{
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
name=temp;
fread(&buyerID,sizeof(LL),1,fp);
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
password=temp;
fread(&k,sizeof(int),1,fp);
fread(&temp,k,1,fp);
address=temp;
fread(&r,sizeof(double),1,fp);
hg[i]=Honoured_guest(name,buyerID,password,address,0,r);
}
fclose(fp);
}
void write_buyer() //用户信息的保存
{
int k; //原理和上面相同
LL p;
double x;
string temp;
FILE *fp;
fp=fopen("C:\\Users\\ASUS\\Desktop\\c++程序\\网上购书 赵凯悦\\用户信息.txt","wb");
fwrite(&num_layfolk,sizeof(int),1,fp);
for(int i=0;i<num_layfolk;i++)
{
temp=lf[i].getbuyname();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
p=lf[i].getid();
fwrite(&p,sizeof(LL),1,fp);
temp=lf[i].getpassword();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
temp=lf[i].getaddress();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
}
fwrite(&num_member,sizeof(int),1,fp);
for(int i=0;i<num_member;i++)
{
temp=mb[i].getbuyname();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
p=mb[i].getid();
fwrite(&p,sizeof(LL),1,fp);
temp=mb[i].getpassword();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
temp=mb[i].getaddress();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
k=mb[i].getleaguer_grade();
fwrite(&k,sizeof(int),1,fp);
}
fwrite(&num_honoured_guest,sizeof(int),1,fp);
for(int i=0;i<num_honoured_guest;i++)
{
temp=hg[i].getbuyname();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
p=hg[i].getid();
fwrite(&p,sizeof(LL),1,fp);
temp=hg[i].getpassword();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
temp=hg[i].getaddress();
k=temp.size()+1;
fwrite(&k,sizeof(int),1,fp);
fwrite(temp.data(),k,1,fp);
x=hg[i].getdiscount_rate();
fwrite(&x,sizeof(double),1,fp);
}
fclose(fp);
}
//---主菜单界面-----------------------------------------------------------------------------
void menu()
{
cout<<"=============欢迎进入网上购书系统============="<<endl;
cout<<"1.会员登录"<<endl;
cout<<"2.显示所有书籍信息及库存"<<endl;
cout<<"3.购物车"<<endl;
cout<<"0.退出"<<endl<<endl;
cout<<"请输入:";
}
//---会员登录子菜单-----------------------------------------------------------------------
int find_1(LL id) //在普通用户中查找用户账号
{
int i;
for(i=0;i<num_layfolk;i++)
{
if(lf[i].getid()==id) return i; //查找到后返回i;
}
return -1; //查找不到返回-1;
}
int find_2(LL id)//在会员用户中查找用户账号
{
int i;
for(i=0;i<num_member;i++)
{
if(mb[i].getid()==id) return i;
}
return -1;
}
int find_3(LL id)//在贵宾用户中查找账户
{
int i;
for(i=0;i<num_honoured_guest;i++)
{
if(hg[i].getid()==id) return i;
}
return -1;
}
void options_1_1();
void options_1()
{
LL id;
int k;
string password;
flag=0; //标记先为未登录
cout<<"请输入账号:";
cin>> id;
k=find_1(id); //普通用户类型中查找
if(k!=-1)
{
flag=1; //查找到后,将标记设置为1,即为普通用户
p1=lf[k]; //p1被赋值当前账号信息
}
k=find_2(id); //以下原理相同
if(!flag&&k!=-1)
{
flag=2;
p2=mb[k];
}
k=find_3(id);
if(!flag&&k!=-1)
{
flag=2;
p3=hg[k];
}
if(!flag) {options_1_1();return;}
cout<<"请输入密码:";
cin>>password;
switch(flag)
{
case 1:if(p1.getpassword()!=password) flag=0;break;
case 2:if(p2.getpassword()!=password) flag=0;break;
case 3:if(p3.getpassword()!=password) flag=0;break;
}
if(flag) cout<<"登录成功!\n";
else cout<<"密码错误!\n";
cout<<endl;
}
void options_1_1() //账号信息不存在的情况下
{
int k;
LL id;
string name;
string password;
string address;
cout<<"账号不存在!\n1.注册账号\n2.重新输入账号\n3.回到主菜单"<<endl;
cout<<"请输入:";
cin>>k;
cout<<endl;
if(k==3) return;
if(k==1)
{
cout<<"请输入用户姓名:";
cin>>name;
cout<<"请输入用户账号:";
cin>>id;
cout<<"请输入密码:";
cin>>password;
cout<<"请输入收货地址:";
cin>>address;
cout<<"注册类型:\n1.普通用户\n2.会员用户\n3.贵宾用户\n";
cout<<"请输入:";
cin>>k;
cout<<endl;
double r;
switch(k)
{
case 1:lf[num_layfolk++]=Layfolk(name,id,password,address,0);break;
case 2:cout<<"请输入会员等级:";cin>>k;mb[num_member++]=Member(name,id,password,address,0,k);break;
case 3:cout<<"请输入贵宾折扣率:";cin>>r;hg[num_honoured_guest++]=Honoured_guest(name,id,password,address,0,r);break;
}
cout<<"注册成功!"<<endl;
}
else options_1();
}
//---图书信息的显示------------------------------------------------------------------------------
void options_2()
{
for(int i=0;i<num_book;i++)
{
goods[i].display();
}
cout<<endl;
}
//------购物车子菜单------------------------------------------------------------------------
int num_buy; //记录购物车里的数量
book buy[100]; //存储购物车里的图书信息
void options_3_1();
void options_3_2();
void options_3_3();
void options_3()
{
int k;
if(!flag) //如果用户还未登录的话就无法进入购物车
{
cout<<"用户还未登录!\n"<<endl;
return;
}
cout<<"1.选购图书\n2.显示购书清单\n3.结算\n4.返回主菜单"<<endl;
cout<<"请输入:";
cin>>k;
cout<<endl;
switch(k)
{
case 1: options_3_1();break;
case 2: options_3_2();break;
case 3: options_3_3();break;
case 4: return;
}
}
void find_book(string p) //通过书名或书号来找书
{
for(int i=0;i<num_book;i++)
{
if(goods[i].getbook_ID()==p||goods[i].getbook_name()==p) buy[num_buy++]=goods[i];
}
}
void options_3_1() //选购图书
{
string p;
cout<<"请输入书号或书名:";
cin>>p;
cout<<endl;
find_book(p);
options_3();
}
void options_3_2() //显示购书清单
{
if(!num_buy) //没有书时,显示空
{
cout<<"空\n"<<endl;
options_3();
return;
}
switch(flag) //显示购书者的信息
{
case 1: p1.display();break;
case 2: p2.display();break;
case 3: p3.display();break;
}
cout<<"*****购书清单**********************"<<endl;
for(int i=0;i<num_buy;i++) buy[i].display(); //显示图书信息
cout<<endl;
options_3();
}
void options_3_3() //结算
{
double sum=0; //三种类型用户,三种结算方式
for(int i=0;i<num_buy;i++) sum+=buy[i].getprice();
if(flag==1)
{
p1.setpay(sum);
cout<<p1.getbuyname()<<"用户本次消费一共"<<p1.getpay()<<"元\n"<<endl;
turnover+=p1.getpay();
return;
}
if(flag==2)
{
p2.setpay(sum);
cout<<p2.getbuyname()<<"用户原价"<<sum<<"元"<<",因为您是会员,所以现价为"<<p2.getpay()<<"元\n"<<endl;
turnover+=p2.getpay();
return;
}
if(flag==3)
{
p3.setpay(sum);
cout<<p3.getbuyname()<<"用户原价"<<sum<<"元"<<",因为您是贵宾,所以现价为"<<p3.getpay()<<"元\n"<<endl;
turnover+=p3.getpay();
return;
}
}
void options_0() //对用户信息和图书信息进行保存
{
write_buyer();
write_book();
}
//-------------------------------------------------------------------------------------------------
int main()
{
int k;
num_layfolk=num_member=num_honoured_guest=num_book=0;
read_book();
read_buyer();
cout<<"欢迎使用网上购书系统"<<endl;
cout<<"****************************"<<endl;
while(1)
{
menu();
cin>>k;
cout<<endl;
switch(k)
{
case 1: options_1();break; //会员登录
case 2: options_2();break; //显示所有书籍信息及库存
case 3: options_3();break; //购物车
case 0: options_0();cout<<"************欢迎下次光临************";return 0; //退出
}
}
return 0;
}
三、 测试内容及结果:
在运行中用户的信息和图书的信息被保存在了“.txt”的文档中,这样子读取和保存信息更方便,也更加明显。
文本信息的内容主要有:
有点乱码了,不好意思。。。
测试的内容即运行的结果如下:
- 先显示的是主菜单的页面:
分别有四个选项:(1)会员登录;(2)显示书籍信息;(3)显示购物车
在会员登录中,我又设置了三种样子的用户,分别是:普通用户;会员用户(会员用户又包含等级制);贵宾用户。在登录中我也加入了我自己的一些想法:设置了账号注册这个功能,这样子更加的真实并且人性化
下面是书籍的信息显示:
后面就是购书的操作了
购书操作里面有三个选项,选购图书;显示清单和结算。
上图也展示了两个功能,最后一个结算就会根据用户的会员等级制度来进行相应的折扣
返回主页,输入0,退出即运行结束
四、 改进功能
在我做的一些小的改动后我觉得光是只有在用户登录的时候增加个几个“密码错误”、“注册登录”“登陆成功”这几个小小的改进不是一些非常大的改动,突发奇想,我想到了一个图书馆的后台管理系统,增加了一个管理员的功能界面。
管理员系统的代码如下:
//----管理员-----------------------------------------------------------------------
void options_4_1();
void options_4_2();
void options_4()
{
int k;
string id,password;
cout<<"请输入管理员账号:";
cin>>id;
cout<<"请输入密码:";
cin>>password;
while(id=="zzz"&&password=="zzz") //管理员的账号密码
{
cout<<"1.添加库存\n2.查看营业信息\n3.返回主菜单"<<endl;
cout<<"请输入:";
cin>>k;
cout<<endl;
switch(k)
{
case 1: options_4_1();break;
case 2: options_4_2();break;
case 3: return;
}
}
}
void options_4_1() //添加库存
{
string book_ID;
string book_name;
string author;
string publishing;
double price;
cout<<"请输入书号:";
cin>>book_ID;
cout<<"请输入书名:";
cin>>book_name;
cout<<"请输入作者:";
cin>>author;
cout<<"请输入出版社:";
cin>>publishing;
cout<<"请输入价格:";
cin>>price;
cout<<endl;
goods[num_book++]=book(book_ID,book_name,author,publishing,price);
return;
}
void options_4_2() //查看营业信息
{
cout<<"当前已有"<<num_layfolk+num_member+num_honoured_guest<<"位用户"<<endl;
cout<<"普通用户"<<num_layfolk<<"位"<<endl;
cout<<"会员用户"<<num_member<<"位"<<endl;
cout<<"贵宾用户"<<num_honoured_guest<<"位"<<endl;
cout<<"总营业额为"<<turnover<<"元\n"<<endl;
return;
}
//-----退出程序--------------------------------------------------------------------------------------
- 这个管理员大的系统我加进去了不少的子功能,在相对于之前的相比就更加的丰富了这个购书系统。
- 给管理员设置了登录界面,只有有权限的人员才可以进入,管理员的账号密码也直接设置到代码中。
3.管理员系统加入了添加图书和保存的功能
4.管理员有一个一天的营业额统计功能
运行结果如下:
- 管理员登录
2.图书库存的添加
3.再显示一下书籍信息及库存
4.同样,文本文档的信息也会被添加上
5.查看营业信息功能
6.返回,退出,运行结束
五、 思考感悟
这个是我在大一下学期里面做的一份c++的大作业——购书系统,当时只是按照老师的要求去完成了,并没有在这一大作业上有细入的研究和思考,通过这次的作业,我将我一年前的作业翻出来,我发现我的功能少之又少,在加了个别的登录注册功能后还是觉得这是一个比较“将就”的作业,在我们又上了一个学年的课后,再看这份作业就显得很“苍凉”,所以我一直想的加一个比较大的功能,再添加几个子功能。一番研究后我觉得还是我们经常做的后台管理系统比较简单但又不失格调。利用这个机会,我将这个购书系统又完善了一下,我感到每一次的重新来看,都会多多少少加一些我们自己的想法,使我们的代码长了一倍,功能多了一点,用户操作方便了一点。时代不也就是这样与时俱进的吗?温故而知新,一次次的比较更改才能一次次的走向成功。