滴滴打车是目前出行的一种选择,打车时根据选择车型不同,实际行驶路程进行计费。武汉市的滴滴打车目前提供了 4 种车型,分别为快车、出租车、专车和豪华车。不同车型的 起步价以及起步价内的行驶路程不同,同时,每公里的计费标准也不相同;例如武汉市的快 车起步价为 8 元,起步价路程为 3Km,超出 3Km后,每公里计费 2.2 元。通过上述描述, 进行程序设计,当给定车型和行驶路程后,计算乘车费用。
表 1 武汉市滴滴计费标准
车辆类型 | 起步价(元) | 起步价路程(km) | 超出距离计费(元/公里) |
---|---|---|---|
快车 | 8.0 | 3 | 2.2 |
出租车 | 10.0 | 4 | 2.7 |
专车 | 14.0 | 3 | 3.6 |
豪华车 | 18.0 | 3 | 3.9 |
要求:
1) 滴滴司机每跑完一个订单,形成一个记录,记入该司机名下;订单记录信息含如下内容: 订单号、起始时间、终止时间、行驶路程、订单支付金额。司机可随时查询指定时间段 内所完成的订单信息,统计收入金额。
2) 保存订单记录的数据结构可采用第一题的数组或 STL 中的容器。
编程思路:因为一共只有4种车,则用一个枚举类型将四种车存入其中。在分别创建滴滴车类(可以计算每个订单的费用),订单类用于存储每个订单的信息,由于要记录时间,可以创建一个时间类方便处理时间.最后创建一个司机类用于存储订单和车,以及能够让司机随时查找订单的功能。完成后测试时只需要创建一辆对应的车给司机,再把订单给司机即可。用于存储订单的列表需要用到之前编写的数组类。
头文件stdfx.h
#ifndef STDAFX_H_INCLUDED
#define STDAFX_H_INCLUDED
#include <iostream>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include "myarray.h"
#include "didi.h"
using namespace std;
#endif // STDAFX_H_INCLUDED
头文件myarray.h
#ifndef MYARRAY_H_INCLUDED
#define MYARRAY_H_INCLUDED
#include "stdafx.h"
//自定义的异常类型
class OutOfRange{
public:
OutOfRange() = default;
OutOfRange(int len, int index): m_len(len), m_index(index) { }
public:
void what() const; //获取具体的错误信息
private:
int m_len = 0; //容器中定义的长度
int m_index = 0; //当前用户要访问的下标
};
void OutOfRange::what() const
{
cout<<"Error: out of range( continents length "<<m_len
<<", access index "<<m_index<<" )"<<endl;
}
//实现动态数组的类模板
template<typename DT>
class ArrayT{
private:
//initialize 初始化
void init(int nums = 0)
{
nums = nums > 0? nums : 0;
m_pData = (DT*)malloc( sizeof(DT) * (nums + m_stepSize) );
m_capacity = nums + m_stepSize;
m_len = nums;
}
public:
//ctor
ArrayT() { init(); }
ArrayT(int nums){ init(nums); }
ArrayT(int nums,DT val)
{
init(nums);
for(int i=0;i<m_len;++i)
{
m_pData[i] = val;
}
}
//copy ctor
ArrayT(const ArrayT & obj)
{
//初始化一个同obj相同的空间
init(obj.m_len);
//将元素进行拷贝
for(int i=0;i<obj.m_len;++i)
{
m_pData[i] = obj.m_pData[i];
}
}
//copy assignment 拷贝赋值
ArrayT & operator=(const ArrayT & obj)
{
//self assignment pred 自我赋值判断
if(m_pData == obj.m_pData){return * this;}
//capacity 如果目标空间大于源空间,则不需要申请内存空间
if(m_capacity < obj.m_capacity)
{
//对原有空间进行扩容,即已经有的数值保持不变,现有空间同obj的空间相同
m_pData = (DT*)realloc( m_pData, sizeof(DT) * obj.m_capacity );
m_capacity = obj.m_capacity;
}
//将元素进行拷贝
for(int i=0; i<obj.m_len; ++i)
{
m_pData[i] = obj.m_pData[i];
}
m_len = obj.m_len;
return *this;
}
//dtor
~ArrayT()
{
if(m_pData)
{
free(m_pData);
m_pData = nullptr;
}
};
//member of function
public:
//overload operator []
DT& operator[](int index) const
{
//判断是否越界
if( index<0 || index>=m_len )
{
//抛出异常(创建一个临时的匿名对象)
throw OutOfRange(m_len, index);
}
return *(m_pData + index);
}
//在末尾插入元素,返回当前插入元素的索引号
int push_back(DT ele)
{
if(m_len >= m_capacity)
{
//如果容量不足就扩容
m_capacity += m_stepSize;
//扩容 原有元素保持不变
m_pData = (DT*)realloc( m_pData, sizeof(DT) * m_capacity );
}
*(m_pData + m_len) = ele;
m_len++;
return m_len-1;
}
//在末尾弹出数组元素,返回该元素
DT pop_back()
{
if(m_len == 0)
{
throw OutOfRange(m_len,m_len); //抛出异常(创建一个匿名对象)
}
m_len--;
return *(m_pData + m_len);
}
//获取数组长度
int length() const{ return m_len; };
//获取开始位置的指针
DT * begin() const{ return m_pData; }
//获取超尾位置的指针
DT * end() const {return m_pData+m_len;}
//member of data
private:
int m_len = 0; //数组长度
int m_capacity = 0; //当前的内存能容纳多少个元素
DT *m_pData = nullptr; //具体数据内容的内存指针
private:
static const int m_stepSize = 50; //每次扩容的步长
};
#endif // MYARRAY_H_INCLUDED
头文件didi.h
#ifndef DIDI_H_INCLUDE
#define DIDI_H_INCLUDE
#include "stdafx.h"
using namespace std;
//用枚举类型放4种车(快车,出租车,专车,豪华车)
enum class DIDITYPE{ QUICK_CAR, TAXI, PRIVATE_CAR, LUXURY_CAR };
//车类
class didicar
{
public:
//构造函数
didicar() = default;
didicar(DIDITYPE dv, float fsp, float fsd, float fp):_type(dv),_fSPrice(fsp), _fSDis(fsd), _fPrice(fp){}
protected:
DIDITYPE _type; //车类
float _fSPrice; //起步价
float _fSDis; //起步距离
float _fPrice; //每公里价格
public:
//计算费用,形参为距离
float calFee(float dis)
{
float fprice;
//如果在起步距离内,价格为起步价,否则另行计算
fprice = dis > _fSDis ? _fSPrice : _fSPrice + (dis - _fSDis) * _fPrice;
return fprice;
}
};
//日期类
class datatime
{
protected:
//一个日期由年月日时分秒构成
int _year;
int _mouth;
int _day;
int _hour;
int _min;
int _sec;
public:
//构造函数
datatime() :_year(2020), _mouth(1), _day(1), _hour(0), _min(0), _sec(0){}
datatime(int year, int mouth, int day, int hour, int min,int sec):
_year(year), _mouth(mouth), _day(day), _hour(hour), _min(min), _sec(sec){}
//输出时间函数
void outdate()
{
cout << _year << "年" << _mouth << "月" << _day << "日"
<< _hour << "时" << _min << "分" << _sec << "秒" << endl;
}
//重载==判断时间是否相等
bool operator==(const datatime& obj)
{
if ((obj._year == _year) && (obj._mouth == _mouth) && (obj._day == _day) && (obj._hour == _hour) && (obj._min == _min) && (obj._sec == _sec))
{
return true;
}
else
{
return false;
}
}
//重载>=用于判断是否在指定时间内
bool operator>=(const datatime& obj)
{
if (_year > obj._year) { return true; }
else if (_year == obj._year)
{
if (_mouth > obj._mouth) { return true; }
else if (_mouth == obj._mouth)
{
if (_day > obj._day) { return true; }
else if (_day == obj._day)
{
if (_hour > obj._hour) { return true; }
else if (_hour == obj._hour)
{
if (_min > obj._min) { return true; }
else if (_min == obj._min)
{
if (_sec >= obj._min) { return true; }
else { return false; }
}
else { return false; }
}
else { return false; }
}
else { return false; }
}
else { return false; }
}
else { return false; }
}
//重载<=用于判断是否在指定时间内
bool operator<=(const datatime& obj)
{
if (_year < obj._year) { return true; }
else if (_year == obj._year)
{
if (_mouth < obj._mouth) { return true; }
else if (_mouth == obj._mouth)
{
if (_day < obj._day) { return true; }
else if (_day == obj._day)
{
if (_hour < obj._hour) { return true; }
else if (_hour == obj._hour)
{
if (_min < obj._min) { return true; }
else if (_min == obj._min)
{
if (_sec <= obj._min) { return true; }
else { return false; }
}
else { return false; }
}
else { return false; }
}
else { return false; }
}
else { return false; }
}
else { return false; }
}
};
//订单类
class order
{
public:
int ID;
datatime _begin;
datatime _end;
float _fDistance;
float _fFee;
//构造函数
order() = default;
order(int id, datatime begin, datatime end, float distance,float fee):
ID(id),_begin(begin),_end(end),_fDistance(distance),_fFee(fee){}
//输出一个订单的相关信息
void outOrder()
{
cout << "订单号为:" << ID << endl;
//输出时间
cout << "起始时间为:";
_begin.outdate();
cout << "起始时间为:";
_end.outdate();
cout << "行驶路程为:" << _fDistance << endl;
cout << "订单支付金额为:" << _fFee;
cout << "\n"<<"\n";
}
};
//司机类
class driver
{
public:
didicar _carobj; //定义一个车类
ArrayT<order> _arOder; //用于存放订单的数组
public:
//根据日期查询订单,只要是在此期间的订单都显示出来
int query(datatime& objbeg, datatime& objend)
{
int nnum = 0; //用于记录在这个区间中有多少个订单
float allmoney = 0; //用于记录这段时间的总收入
//但是在实际过程中,录入的订单一般是已经排好序的,采用二分法更好
//由于此题的订单可能是乱序的,避免重新排序,使用顺序法
int m_len;
//获取数组长度
m_len = _arOder.length();
bool flag = true;
for (int i = 0;i < m_len;++i)
{
if (objbeg <= _arOder[i]._begin && objend >= _arOder[i]._end)
{
cout << "这段时间的订单:" << endl;
_arOder[i].outOrder();
allmoney += _arOder[i]._fFee;
++nnum;
flag = false;
cout << "这段时间的总收入为:" << allmoney << "元" << endl;
}
}
if(flag){ cout << "记录中没有这段时间的订单!" << endl; }
return nnum;
}
//根据订单号查询
void query(int norderID)
{
int m_len;
//获取数组长度
m_len = _arOder.length();
//遍历数组,查看是否有该订单
//每个订单号都是独一无二的,不存在一个订单号有几个订单
bool flag = true;
for (int i = 0;i < m_len;++i)
{
if (norderID == _arOder[i].ID)
{
cout << "该订单在记录中,相关信息为:" << endl;
_arOder[i].outOrder();
flag = false;
}
}
//如果没有订单告诉司机
if (flag)
{
cout << "记录中没有" << norderID << "这个订单号!" << endl;
}
}
};
#endif // !DIDI_H_INCLUDE
源文件main.cpp
#include "stdafx.h"
int main()
{
//构建一辆车
DIDITYPE dv = DIDITYPE::QUICK_CAR;
didicar didiobj(dv, 8.0, 3.0, 2.2);
//构建一个司机
driver zztobj;
//把车给司机
zztobj._carobj = didiobj;
//跑完一单后的钱
float nfee = zztobj._carobj.calFee(26.5);
//创建初始时间与结束时间
datatime begin(2020, 8, 19, 13, 18, 50);
datatime end(2020, 8, 19, 13, 52, 13);
//创建订单并放入订单数组中
order objorder(1, begin, end, 26.5, nfee);
zztobj._arOder.push_back(objorder);
//输出这个订单的信息
zztobj._arOder[0].outOrder();
//通过时间段来查找订单
//确定起止区间,让订单在其中,再根据时间查找
datatime one_begin(2020, 1, 1, 0, 0, 0);
datatime one_end(2020, 12, 31, 0, 0, 0);
zztobj.query(one_begin, one_end);
//确定起止区间,让订单不在其中,再根据时间查找
/*
datatime two_begin(2030, 1, 1, 0, 0, 0);
datatime two_end(2030, 12, 31, 0, 0, 0);
zztobj.query(two_begin, two_end);
*/
//通过ID的方法查找订单
/*
zztobj.query(1); //订单号存在时
zztobj.query(123); //订单号不存在时
*/
return 0;
}