C++编程训练9


滴滴打车是目前出行的一种选择,打车时根据选择车型不同,实际行驶路程进行计费。武汉市的滴滴打车目前提供了 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;
}

文章作者: 陈细利
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 陈细利 !
评论
 上一篇
数据结构第一次上机实习 数据结构第一次上机实习
实习题目:一元稀疏多项式运算器一、 上机实习题目与要求问题描述设计一个一元稀疏多项式简单计算器。 基本要求(1)输入并建立两个多项式; (2)多项式a与b相加,建立和多项式c; (3)多项式a与b相减,建立差多项式d; (3)输出多项
下一篇 
C++编程训练8 C++编程训练8
已提供代码文件如下: stdafx.h 文件,包含程序所需的文件; myarray.h 文件 动态数组类模板文件,实现了动态数组的基本操作;提供了[], begin(),end() 等,同时提供了异常处理的类,当访问数组时出现越界异常,则
  目录