C++大作业——网上购书系统

1.设计题目

网上购书的一般流程是:用户根据自己的需求将所选书籍放入到购书框,选择结束后,输入自己的名字进行结账,系统会自动生成相应订单。
模拟网上购书系统,要求根据不同的顾客,按照不同的计费标准进行收费.根据实际情况,确定了购书人可分为3类:普通人、会员、贵宾。
要求:客户信息、书籍信息、订单信息数据用二进制问文件进行读取。

2.系统环境

硬件:系统类型: 64 位操作系统, 基于 x64 的处理器
软件:操作系统为Windows 10,工作软件为:Dev-c++ 5.11

3.设计内容

3.1问题分析

系统要求实现如下功能:
1.系统后台
1.原有数据:利用二进制文件当作购书系统的数据库,存储书籍信息、用户信息、订单信息。
2.添加信息:在原有数据库的基础上,有新的客户信息需要录入,需要二进制文件的读写操作进行存储和读取数据库内的信息。
2.系统前台
1.购书者查看系统的录入客户信息
2. 购书者添加自己的个人信息
3. 购书者查看系统中所有的书籍信息
4. 购书者根据个人的需求进行选择性购买
5. 购书者结账时输入自己名字进行优惠购买
6. 购书者购买完成后查看自己买的书籍订单

3.2框架及数据设计

​ 1.设计框架

​ 客户需求流程图

利用循环语句及switch语句实现功能模块多次执行,代码如下

void show() {
	int n;
	while (1) {
		menu_show();
		cin >> n;
		switch (n) {
			case (7) : {
				cout << "欢迎下次光临,祝您生活愉快!" << endl;
				return;
			}
			case (1): {
				show_file2();//书本信息显示函数
				break;
			}
			case (2): {
				show_file1();//客户信息显示函数
				break;
			}
			case (3):{
				purchase();//选购书籍 
				break;
			} 
			case(4) :{
				pay();//结算总额 
				break;
			}
			case(5):{
				order_show();//订单显示 
				break;
			} 
				case (6) : {
				explation();//使用说明 
				break;
			}
		}
	}
}

设计主菜单

部分模块设置了回退功能

if(条件)  return;//返回主菜单

个人信息、书籍信息、订单信息等都是由多个基础的数据类型共同组成,因此,使用类进行封装存储。类中的基础数据类型包括浮点型、整形、字符数组、整形数组。在条件允许的情况下,应多使用newdelete函数以节省空间

2.定义宏数据

const int book_idlength=20;//书编号长度 
const int book_10=20;//书名长度
const int book_authorlength=20;//书作者名长度
const int book_publishinglength=20;//书出版社长度 
const int ordermax=10;//购买书籍种类上限 
//以下变量多个函数同时要用,定义为全局变量 
int A[ordermax+1]={0},id=0;//i代表购书号,A[i]代表数量,用此记录已购书籍信息 ,id记录购买者编号 
double sum=0; //已选购书籍总价 
char nam[10];//购买者名字

此处定义的部分宏变量,A[i]数组i代表购书号,A[i]代表数量,用此记录已购书籍信息 ,id记录购买者编号,sum记录本次购书总额,这些数据由于在选购书籍,结算总额时都会用到,分别于俩个不同函数中,因此使用全局变量。

注:鉴于文件中读写问题,以上宏定义数据在系统录入数据后一律不得修改,否则将会产生二进制文件读写问题

3.类的应用

源代码中包含了一个基类buyer,以及基类buyer的3个共有继承派生类,分别是member(会员类)、honoured_guest(贵宾类)、layfolk(普通类)类,派生类的作用是储存不同的顾客信息并收取不同的费用。除此之外,还有bookorder类。

buyer派生类的继承关系图

它们实现的功能如下

buyer类:

保护数据成员(便于派生类成员函数访问)

name[10]//记录购书人姓名
buyerID//记录购书人编号
address[10]//记录购书人地址
pay//记录购书人应付额 

公有成员函数

Buyer() 俩个构造函数
char *getbuyname();char *getaddress();double getpay();int getid();//分别用于获取姓名、地址、应付额、编号

layfolk 类:

公有继承的基础上增加了俩个公有成员函数:

void display1();          //显示函数,输出客户信息
double setpay1(double p);           //计算优惠后购书金额并返回

member

公有继承的基础上增加了一个私有数据

int leaguer_grade;    //表示会员级别

俩个公有成员函数

void display3();    //显示函数,输出客户信息
double setpay3(double p);// //计算优惠后购书金额并返回

honoured_guest

公有继承的基础上增加了一个私有数据

double discount_rate;          //表示折扣率

俩个公有成员函数

void display2();    //显示函数,输出客户信息
double setpay3(double p);// //计算优惠后购书金额并返回

book

私有数据成员:(此处含有常变量数组)

char bookid[book_idlength];//记录书的编号 
char book_name[book_10];// 记录书名 
char author[book_authorlength];// 记录作者 
char publishing[book_publishinglength];// 记录出版社 
double price;// 记录价格 
int buyid;//购书号,便于客户选购书籍,此代码中规定购书号不超过宏定义数据ordermax

公有成员函数:

构造函数:

book(); //用于指针开辟空间且不初始化,比如 book *p=new book();
book(char a[10],char b[10],char c[10],char d[10],double pr,int i);//用于初始化数据

成员函数

void display();  //展示书的具体信息
char* getbook_id();  //获得书的编号
char* getbook_name();//获得书的书名
char* getauthor();//获得书的作者
char* getpublishing();//获得书的出版社
double getprice(); //获得书的价格
int get_buyid();//获得书的购买号

order

私有数据

int orderid;//订单编号,随机函数随机生成
int buyid; // 购书人编号 
char name[10];//购书人名字 
double pay; //应付金额 
int od[ordermax+1];//该数列用于存储书籍信息,下标代表购书号,相应数组元素代表该书的购买数量

公有成员函数

order();//构造函数,用于指针开辟空间且不初始化,比如 order *p=new order()
order(int a,int b,char n[],int m[],double p)//构造函数,初始化数据
char * get_name()//获得购书者名字,便于查询订单信息
void display()//用于输出订单信息

注意事项:

1.以上各个类中的字符数组均不能换成string类,在存入二进制文件时,string型数据存入的是指针,二进制文件是不能存储指针的

2.使用基类虚函数display()会出现bug,因此此处取消使用虚函数display()

4.二进制文件

该系统中共建立了4个二进制文件,分别是“客户信息.dat”,“书籍信息.dat”,“flag.dat”,“order.dat”。引用二进制文件,<fstream>头文件是不可少的,其次,c++中的利用文件流进行读写文件,因此使用时需要定义文件流对象,每次以二进制方式打开文件并检查是否成功打开

3.3读文件信息并输出

对于bookorder俩大类而言,每次存储的信息长度一样,因此每次二进制文件读写指针移动的距离一样,通过简单的循环即可完成读写

下面以book为例(仅显示该部分读文件功能代码)

ifstream i;
		i.open("书籍信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
	if (!i) {
		cout << "书籍信息文件打开失败!" << endl;
		exit(1);
	}
	i.seekg(0, ios::end);
	int filelen;
	filelen = i.tellg();//获取文件长度
	i.seekg(0, ios::beg);//移动指针位置
	while (filelen != i.tellg()){
		book *p=new book();
		i.read((char*)p,sizeof(book));
		p->display();
		delete p;
	}
	i.close();

上述流程为利用seekg函数先将文件指针移动至文件末尾,利用tell()函数获得文件长度,再利用seekg函数将文件指针移动回文件首,然后进行循环读文件,直至文件指针至文件末尾

上述代码流程图如下

上述俩大类读文件方式并不适用于客户信息.dat文件,原因是该二进制问文件存储了不同的三大类:layfolk、member、honoured_guest类,这就导致了第一个问题:每次读文件时,read函数中要求移动的字节数不同,其次,不同的类输出数据信息的函数也不同(他们有着不同的display()函数)

.鉴于此,读取书籍信息.datorder.dat文件的方法不适用于读客户信息.dat文件。于是,flag.dat文件的作用便发挥出来了。我们通过在存储某各类至客户信息.dat文件时,同时存入一个标志字符至flag.dat文件中,这样就形成了一一对应的关系,通过读flag.dat文件中的标志字符来确定什么时候客户信息.dat文件读取结束、每次读客户信息.dat文件时要给read函数多少字节、利用哪个类来获取文件数据。通过flag.dat文件,使得本混乱的客户信息.dat文件变得有序起来

下面我们以字符0标记layfolk类,字符1标记honoured_guest类,字符2标记member

上述过程功能代码如下(void user_show()函数)

ifstream it1, it2;
	it1.open("客户信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
	if (!it1) {
		cout << "客户信息文件打开失败!" << endl;
		exit(1);
	}
	it2.open("flag.dat", ios::binary );
	if (!it2) {
		cout << "标记文件打开失败!";
		exit(1);
	}
	it2.seekg(0, ios::end);
	int filelen;
	filelen = it2.tellg();//获取"flag.dat"文件长度
	it2.seekg(0, ios::beg);
	it1.seekg(0, ios::beg);//移动指针位置
	while (filelen != it2.tellg()) {
		char c;
		it2.read(&c, sizeof('1'));//字符和字符串占用的空间不一样 
		if (c == '0') {
			layfolk *p1 = new layfolk();
			it1.read((char *)p1, sizeof(layfolk));///输出的格式不对称,'\t'时
			p1->display1();
			delete p1;
		}
		if (c == '1') {
			honoured_guest *p2 = new honoured_guest();
			it1.read((char *)p2, sizeof(honoured_guest));
			p2->display2();
			delete p2;
		}
		if (c == '2') {
			member *p3 = new member();
			it1.read((char*)p3, sizeof(member));
			p3->display3();
			delete p3;
		}
	}
	it1.close();
	it2.close();

上述代码存于源代码的void user_show()函数中,user_show函数用于显示客户信息。

上述代码流程图如下

3.4写文件

对于书籍信息.datorder.dat文件写的具体过程和读差不多,只是稍加注意的是,文件打开的方式为追加(ios::app),这样每次的订单信息才能写入文件,否则文件中只存储了本次购书系统运行产生的数据。

格式如下(以order.dat文件存入订单信息为例,源代码中不进行书籍信息添加)

ofstream o;
	o.open("order.dat",ios::binary|ios::app);
	if(!o){
		cout<<"order.dat文件打开失败!"<<endl;
		return;
	} 
	order *p=new order(order_number,id,nam,A,sum);
	if(sum!=0)
    o.write((char *)p,sizeof(order));
    o.close();
    delete p;

对于客户信息.dat,具体过程和读类似,只是在添加客户信息时,文件要以追加方式写文件,同时存入标志字符至flag.dat文件。
功能代码如下(购书者添加新的信息功能处代码):

    ofstream ot1, ot2;
	ot1.open("客户信息.dat",  ios::binary | ios::app );
	ot2.open("flag.dat", ios::binary | ios::app);
	cout << "添加普通用户输入0,贵宾输入1,会员输入2" << endl;
		cout << "请输入你的选择:" << endl;
		char ch = getchar();
		ot2.write(&ch, sizeof('1'));
		char name[10], address[10];
		double a, b, c;
		if (ch == '0') {
			cout << "请依次输入姓名、编号、地址、费用" << endl;
			cin >> name >> a >> address >> c;
			layfolk *p=new layfolk(name, a, address, c);
			ot1.write((char *)p, sizeof(layfolk));
			delete p;
		}
			if (c == '1') {
			honoured_guest *p2 = new honoured_guest();
			it1.read((char *)p2, sizeof(honoured_guest));
			p2->display2();
			delete p2;
		}
		if (c == '2') {
			member *p3 = new member();
			it1.read((char*)p3, sizeof(member));
			p3->display3();
			delete p3;
		}
ot1.close();
ot2.close();

其他的一些功能在读写四个文件的基础上都可以建立,在本程序中,通过名字查找用户折扣率并计算最终应付款,查找用户历史订单,通过购书号进行购买书籍,都是通过读文件来实现相应功能的

下面以通过名字查找历史订单的代码为例

ifstream i;
	i.open("order.dat",ios::binary);
	if(!i){
		cout<<"order.dat文件打开失败!"<<endl;
		return;
	}
cout<<"请输入要查询人的姓名:"<<endl;
	char nam[10];
	cin>>nam;
	i.seekg(0,ios::beg);
	if(filelen!=0){
	while(i.tellg()!=filelen){
		i.read((char *)p,sizeof(order));
		if(strcmp(p->get_name(),nam)==0)
		p->display();
	}}
	else cout<<"暂无订单信息"<<endl;

3.5数据文件

源代码中文件数据代码如下:

此为flag.dat客户信息.dat文件的数据

	layfolk a1("林小茶", 1,  "北京", 0), b("张三", 2,  "上海", 0);
	honoured_guest c("王瑶瑶", 3, 0.6, "上海", 0), d("李四", 4, 0.7, "武汉", 0);
	member  e("赵红艳", 5, 5, "广州", 0), f("王五", 6, 4, "长沙", 0);
	ot1.write((char *)&a1, sizeof(layfolk));
	ot1.write((char *)&b, sizeof(layfolk));  //"客户信息.dat" 数据库 
	ot1.write((char *)&c, sizeof(honoured_guest));       //初始化起始客户信息//原有数据库
	ot1.write((char *)&d, sizeof(honoured_guest));       //一一对应,‘0’对layfolk 
	ot1.write((char *)&e, sizeof(member));               //‘1’对 honoured_guest,‘2’对member 
	ot1.write((char *)&f, sizeof(member));
	char a[6]={'0','0','1','1','2','2'};  //6与文件中数据客户信息数量相对应 
	for(int i=0;i<6;i++)         //标记文件"flag.dat"的数据
	ot1.write((char *)&a[i], sizeof('0'));

此为书籍信息.dat文件的数据

	book a1("7-302-04504-6","C++程序设计","谭浩强","清华",25,1);
	book a2("7-402-03388-9","数据结构","许卓群","北大",20,2);
	book a3("978-7-04-042744-8","高等数学","陈海杰","高等教育",38.1,3);
	o.write((char*)&a1,sizeof(book));       //      原始书籍数据库 
	o.write((char*)&a2,sizeof(book));
	o.write((char*)&a3,sizeof(book));

文件中的原始数据可以按要求更改,原始数据初始化方法为,在第一次运行源代码时(以设备中不存在上述3个文件判断为第一次运行),将上述代码内容不用注释,然后运行相应功能,书籍信息显示,原有客户信息显示俩大功能都运行一次即可完成数据录入,运行一次后退出本次运行,然后将上述代码注释掉(不注释会在每一次运行时都将数据信息再录入一次),这样,文件就完成了初始化。当然,如果已有相应文件可免去上述操作

3.6异常处理

异常处理格式

try{
    被检查语句
    throw 异常
  }	
  catch(异常类型1)
  {
    进行异常处理的语句1
  }
  catch(异常类型2)
  {
    进行异常处理的语句2
  }

流程图

在本程序中,共俩处用到了异常处理,位于功能模块购买书籍、支付总额处。前者处使用是为了避免客户输入的书籍数量为负数,后者使用是防止客户信息未存入就输入名字进行购买导致程序运行错误

书籍数量异常处理代码

cout<<"请输入你要购买的书籍购买号、以及数量:"<<endl;
	while(1){
	try{
	cin>>a[i]>>b[i];
	if(b[i]<=0)  //异常处理 
	 throw b[i];
	 break;
	}
	catch(int i){
		cout<<"数量格式错误,请重新输入!"<<endl;
	}
}

通过循坏保证多次读取,直至读入合法数值。

上述代码中,读入a[i]b[i]俩个元素值后,判断数量b[i]是否大于0,如果小于,则当作异常处理,通过thorw函数抛出并被catch(int)接收,然后执行catch(int)内的语句,提示用户输入有错误,重新输入。

如果大于0,则执行下一条语句break,退出循环,并执行后续语句。对于支付总额功能处异常处理,原理与之类似,注意数据类型换为(char *)

4.测试内容及结果

1.主菜单

2.书籍信息显示

书籍信息.dat”文件内容

3.客户信息显示

flag.dat”文件内容

客户信息.dat”文件内容

输出面板

4.添加客户信息

客户信息.dat文件内容

flag.dat文件内容

5.购买书籍时的返回语句

6.选购书籍

输入非法数量数据(异常处理)

7.结账模块

测试返回程序

文件中不包含的成员(异常处理)

order.dat文件内容

8.订单显示功能

查询本次订单

查询历史订单

查张三的订单时(此时order.dat文件只录入了王五的订单信息)

查王五的订单时

9.使用说明

10.退出系统

5.源代码

img

#include <cstring>
#include <fstream>
#include <iostream>
#include <iomanip>//控制输出格式
#include <ctime>
#include <cstdlib>//生成随机数,制造订单编号(仿真) 
using namespace std;

//const int 10=10;//设置名字长度
//const int 10=10; //地址长度
const int book_idlength = 20; //书编号长度
const int book_10 = 20; //书名长度
const int book_authorlength = 20; //书作者名长度
const int book_publishinglength = 20; //书出版社长度
const int ordermax = 10; //购买书籍种类上限
//以下变量多个函数同时要用,定义为全局变量
int A[ordermax + 1] = {0}, id = 0; //i代表购书号,A[i]代表数量,用此记录已购书籍信息 ,id记录购买者编号
double sum = 0; //已选购书籍总价
char nam[10];//购买者名字
int flag1 = 0;

class buyer {
	protected:
		char name[10];
		int buyerID;
		char address[10];
		double pay;
	public:
		buyer();
		buyer(char n[10], int b, char a[10], double p);
		char *getbuyname();
		char *getaddress();
		double getpay();
		int getid();
		//virtual void display() = 0;
		//virtual void setpay(double = 0) = 0;
};

class member: public buyer { //会员类
		int leaguer_grade;    //会员级别
	public:
		member() {
		}
		member(char n[10], int b, int l, char a[10], double p): buyer(n, b, a, p) {
			leaguer_grade = l;   //构造函数
		}
		void display3();    //显示函数
		double setpay3(double p);
};

class honoured_guest: public buyer {       //贵宾类
		double discount_rate;          //折扣率
	public:
		honoured_guest() {
		}
		honoured_guest(char n[10], int b, double r, char a[10], double p): buyer(n, b, a, p) {
			discount_rate = r;
		}            //构造函数
		void display2();          //显示函数
		double setpay2(double p);          //计算购书金额
};

class layfolk: public buyer {       //普通人类
	public:
		layfolk() {
		}
		layfolk(char n[10], int b,  char a[10], double p): buyer(n, b, a, p) {
			//构造函数
		}
		void display1();          //显示函数
		double setpay1(double p);           //计算购书金额
		/*friend	ostream &operator<<(ostream &cout, layfolk &x) {
			x.display();
			return cout;
		}
		friend	istream &operator>>(istream &cin, layfolk &x) {
			char name[10];
			int buyerID;
			char address[10];
			double pay;
			cin >> name >> buyerID  >> address >> pay;
			strcpy(x.getbuyname,name);
			strcpy(x.address, address);
			x.pay = pay;
			x.buyerID = buyerID;
			return cin;
		}*/
};

buyer::buyer() {        //基类的构造函数
	strcpy(name, " ");
	buyerID = 0;
	strcpy(address, " ");
	pay = 0;
}

buyer::buyer(char n[10], int b, char a[10], double p = 0) { //基类的构造函数
	strcpy(name, n);
	buyerID = b;
	strcpy(address, a);
	pay = p;
}

double buyer::getpay() {    //取购书金额
	return pay;
}

char *buyer::getaddress() {   //取购书人地址
	return address;
}

char *buyer::getbuyname() {   //取购书人名字
	return name;
}

int buyer::getid() {   //取购书人编号
	return buyerID;
}

void member::display3() {   //会员类的显示函数
	cout << "购书人姓名:" << name << '\n' ;
	cout << "购书人编号:" << buyerID << "\t";
	cout << "购书人为会员,级别:" << leaguer_grade << "\t";
	cout << "地址:" << address << "\n\n";
}

double member::setpay3(double p) {   //会员类的计算购书金额
	if (leaguer_grade == 1)   //会员级别为1
		pay = .95 * p + pay;
	else if (leaguer_grade == 2)  //会员级别为2
		pay = .90 * p + pay;
	else if (leaguer_grade == 3)  //会员级别为3
		pay = .85 * p + pay;
	else if (leaguer_grade == 4)  //会员级别为4
		pay = .8 * p + pay;
	else if (leaguer_grade == 5)  //会员级别为5
		pay = .7 * p + pay;
	else
		cout << "级别错误!";
	return pay;
}

void honoured_guest::display2() {        //贵宾类的显示函数
	cout << "购书人姓名:" << name << '\n' ;
	cout << "购书人编号:" << buyerID << "\t";
	cout << "购书人为贵宾!折扣率为:" << discount_rate * 100 << "%\t";
	cout << "地址:" << address << "\n\n";
}

double honoured_guest::setpay2(double p) {   //贵宾类计算购书金额
	pay = pay + (1 - discount_rate) * p;
	return pay;
}

void layfolk::display1() {    //普通类显示函数
	cout << "购书人姓名:" << name << '\n' ;
	cout << "购书人编号:" << buyerID << "\t";
	cout << "购书人为普通人" << "\t";
	cout << "地址:" << address << "\n\n";
}

double layfolk::setpay1(double p) {
	pay = pay + p;
	return pay;
}

class book {
	protected:
		char bookid[book_idlength];//书的编号
		char book_name[book_10];//书名
		char author[book_authorlength];//作者
		char publishing[book_publishinglength];//出版社
		double price;//价格
		int buyid;//购书号
	public:
		book();
		book(char a[10], char b[10], char c[10], char d[10], double pr, int i);
		void display();
		char *getbook_id();
		char *getbook_name();
		char *getauthor();
		char *getpublishing();
		double getprice();
		int get_buyid();
};

book::book() {
	strcpy(bookid, "无输入");
	strcpy(book_name, "无输入");
	strcpy(author, "无输入");
	strcpy(publishing, "无输入");
	price = 0;
}

book::book(char a[10], char b[10], char c[10], char d[10], double pr, int i) {
	strcpy(bookid, a);
	strcpy(book_name, b);
	strcpy(author, c);
	strcpy(publishing, d);
	price = pr;
	buyid = i;
}

void book::display() {
	cout << "书号:" << bookid << "\t";
	cout << "书名:" << book_name << "\n";
	cout << "作者:" << author << "\t";
	cout << "出版社:" << publishing << "\t\t";
	cout << "定价" << setw(5) << price;
	cout << "  购书号为:" << buyid << endl << endl;
}

char *book::getbook_id() {
	return bookid;
}

char *book::getbook_name() {
	return book_name;
}

char *book::getauthor() {
	return author;
}

char *book::getpublishing() {
	return publishing;
}

double book::getprice() {
	return price;
}

int book::get_buyid() {
	return buyid;
}

class order {
	private:
		int orderid;//订单编号
		int buyid; //购书人编号
		char name[10];//购书人名字
		double pay; //应付金额
		int od[ordermax + 1];
	public:
		order() {
		}
		order(int a, int b, char n[], int m[], double p) {
			orderid = a;
			buyid = b;
			strcpy(name, n);
			for (int i = 0; i <= ordermax; i++)
				od[i] = m[i];
			pay = p;
		}
		char *get_name() {
			return name;
		}
		void display() { //考虑运算符重载
			cout << "订单编号为:" << orderid << "\n";
			cout << "购书人姓名:" << name << "\t" << "购书人编号: " << buyid << "\n";
			cout << "所购书籍如下:" << endl;
			ifstream i;
			i.open("书籍信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
			if (!i) {
				cout << "书籍信息文件打开失败!" << endl;
				exit(1);
			}
			i.seekg(0, ios::end);
			int filelen;
			filelen = i.tellg();//获取文件长度
			for (int j = 1; j <= ordermax; j++) {
				i.seekg(0, ios::beg);//移动指针位置
				while (filelen != i.tellg()) {
					book *p = new book();
					i.read((char *)p, sizeof(book));
					if (p->get_buyid() == j && od[j] > 0)
						cout << "书名:" << left << setw(15) << p->getbook_name() << "   数量: " << od[j] << endl;
					delete p;
				}
			}
			i.close();
			cout << "本次消费总额为:  " << pay << endl;
		}
};

void show_file2() { //1.书籍信息显示函数
	cout << "本店所有书籍信息如下:" << endl;
	ofstream o;
	o.open("书籍信息.dat",  ios::binary | ios::app);
	if (!o) {
		cout << "书籍信息文件打开失败!" << endl;
		exit(1);
	}
	/*book a1("7-302-04504-6","C++程序设计","谭浩强","清华",25,1);
	book a2("7-402-03388-9","数据结构","许卓群","北大",20,2);
	book a3("978-7-04-042744-8","高等数学","陈海杰","高等教育",38.1,3);
	o.write((char*)&a1,sizeof(book));       //      原始书籍数据库
	o.write((char*)&a2,sizeof(book));
	o.write((char*)&a3,sizeof(book));*/
	o.close();
	ifstream i;
	i.open("书籍信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
	if (!i) {
		cout << "书籍信息文件打开失败!" << endl;
		exit(1);
	}
	i.seekg(0, ios::end);
	int filelen;
	filelen = i.tellg();//获取文件长度
	i.seekg(0, ios::beg);//移动指针位置
	while (filelen != i.tellg()) {
		book *p = new book();
		i.read((char *)p, sizeof(book));
		p->display();
		delete p;
	}
	i.close();
}

void user_show() { //从"客户信息.dat"中读取客户信息
	ifstream it1, it2;
	it1.open("客户信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
	if (!it1) {
		cout << "客户信息文件打开失败!" << endl;
		exit(1);
	}
	it2.open("flag.dat", ios::binary );
	if (!it2) {
		cout << "标记文件打开失败!";
		exit(1);
	}
	it2.seekg(0, ios::end);
	int filelen;
	filelen = it2.tellg();//获取"flag.dat"文件长度
	it2.seekg(0, ios::beg);
	it1.seekg(0, ios::beg);//移动指针位置
	while (filelen != it2.tellg()) {
		char c;
		it2.read(&c, sizeof('1'));//字符和字符串占用的空间不一样
		if (c == '0') {
			layfolk *p1 = new layfolk();
			it1.read((char *)p1, sizeof(layfolk));///输出的格式不对称,'\t'时
			p1->display1();
			delete p1;
		}
		if (c == '1') {
			honoured_guest *p2 = new honoured_guest();
			it1.read((char *)p2, sizeof(honoured_guest));
			p2->display2();
			delete p2;
		}
		if (c == '2') {
			member *p3 = new member();
			it1.read((char *)p3, sizeof(member));
			p3->display3();
			delete p3;
		}
	}
	it1.close();
	it2.close();
}

void show_file1() { //2.客户信息添加
	cout << "添加客户信息输入1,查看原有客户信息输入2" << endl;
	cout << "请输入你的选择:" << endl;
	int ch;
	cin >> ch;
	getchar();//吃掉回车
	ofstream ot1, ot2;
	ot1.open("客户信息.dat",  ios::binary | ios::app );
	if (!ot1) {
		cout << "客户信息文件打开失败!" << endl;
		exit(1);
	}
	ot2.open("flag.dat", ios::binary | ios::app);
	if (!ot2) {
		cout << "标记文件打开失败!";
		exit(1);
	}
	/*layfolk a1("林小茶", 1,  "北京", 0), b("张三", 2,  "上海", 0);
	honoured_guest c("王瑶瑶", 3, 0.6, "上海", 0), d("李四", 4, 0.7, "武汉", 0);
	member  e("赵红艳", 5, 5, "广州", 0), f("王五", 6, 4, "长沙", 0);
	ot1.write((char *)&a1, sizeof(layfolk));
	ot1.write((char *)&b, sizeof(layfolk));  //"客户信息.dat" 数据库
	ot1.write((char *)&c, sizeof(honoured_guest));       //初始化起始客户信息//原有数据库
	ot1.write((char *)&d, sizeof(honoured_guest));       //一一对应,‘0’对layfolk
	ot1.write((char *)&e, sizeof(member));               //‘1’对 honoured_guest,‘2’对member
	ot1.write((char *)&f, sizeof(member));
	char a[6]={'0','0','1','1','2','2'};  //6与数据库客户信息数量相对应
	for(int i=0;i<6;i++)         //标记文件"flag.dat"数据库
	ot2.write((char *)&a[i], sizeof('0'));*/

	if (ch == 1) {
		//ot2.seekp(0,ios::end);
		cout << "添加普通用户输入0,贵宾输入1,会员输入2" << endl;
		cout << "请输入你的选择:" << endl;
		char ch = getchar();
		ot2.write(&ch, sizeof('1'));
		char name[10], address[10];
		double a, b, c;
		if (ch == '0') {
			cout << "请依次输入姓名、编号、地址、费用" << endl;
			cin >> name >> a >> address >> c;
			layfolk *p = new layfolk(name, a, address, c);
			ot1.write((char *)p, sizeof(layfolk));
			delete p;
		}
		if (ch == '1') {
			cout << "请依次输入姓名、编号、折扣率、地址、费用" << endl;
			cin >> name >> a >> b >> address >> c;
			honoured_guest *p = new honoured_guest(name, a, b, address, c);
			ot1.write((char *)p, sizeof(honoured_guest));
			delete p;
		}
		if (ch == '2') {
			cout << "请依次输入姓名、编号、会员等级、地址、费用" << endl;
			cin >> name >> a >> b >> address >> c;
			member *p = new member(name, a, b, address, c);
			ot1.write((char *)p, sizeof(member));
			delete p;
		}
		cout << "添加客户信息成功!" << endl;
	}
	ot1.close();
	ot2.close();
	user_show();
}

void purchase() { //3.选购函数,主要记录用户购买的书籍信息
	cout << "*******购买须知:先输入所需书籍购买号,再输入相对应数量********" << endl;
	cout << "*******购买请输入1,退出请输入0*******" << endl;
	int flag = 0, i = 0, amax = 0; //进行初始化amax,避免函数调用俩次及以上时出问题
	int a[ordermax] = {0}, b[ordermax] = {0}; 前者记录书的种类、后者记录书的数量,amax记录已添加几种书籍
//a[i]的值为购书号,b[i]值为a[i]中书对应数量
	cin >> flag;
	if (flag == 1) {
		while (1) { //挑选书籍
			cout << "请输入你要购买的书籍购买号、以及数量:" << endl;
			while (1) {
				try {
					cin >> a[i] >> b[i];
					if (b[i] <= 0) //异常处理
						throw b[i];
					break;
				} catch (int i) {
					cout << "数量格式错误,请重新输入!" << endl;
				}
			}
			amax++, i++;
			cout << "继续购买输入1,退出输入0" << endl;
			int x;
			cin >> x;
			if (x == 0) //判断退出
				break;
		}              //从文件读取书籍信息,进行计费
		//double sum=0;  //记录总费用
		ifstream i;
		i.open("书籍信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
		if (!i) {
			cout << "书籍信息文件打开失败!" << endl;
			exit(1);
		}
		i.seekg(0, ios::end);
		int filelen;
		filelen = i.tellg();//获取文件长度
		//i.seekg(0, ios::beg);//移动指针位置
		for (int j = 0; j < amax; j++) { //遍历数组a,即书籍种类
			i.seekg(0, ios::beg);//移动指针至起始位位置,进行遍历,类似于数列从i=0开始
			while (filelen != i.tellg()) { //到末尾时结束
				book *p = new book();
				i.read((char *)p, sizeof(book));
				if (p->get_buyid() == a[j]) {
					sum += p->getprice() * b[j];
				}
				delete p;
			}

		}
		i.close();
		//为避免重复调用此函数导致记录出错问题,用大A[]记录所有,以下是存储本次调用购买的书籍信息
		for (int j = 1; j <= ordermax; j++) { //遍历A数组
			for (int k = 0; k < amax; k++) //遍历a[i]数组
				if (a[k] == j)
					A[j] += b[k];
		}
	}	else
		return;
}

void pay() { //4.结算函数,此处要求得到应付金额sum、购买人信息
	flag1 = 1; //标记用户已经到达此函数
	cout << "*******请确认是否已选购好所需书籍,继续结账输入1,继续选购输入0*******" << endl;
	cout << "请输入:" << endl;
	int ii;
	cin >> ii;
	if (ii == 0)
		return;
	while (1) {
		try {
			cout << "请输入您的名字:" << endl;
			char a[10];
			cin >> a;
			strcpy(nam, a);
			//从客户信息文件遍历客户信息并找出客户信息
			ifstream it1, it2;
			it1.open("客户信息.dat",  ios::binary);//同时具备读写功能会出问题,编译器不报错
			if (!it1) {
				cout << "客户信息文件打开失败!" << endl;
				exit(1);
			}
			it2.open("flag.dat", ios::binary );
			if (!it2) {
				cout << "标记文件打开失败!";
				exit(1);
			}
			it2.seekg(0, ios::end);
			int filelen;
			filelen = it2.tellg();//获取文件长度
			it2.seekg(0, ios::beg);
			it1.seekg(0, ios::beg);//移动指针位置
			int fflag = 0;
			while (filelen != it2.tellg()) {
				char c;
				it2.read(&c, sizeof('1'));
				if (c == '0') {
					layfolk *p1 = new layfolk();
					it1.read((char *)p1, sizeof(layfolk));///输出的格式不对称,'\t'时
					if (strcmp(p1->getbuyname(), a) == 0) {
						sum = p1->setpay1(sum);
						id = p1->getid();
						fflag = 1;
						break;
					}
					delete p1;
				}
				if (c == '1') {
					honoured_guest *p2 = new honoured_guest();
					it1.read((char *)p2, sizeof(honoured_guest));
					if (strcmp(p2->getbuyname(), a) == 0) {
						sum = p2->setpay2(sum);
						id = p2->getid();
						fflag = 1;
						break;
					}
					delete p2;
				}
				if (c == '2') {
					member *p3 = new member();
					it1.read((char *)p3, sizeof(member));
					if (strcmp(p3->getbuyname(), a) == 0) {
						sum = p3->setpay3(sum);
						id = p3->getid();
						fflag = 1;
						break;
					}
					delete p3;
				}
			}
			it1.close();
			it2.close();
			if (fflag == 0)
				throw a;
			break;
		} catch (char a[10]) {
			cout << "未查询到您的信息,请进行登记或者重新输入,登记请输入0,重新输入请输入1:" << endl;
			int i;
			cin >> i;
			if (i == 0)
				return;
		}
	}
	cout << "您本次消费总额为: " << sum << endl;
	srand((int)time(0));
	int order_number;
	order_number = rand() % 9000 + 1000; //订单编号为四位数
	ofstream o;
	o.open("order.dat", ios::binary | ios::app);
	if (!o) {
		cout << "order.dat文件打开失败!" << endl;
		return;
	}
	order *p = new order(order_number, id, nam, A, sum);
	if (sum != 0)
		o.write((char *)p, sizeof(order));
	o.close();
	delete p;
}

void order_show() {
	order *p = new order(); //新建指针
	ifstream i;
	i.open("order.dat", ios::binary);
	if (!i) {
		cout << "order.dat文件打开失败!" << endl;
		return;
	}
	i.seekg(0, ios::end); //
	int filelen;//
	filelen = i.tellg();//获取文件长度
	i.seekg(0, ios::beg);
	cout << "查看本次订单输入1,查看您的历史订单输入2" << endl;
	int ii;
	cin >> ii;
	if (ii == 1) {
		if (sum != 0 && flag1 == 1) {
			i.seekg(-sizeof(order), ios::end);
			i.read((char *)p, sizeof(order));
			p->display();
		} else
			cout << "暂无订单信息" << endl;
	} else {
		cout << "请输入要查询人的姓名:" << endl;
		char nam[10];
		cin >> nam;
		i.seekg(0, ios::beg);
		if (filelen != 0) {
			int f = 0;
			while (i.tellg() != filelen) {
				i.read((char *)p, sizeof(order));
				if (strcmp(p->get_name(), nam) == 0) {
					p->display();
					f = 1;
					break;
				}
			}
			if (f == 0)
				cout << "未查询到您的订单信息" << endl;
		} else
			cout << "暂无订单信息" << endl;
	}
	i.close();
	delete p;
	//该客户购买完成后,进行sum,A[]归0,进行下一个客户购买,实现多次购买
	sum = 0, flag1 = 0; ///上面查询本次订单进行限制
	for (int j = 1; j <= ordermax; j++)
		A[j] = 0;
}

void explation() { //6.使用说明函数
	cout << "购书注意事项如下:" << endl;
	cout << "1.输入的信息以空格或者回车键为间隔" << endl;
	cout << "2.书籍下单后信息不可修改" << endl;
	cout << "3.若您未在系统客户信息里面,需要进行登记后购买" << endl;
	cout << "4.书籍购买完成后进行订单查看,信息无误后可退出系统" << endl;
}

void menu_show() { //主页菜单栏显示函数
	cout << "*************************************************************************" << endl;
	cout << "------------------------------网上购书系统-------------------------------" << endl;
	cout << "                     *****************************                       " << endl;
	cout << "                     ***    1.书籍信息显示     ***                       " << endl;
	cout << "                     ***    2.客户信息显示     ***                       " << endl;
	cout << "                     ***    3.选购书籍         ***                       " << endl;
	cout << "                     ***    4.结算总额         ***                       " << endl;
	cout << "                     ***    5.订单显示         ***                       " << endl;
	cout << "                     ***    6.使用说明         ***                       " << endl;
	cout << "                     ***    7.退出系统         ***                       " << endl;
	cout << "                     *****************************                       " << endl;
	cout << "请输入一个数字选择功能: ";
}

void show() {
	int n;
	while (1) {
		menu_show();
		cin >> n;
		switch (n) {
			case (7) : {
				cout << "欢迎下次光临,祝您生活愉快!" << endl;
				return;
			}
			case (1): {
				show_file2();//书本信息显示函数
				break;
			}
			case (2): {
				show_file1();//客户信息显示函数
				break;
			}
			case (3): {
				purchase();//选购书籍
				break;
			}
			case (4) : {
				pay();//结算总额
				break;
			}
			case (5): {
				order_show();//订单显示
				break;
			}
			case (6) : {
				explation();//使用说明
				break;
			}
		}
	}
}

int main() {
	show();
	return 1;
}

  • 28
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
网上超市购物管理系统,具体功能如下: 1、商品基本信息 1)商品代码,商品名称,商品价格,商品库存。 2)设计约定:可以假定超市有 N 种商品,在系统启动时将这些商品信息加载到商品库中。 2、顾客信息 1)普通顾客属性:ID(顾客代码)(随机生成或流水号) 2)普通会员:ID(会员代码),会员姓名,会员电话,会员积分。 3)高级会员:ID(会员代号),会员姓名,会员电话,会员积分,副卡 ID。 3、购物管理 1)为每一个普通顾客生成临时顾客代码。 2)普通会员购买商品时,可享受 9.8 折,普通顾客在单次购物满 1000 元,添加个人基本信息后,可成为普通会员。 3)高级会员购买商品时,可享受 9.5 折,普通顾客在单次购物满 2000 元,添加个人基本信息后,或普通会员单次购物满 1000 元可成为高级会员。普通会员和高级会员可查询 1 年内的购物详单,会员购物积分按照 1 元 1 分计。 4)每次购物后,输出购物清单。包括顾客代号(会员代码)、商品的名称、代号、单价、折扣、数量、价格以及合计价格、购买时间。 4、店铺管理 1)实现商品信息的添加、修改、删除、查询的功。可查询库存少于一定数量的商品。 2)实现会员资料的查询、修改、删除;实现会员整理的功能,对于 1 年内无购物的会员,进行自动删除。 3)可以按照时间区间统计,包括:销售总额;分类统计商品的销售情况;统计对会员的让利情况。
贪心算法是一种问题求解方法,它在每一步总是做出当前情况下的最优选择,以期望获得最优解。而"最大整数"同样可以使用贪心算法来求解。 对于"最大整数"的问题,我们可以考虑如下的贪心策略:从高位开始,尽可能选择较大的数字。具体步骤如下: 1. 对于给定的整数,我们首先将其转化为一个数组,其中每个元素表示整数的一个位数。 2. 从最高位(最左侧)开始,遍历数组。 3. 对于当前位上的数字,从9开始递减,找到第一个小于等于当前数字的最大数字。 4. 如果找到了符合条件的最大数字,将其放在当前位。否则,不做任何操作。 5. 继续向下遍历,重复步骤3-4。 6. 最终,得到的数组即为满足条件的最大整数。 以一个具体的例子说明上述算法:假设给定的整数为5372。 1. 将整数转化为数组[5, 3, 7, 2]。 2. 从最高位开始遍历。 3. 对于第一位5,从9开始递减,找到第一个小于等于5的数字,为7。 4. 将7放在第一位,得到[7, 3, 7, 2]。 5. 对于第二位3,从9开始递减,找到第一个小于等于3的数字,为3(与当前数字相等)。 6. 不做任何操作,得到[7, 3, 7, 2]。 7. 对于第三位7,从9开始递减,找到第一个小于等于7的数字,为7。 8. 将7放在第三位,得到[7, 3, 7, 2]。 9. 对于第四位2,从9开始递减,找到第一个小于等于2的数字,为2。 10. 将2放在第四位,得到[7, 3, 7, 2]。 11. 遍历结束,最终得到的数组为[7, 3, 7, 2],转化为整数为7372。 通过上述贪心算法,我们得到了满足条件的最大整数7372。证明了贪心算法在"最大整数"问题中的有效性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我还没秃头~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值