菜鸟智慧系统(线性表)

[问题描述]

使用双向链表模拟快递驿站的系统运作:

+ 假设快递驿站的货架分小、中、大3种类型,容量分别为500、100、50个包裹;该快递站关联的社区人员为MAX_PERSON人(例如,限定为30人,每人唯一手机号)。

+ 驿站每天都会来一批新的包裹。包裹根据大小类型分别上对应的货架,加入对应链表表尾,并使用该货架当前可用的最小编号。用N[1]、N[2]、N[3]分别表示每天随机来的大、中、小包裹数量,保证N[i]在货架的承受能力之内。

+ 包裹信息包括:包裹编号(生成的取件码,分别为1-x(小),2-x(中), 3-x(大))、取件人姓名、取件人手机号、包裹大小(小1、中2、大3)、到达日期。

+ 包裹上架时,按照包裹编号从小到大的顺序排列。

+ 包裹取出后就从对应链表中删除。用M表示每天随机来取包裹的人数,且M≤MAX_PERSON。

+ 包裹最多在驿站存放两天,逾期则退还寄件人(从货架上清除)。

+ 当一人来取包裹时,可通过提供其任一取件码或手机号查询包裹并取出该人员所有关联的包裹。

+ 设计相应的分析、统计功能(自定义),例如当天收包裹数量最多的人,当天有包裹人的平均包裹数量,一周内与其被退回的包裹数量等。

+ 可根据需要做功能拓展,使得模拟系统更接近实用或在现有商用快递系统的基础上有针对性的创新(*)

+ 该问题需有较好的展示性,能够演示快递收发过程。

[基本要求]

  1. 所有事件均随机生成

  1. 用文件存储货架状态,所有变更均应反应在文件中。存储形式自行设计,但务必清晰、直观

解题思考:

(1)把日期封装成类,便于处理。包裹保存为结构体。创建一个全局变量Vis[4][505]来保存货架上的位置情况。但要创建一个保存取件人姓名、手机号的文件。另外,包裹分为三个状态:0:未取件;1:已取件;2:已退件。

(2)每次运行程序时,第一步从Package.dat文件中读取原有数据,构建3个双向链表(不论原文件中有没有数据,都要构建)。

(3)添加新到的包裹,编号不是随机生成的,而是使用对应货架当前可用的最小编号。快递生成编号时,与Vis[4][505]进行比较来查重。然后依据编号大小进行插入操作。

(4)根据每个包裹的日期执行退还操作,即在文件中将其删除(将这一步放到第2步一起执行,读取Package.dat文件中的数据时顺便检查是否有未领取包裹的时间超过了两天)。

(5)因为一开始就确定了来取包裹的人数,所以不适合一个人一个人的进行取包裹操作,于是我将取包裹变成了随机事件,放在一起处理。取包裹时,用取件码或手机查询这个人的所有包裹,并将其取出。对于取走的包裹,改变它的状态为已领取,再修改文件。

(6)最后就是关于统计了,当天收到包裹数量最多的人可以放到第3步一起做,可以创建一个全局变量People[30](这里假定为30人),添加新包裹的同时,给对应的收件人加1;当天有包裹人的平均包裹数量,这个根据已有的People[30]也容易处理;一周内被退回的包裹数量,我们的Package.dat文件保存有一周内的包裹信息,直接打开文件统计状态为“退回”的包裹的数量就可以了。

注:数据积累一周,在周一的时候再清理已取或退还的快递的信息。这样可以方便进行一周的统计,以及导出任意人员的收件情况。另外,我增加“查询任意人员过去三天的取件记录”的功能。

Date.h的代码(用于时间处理的头文件):

# include <windows.h>
# include <iostream>

using namespace std;

class Date                               //表示日期的类 
{
    private:
        int year;//年 
        int month;//月 
        int day;  //日
        void simplify(); //调整日期(--) 
    public:
        Date(int y = 0, int m = 0, int d = 0)
        {
            year = y;
            month = m;
            day = d;
        }
        void SetToday();//完成对Date型的当前日期赋值 
        Date operator =(const Date& right);//重载"=",以完成对Date型的直接赋值
        bool operator ==(const Date& right);//重载"==",以完成Date型的比较
        bool operator >(const Date& right); //重载">",以完成Date型的比较
        bool operator <(const Date& right); //重载"<",以完成Date型的比较        
        int operator -(const Date& right); //重载"-",以求出任意两天的间隔天数
        int Week();     //求今天是星期几
        Date operator --();   //重载前置--  
        friend istream& operator >>(istream&, Date&); //重载">>",完成Date型的直接输入
        friend ostream& operator <<(ostream&, Date&); //重载"<<",完成Date型的直接输出 
};

void Date::simplify()
{
    int y = year, m = month, d = day;
    int p = 0;
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        p = 1;
    }
    if (p)   //如果是闰年 
    {
        switch (m)
        {
        case 1:if (d < 1) { y--; m = 12; d = 31; } break;
        case 2:if (d < 1) { m--; d = 31; } break;
        case 3:if (d < 1) { m--; d = 29; } break;
        case 4:if (d < 1) { m--; d = 31; } break;
        case 5:if (d < 1) { m--; d = 30; } break;
        case 6:if (d < 1) { m--; d = 31; } break;
        case 7:if (d < 1) { m--; d = 30; } break;
        case 8:if (d < 1) { m--; d = 31; } break;
        case 9:if (d < 1) { m--; d = 31; } break;
        case 10:if (d < 1) { m--; d = 30; } break;
        case 11:if (d < 1) { m--; d = 31; } break;
        case 12:if (d < 1) { m--; d = 30; } break;
        }
    }
    else
    {
        switch (m)
        {
        case 1:if (d < 1) { y--; m = 12; d = 31; } break;
        case 2:if (d < 1) { m--; d = 31; } break;
        case 3:if (d < 1) { m--; d = 28; } break;
        case 4:if (d < 1) { m--; d = 31; } break;
        case 5:if (d < 1) { m--; d = 30; } break;
        case 6:if (d < 1) { m--; d = 31; } break;
        case 7:if (d < 1) { m--; d = 30; } break;
        case 8:if (d < 1) { m--; d = 31; } break;
        case 9:if (d < 1) { m--; d = 31; } break;
        case 10:if (d < 1) { m--; d = 30; } break;
        case 11:if (d < 1) { m--; d = 31; } break;
        case 12:if (d < 1) { m--; d = 30; } break;
        }
    }
}

istream& operator >>(istream& strm, Date& obj)//重载">>",完成Date型的直接输入
{
    cout << "\t\t*年*:";
    strm >> obj.year;
    cout << "\t\t*月*:";
    strm >> obj.month;
    cout << "\t\t*日*:";
    strm >> obj.day;
    return strm;
}

void Date::SetToday()//显示今日日期,并完成对Date型的赋值 
{
    int y, m, d;
    SYSTEMTIME sys;
    GetLocalTime(&sys);
    year = sys.wYear;
    month = sys.wMonth;
    day = sys.wDay;
}

ostream& operator <<(ostream& strm, Date& obj) //重载"<<",完成Date型的直接输出 
{
    strm << obj.year << "年" << obj.month << "月" << obj.day << "日";
    return strm;
}

Date Date::operator =(const Date& right)//重载"=",完成日期的直接赋值 
{
    year = right.year;
    month = right.month;
    day = right.day;
    return *this;
}

Date Date::operator --()   //重载前置--
{
    --day;
    simplify();
    return *this;
}

bool Date::operator ==(const Date& right)//重载"==",以完成Date型的比较 
{
    if (year == right.year && month == right.month && day == right.day)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Date::operator >(const Date& right) //重载">",以完成Date型的比较
{
    if (year > right.year)
    {
        return true;
    }
    else if (year == right.year && month > right.month)
    {
        return true;
    }
    else if (year == right.year && month == right.month && day > right.day)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Date::operator <(const Date& right)   //重载"<",以完成Date型的比较        
{
    if (year < right.year)
    {
        return true;
    }
    else if (year == right.year && month < right.month)
    {
        return true;
    }
    else if (year == right.year && month == right.month && day < right.day)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int Date::operator -(const Date& right) //重载"-",以求出任意两天的间隔天数 
{
    int y1 = year, m1 = month, d1 = day;//大天数 
    int y2 = right.year, m2 = right.month, d2 = right.day;//小天数 
    int p1 = 0, p2 = 0; //判断是否为闰年
    int a1 = 0, a2 = 0; //判断这一天是这一年的第几天 
    int a3 = 0; //间隔天数 
    if ((y1 % 4 == 0 && y1 % 100 != 0) || y1 % 400 == 0)
    {
        p1 = 1;
    }
    if ((y2 % 4 == 0 && y2 % 100 != 0) || y2 % 400 == 0)
    {
        p2 = 1;
    }
    if (p1)
    {
        switch (m1)
        {
        case 1: a1 += d1; break;
        case 2: a1 += 31 + d1; break;
        case 3: a1 += 60 + d1; break;
        case 4: a1 += 91 + d1; break;
        case 5: a1 += 121 + d1; break;
        case 6: a1 += 152 + d1; break;
        case 7: a1 += 182 + d1; break;
        case 8: a1 += 213 + d1; break;
        case 9: a1 += 244 + d1; break;
        case 10: a1 += 274 + d1; break;
        case 11: a1 += 305 + d1; break;
        case 12: a1 += 335 + d1; break;
        }
    }
    else
    {
        switch (m1)
        {
        case 1: a1 += d1; break;
        case 2: a1 += 31 + d1; break;
        case 3: a1 += 59 + d1; break;
        case 4: a1 += 90 + d1; break;
        case 5: a1 += 120 + d1; break;
        case 6: a1 += 151 + d1; break;
        case 7: a1 += 181 + d1; break;
        case 8: a1 += 212 + d1; break;
        case 9: a1 += 243 + d1; break;
        case 10: a1 += 273 + d1; break;
        case 11: a1 += 304 + d1; break;
        case 12: a1 += 334 + d1; break;
        }
    }
    if (p2)
    {
        switch (m2)
        {
        case 1: a2 += d2; break;
        case 2: a2 += 31 + d2; break;
        case 3: a2 += 60 + d2; break;
        case 4: a2 += 91 + d2; break;
        case 5: a2 += 121 + d2; break;
        case 6: a2 += 152 + d2; break;
        case 7: a2 += 182 + d2; break;
        case 8: a2 += 213 + d2; break;
        case 9: a2 += 244 + d2; break;
        case 10: a2 += 274 + d2; break;
        case 11: a2 += 305 + d2; break;
        case 12: a2 += 335 + d2; break;
        }
    }
    else
    {
        switch (m2)
        {
        case 1: a2 += d2; break;
        case 2: a2 += 31 + d2; break;
        case 3: a2 += 59 + d2; break;
        case 4: a2 += 90 + d2; break;
        case 5: a2 += 120 + d2; break;
        case 6: a2 += 151 + d2; break;
        case 7: a2 += 181 + d2; break;
        case 8: a2 += 212 + d2; break;
        case 9: a2 += 243 + d2; break;
        case 10: a2 += 273 + d2; break;
        case 11: a2 += 304 + d2; break;
        case 12: a2 += 334 + d2; break;
        }
    }
    if (y1 == y2)
    {
        a3 = a1 - a2;
    }
    else
    {
        for (int i = y2 + 1; i < y1; i++)
        {
            if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)
            {
                a3 += 366;
            }
            else
            {
                a3 += 365;
            }
        }
        if (p2 == 1)
        {
            a3 = a3 + a1 + 366 - a2;
        }
        else
        {
            a3 = a3 + a1 + 365 - a2;
        }
    }
    return a3;
}

int Date::Week()     //求今天是星期几
{ 
    Date d1(2022, 11, 20);     //2022.11.20是周日
    Date d2(year, month, day);
    int a = d2 - d1;
    int b = a % 7;
    if (b == 0) {
        b = 7;
    }
    return b;
}

主程序代码:

# include <iostream>
# include <stdlib.h>
# include <fstream>
# include <string.h>
# include <stdlib.h>
# include <windows.h>
# include <iomanip>
# include <random>
# include <time.h>
# include "Date.h"
# define maxp 30    //人员总数
# define maxn 505   
# define maxn1 500  //货架1的最大容量
# define maxn2 100  //货架2的最大容量
# define maxn3 50   //货架3的最大容量
# define maxp1 10   //每天新到的小包裹的最大数目
# define maxp2 5    //每天新到的中包裹的最大数目
# define maxp3 3    //每天新到的大包裹的最大数目
# define maxp4 10   //每天来取包裹的最大人数

using namespace std;

typedef struct Package
{
    int condition;   //包裹的收取状态(0.待收;1.已收;2.退还)
    int size;        //包裹大小
    int num;         //在货架上的位置编号
    int code;        //取件码
    char name[15];   //取件人姓名
    char phone[12];  //取件人手机号
    Date day;        //到达日期
    struct Package* prev;   //前驱结点
    struct Package* next;   //后继结点
}Package;

void frame();                          //框架函数 
void Outline();                       //界面菜单
void Create();                          //从文件中读取数据,创建三个货柜的双向链表
void SetPackage(int i, int n, int m); //设置添加单个包裹
void Insert(Package p);                  //根据包裹大小和编号插入指定货架的相应位置
void AddPackages();                      //添加今日新到的包裹
void Delete(Package p);                  //从货架的双向链表中删除包裹
void TakePackages();                  //取走包裹
void Count();                         //统计一些基本情况
void Find();                          //查询人员过去三天的取件记录
void Print(Package* S, int n);        //打印双向链表里的数据
void Show();                          //展现目前三个货架上的快递
void Clear();                         //清理Package.dat文件中的数据
int Vis[4][maxn] = { {0} };              //保存编号(与货柜的位置相对应),查重包裹编号
int People[maxp + 1] = { 0 };          //索引当天每个人收到的快递数
Package* Shelve[4];                      //三个货架
int N[4] = { 0,maxn1,maxn2,maxn3 };   //保存三个货架的剩余容量
Date today;                           //今日日期
int total;                            //每次货架上的包裹总数

int main()
{
    Outline();
    today.SetToday();
    cout << "今日日期:" << today << endl;
    int week = today.Week(); //获取今天是星期几
    if (week == 1)  //如果是周一,要执行清理Package.dat文件的操作
    {
        cout << "\n今日是周一,已自动对包裹数据进行清理" << endl;
        Clear();
    }
    char c;
    cout << "\n今日退还的包裹:" << endl;
    cout << "\n输入任意键继续运行:";
    cin >> c;
    Create();
    frame();
    cout << "\n今日收件前各货架上的包裹状况:" << endl;
    cout << "\n输入任意键继续运行:";
    cin >> c;
    Show();
    frame();
    cout << endl;
    frame();
    cout << "\n今日新增包裹:" << endl;
    cout << "\n输入任意键继续运行:";
    cin >> c;
    AddPackages();
    frame();
    cout << endl;
    frame();
    cout << "\n今日收件后各货架上的包裹状况:" << endl;
    cout << "\n输入任意键继续运行:";
    cin >> c;
    Show();
    frame();
    cout << endl;
    frame();
    cout << "\n今日被取走的包裹:" << endl;
    cout << "\n输入任意键继续运行:";
    cin >> c;
    TakePackages();
    frame();
    cout << endl;
    frame();
    cout << "\n今日取件后各货架上的包裹状况:" << endl;
    cout << "\n输入任意键继续运行:";
    cin >> c;
    Show();
    frame();
    cout << endl;
    cout << "统计信息:" << endl;
    Count();
    frame();
    cout << "\n查询客户信息" << endl;
    int select = 1;
    while (select == 1)
    {
        Find();
        cout << "是否继续查询:(1)是 (2)否" << endl;
        cout << "请选择:";
        cin >> select;
    }
    return 0;
}

//框架函数
void frame()
{
    for (int i = 0; i < 120; i++)
    {
        cout << "*";
    }
    cout << endl;
}

//界面菜单
void Outline()
{
    frame();
    cout << "\n------------------------------------------------- ";
    cout << "欢迎进入菜鸟智慧系统";
    cout << " ----------------------------------------------- \n";
    frame();
    cout << '\n';
}

//根据包裹大小和编号插入指定货架的相应位置
void Insert(Package p)                //根据包裹大小和编号插入指定货架的相应位置
{
    Package* pk;
    pk = (Package*)malloc(sizeof(Package)); //创建指针型的变量,并用包裹数据为其赋值
    pk->condition = p.condition;
    pk->size = p.size;
    pk->num = p.num;
    pk->code = p.code;
    strcpy(pk->name, p.name);
    strcpy(pk->phone, p.phone);
    pk->day = p.day;
    int n = pk->size;
    Package* pN = Shelve[n];
    while (pN->next != NULL)
    {
        if (pN->next->num > pk->num)  //寻找该包裹在货架上的位置
        {
            break;
        }
        pN = pN->next;
    }
    pk->next = pN->next;
    pN->next = pk;
    pk->prev = pN;
    if (pk->next != NULL) {
        pk->next->prev = pk;
    }
}

//从文件中读取数据,创建三个货柜的双向链表
void Create()
{
    cout.setf(ios::left);
    Shelve[1] = (Package*)malloc(sizeof(Package));
    Shelve[2] = (Package*)malloc(sizeof(Package));
    Shelve[3] = (Package*)malloc(sizeof(Package));
    Shelve[1]->prev = NULL;
    Shelve[1]->next = NULL;
    Shelve[2]->prev = NULL;
    Shelve[2]->next = NULL;
    Shelve[3]->prev = NULL;
    Shelve[3]->next = NULL;
    Package p;
    fstream file1, file2;
    file1.open("Package.dat", ios::in | ios::binary); //二进制读取文件中已有的包裹数据
    file2.open("Empty.dat", ios::out | ios::binary);  //只写打开空白文件(辅助进行文件修改)
    if (file2.fail())
    {
        cout << "Empty.dat文件打开失败" << endl;
        exit(0);
    }
    int t = 0;
    if (!file1.fail())
    {
        //文件打开失败说明是第一次使用系统,不存在先前数据
        //文件打开成功说明存在先前数据
        file1.read((char*)&p, sizeof(p));
        while (!file1.eof())
        {
            if (today - p.day > 2 && p.condition != 2) //检测到包裹存放时间已超过两天
            {
                p.condition = 2;         //调整包裹为退还状态
                cout << "取件码:" << p.code << "\t";
                cout << "取件人姓名:" << setw(10) << p.name;
                cout << "取件人手机号:" << p.phone << "\t";
                cout << "收件日期:" << p.day << "\n";
                N[p.size]++;
                Vis[p.size][p.num] = 0;  //将货架的相应位置还原为0
                t = 1;                   //改变了文件内容,之后需修改文件
            }
            else if (p.condition == 0)   //将仍未被收取的包裹放到货架上
            {
                Insert(p);
                Vis[p.size][p.num] = 1;  //将货架的相应位置标注为1
                N[p.size]--;
            }
            file2.write((char*)&p, sizeof(p));
            file1.read((char*)&p, sizeof(p));
        }
    }
    file1.close();
    file2.close();
    if (t) //修改Package.dat
    {
        file1.open("Package.dat", ios::out | ios::binary); //只写覆盖打开Package.dat
        file2.open("Empty.dat", ios::in | ios::binary);    //只读打开空白文件
        if (file1.fail())
        {
            cout << "Package.dat文件打开失败" << endl;
            exit(0);
        }
        if (file2.fail())
        {
            cout << "Empty.dat文件打开失败" << endl;
            exit(0);
        }
        file2.read((char*)&p, sizeof(p));
        while (!file2.eof())
        {
            file1.write((char*)&p, sizeof(p));
            file2.read((char*)&p, sizeof(p));
        }
        file1.close();
        file2.close();
    }
    else
    {
        cout << "无" << endl;
    }
}

//设置添加单个包裹
void SetPackage(int i, int n, int m)
{
    cout.setf(ios::left);
    Package p;
    char str[100], strn[20], strp[15];
    fstream file, file1;
    for (int j = 1; j <= n; j++)
    {
        if (Vis[i][j] == 0)  //寻找货架当前可用的最小位置编号
        {
            int x = 10 * i;
            while (x <= j)
            {
                x *= 10;
            }
            p.code = x + j;  //生成新到包裹的编号
            p.num = j;       //生成新到包裹的位置编号
            Vis[i][j] = 1;   //将货架的相应位置标注为1
            break;
        }
    }
    p.condition = 0;
    p.size = i;
    p.day = today;
    People[m]++;
    file.open("收件人信息.txt", ios::in);
    if (file.fail())
    {
        cout << "收件人信息.txt文件打开失败" << endl;
        exit(0);
    }
    for (int k = 1; k <= m && !file.eof(); k++)
    {
        file.getline(str, 100);
    }
    int t = 0, ln = 0, lp = 0;
    for (int k = 0; k < strlen(str); k++)  //处理文本文件,获取随机选中的收件人的姓名和手机号
    {
        if (!t)
        {
            if (str[k] == ' ')
            {
                t = 1;
                strn[ln] = '\0';
            }
            else
            {
                strn[ln] = str[k];
                ln++;
            }
        }
        else
        {
            strp[lp] = str[k];
            lp++;
        }
    }
    strp[lp] = '\0';
    strcpy(p.name, strn);
    strcpy(p.phone, strp);
    Insert(p);
    cout << "取件码:" << p.code << "\t";
    cout << "取件人姓名:" << setw(10) << p.name;
    cout << "取件人手机号:" << p.phone << "\t";
    cout << "收件日期:" << today << "\n";
    file1.open("Package.dat", ios::out | ios::app | ios::binary); //只写追加打开Package.dat
    if (file1.fail())
    {
        cout << "Package.dat文件打开失败" << endl;
        exit(0);
    }
    file1.write((char*)&p, sizeof(p));
    file.close();
    file1.close();
}

//添加今日新到的包裹
void AddPackages()
{
    int m;
    srand((unsigned int)time(0)); //修改种子
    int n1 = rand() % maxp1 + 1;  //随机生成新到的小包裹数
    while (n1 > N[1])  //限定新到的包裹数小于货架剩余的空间
    {
        n1 = rand() % maxp1 + 1;
    }
    cout << "\n今日新增小包裹" << n1 << "件" << endl;
    for (int i = 1; i <= n1; i++)
    {
        m = rand() % maxp + 1;  //随机选中收件人
        SetPackage(1, maxn1, m);
    }
    N[1] -= n1;
    cout << endl;
    int n2 = rand() % maxp2 + 1;  //随机生成新到的中包裹数
    while (n2 > N[2])  //限定新到的包裹数小于货架剩余的空间
    {
        n2 = rand() % maxp2 + 1;
    }
    cout << "今日新增中包裹" << n2 << "件" << endl;
    for (int i = 1; i <= n2; i++)
    {
        m = rand() % maxp + 1;  //随机选中收件人
        SetPackage(2, maxn2, m);
    }
    N[2] -= n2;
    cout << endl;
    int n3 = rand() % maxp3 + 1;  //随机生成新到的大包裹数
    while (n3 > N[3])  //限定新到的包裹数小于货架剩余的空间
    {
        n3 = rand() % maxp3 + 1;
    }
    cout << "今日新增大包裹" << n3 << "件" << endl;
    for (int i = 1; i <= n3; i++)
    {
        m = rand() % maxp + 1;  //随机选中收件人
        SetPackage(3, maxn3, m);
    }
    N[3] -= n3;
}

//从货架的双向链表中删除包裹
void Delete(Package p)
{
    int n = p.size;
    Package* pN = Shelve[n]->next;
    while (pN != NULL)
    {
        if (strcmp(pN->phone, p.phone) == 0)  //寻找该人的所有包裹
        {
            pN->prev->next = pN->next;
            if (pN->next != NULL)
            {
                pN->next->prev = pN->prev;
            }
        }
        pN = pN->next;
    }
}

//取包裹
void TakePackages()
{
    int sum = 0;
    fstream file, file1, file2;
    Package p;
    char str[100], strn[20], strp[15];
    srand((unsigned int)time(0));    //修改种子
    int n = rand() % maxp4 + 1;      //随机生成来取包裹的人数
    for (int i = 1; i <= n; i++)
    {
        int n1 = rand() % maxp + 1;  //随机生成来取包裹的人
        file.open("收件人信息.txt", ios::in);
        if (file.fail())
        {
            cout << "收件人信息.txt文件打开失败" << endl;
            exit(0);
        }
        for (int k = 1; k <= n1 && !file.eof(); k++)
        {
            file.getline(str, 100);
        }
        int t = 0, ln = 0, lp = 0;
        for (int k = 0; k < strlen(str); k++)  //处理文本文件,获取随机选中的收件人的姓名和手机号
        {
            if (!t)
            {
                if (str[k] == ' ')
                {
                    t = 1;
                    strn[ln] = '\0';
                }
                else
                {
                    strn[ln] = str[k];
                    ln++;
                }
            }
            else
            {
                strp[lp] = str[k];
                lp++;
            }
        }
        strp[lp] = '\0';
        file1.open("Package.dat", ios::in | ios::binary); //二进制读取文件中的包裹数据
        if (file1.fail())
        {
            cout << "Package.dat文件打开失败" << endl;
            exit(0);
        }
        file2.open("Empty.dat", ios::out | ios::binary);  //只写打开空白文件(辅助进行文件修改)
        if (file2.fail())
        {
            cout << "Empty.dat文件打开失败" << endl;
            exit(0);
        }
        int t1 = 0;
        int n2 = rand() % 2 + 1;   //随机生成查寻并取走所有包裹的方式
        if (n2 == 1)               //直接用手机号查询
        {
            file1.read((char*)&p, sizeof(p));
            while (!file1.eof())
            {
                if (strcmp(p.phone, strp) == 0 && p.condition == 0) //检测到该人未取的包裹
                {
                    p.condition = 1;         //调整包裹为已取状态
                    Vis[p.size][p.num] = 0;  //将货架的相应位置还原为0
                    N[p.size]++;
                    Delete(p);
                    cout << "取件码:" << p.code << "\t";
                    cout << "取件人姓名:" << setw(10) << p.name;
                    cout << "取件人手机号:" << p.phone << "\t";
                    cout << "取件日期:" << today << "\n";
                    sum++;
                    t1 = 1;                   //改变了文件内容,之后需修改文件
                }
                file2.write((char*)&p, sizeof(p));
                file1.read((char*)&p, sizeof(p));
            }
        }
        else   //用取件码查询
        {
            int s = 0;
            char str1[15];
            file1.read((char*)&p, sizeof(p));
            while (!file1.eof())
            {
                if (!s && strcmp(p.name, strn) == 0 && p.condition == 0) //找到一个该人未取的包裹
                {
                    strcpy(str1, p.phone);  //记下手机号
                    s = 1;
                }
                if (s && strcmp(p.phone, str1) == 0 && p.condition == 0)
                {
                    p.condition = 1;         //调整包裹为已取状态
                    Vis[p.size][p.num] = 0;  //将货架的相应位置还原为0
                    N[p.size]++;
                    Delete(p);
                    cout << "取件码:" << p.code << "\t";
                    cout << "取件人姓名:" << p.name << "\t";
                    cout << "取件人手机号:" << p.phone << "\t";
                    cout << "取件日期:" << today << "\n";
                    sum++;
                    t1 = 1;                  //改变了文件内容,之后需修改文件
                }
                file2.write((char*)&p, sizeof(p));
                file1.read((char*)&p, sizeof(p));
            }
        }
        file1.close();
        file2.close();
        if (t1)      //修改Package.dat
        {
            file1.open("Package.dat", ios::out | ios::binary); //只写覆盖打开Package.dat
            file2.open("Empty.dat", ios::in | ios::binary);    //只读打开空白文件
            if (file1.fail())
            {
                cout << "Package.dat文件打开失败" << endl;
                exit(0);
            }
            if (file2.fail())
            {
                cout << "Empty.dat文件打开失败" << endl;
                exit(0);
            }
            file2.read((char*)&p, sizeof(p));
            while (!file2.eof())
            {
                file1.write((char*)&p, sizeof(p));
                file2.read((char*)&p, sizeof(p));
            }
            file1.close();
            file2.close();
        }
        file.close();
        file1.close();
        file2.close();
    }
    cout << "今日被取走的包裹数:" << sum << endl;
}

//统计一些基本情况
void Count()
{
    fstream file, file1;
    Package p;
    char str[100], strn[20];
    int n = 1;    //保存今天收件最多的人
    float sum = 0;  //统计今天的收件数
    int man = 0;  //统计今天的收件人数  
    for (int i = 1; i <= maxp; i++)
    {
        sum += People[i];
        if (People[i] > 0)
        {
            man++;
        }
        if (People[i] > People[n])
        {
            n = i;
        }
    }
    file.open("收件人信息.txt", ios::in);
    if (file.fail())
    {
        cout << "收件人信息.txt文件打开失败" << endl;
        exit(0);
    }
    for (int k = 1; k <= n && !file.eof(); k++)
    {
        file.getline(str, 100);
    }
    int ln = 0;
    for (int k = 0; str[k] != ' '; k++)  //处理文本文件,获取当天收件最多的人的姓名
    {
        strn[ln] = str[k];
        ln++;
    }
    strn[ln] = '\0';
    float aver = sum / man;
    cout << "当天收包裹数量最多的人为" << strn << " 共" << People[n] << "件" << endl;
    cout << "当天共收到包裹" << sum << "件" << endl;
    cout << "当天有包裹人的平均包裹数量为" << setprecision(2) << aver << endl;
    file1.open("Package.dat", ios::in | ios::binary); //只读打开Package.dat
    if (file1.fail())
    {
        cout << "Package.dat文件打开失败" << endl;
        exit(0);
    }
    int total = 0;  //统计一周内被退还的包裹数
    while (!file1.eof())
    {
        file1.read((char*)&p, sizeof(p));
        if (today - p.day < 7 && p.condition == 2)
        {
            total++;
        }
    }
    cout << "一周内被退回的包裹数量为" << total << endl;
    file.close();
    file1.close();
}

//查询人员过去三天的取件记录
void Find()
{
    fstream file;
    Package p;
    char s[20];
    cout << "\n请输入要查询的人员姓名:";
    cin >> s;
    file.open("Package.dat", ios::in | ios::binary); //只读打开Package.dat
    if (file.fail())
    {
        cout << "Package.dat文件打开失败" << endl;
        exit(0);
    }
    cout << endl;
    cout << s << "最近三天的收件记录:" << endl;
    int t = 0;
    while (!file.eof())
    {
        file.read((char*)&p, sizeof(p));
        if (strcmp(p.name, s) == 0 && p.condition == 1 && today - p.day <= 3)
        {
            t = 1;
            cout << p.day << "签收了编号为" << p.code << "的包裹" << endl;
        }
    }
    if (!t)
    {
        cout << s << "最近三天没有收件" << endl;
    }
    cout << endl;
    file.close();
}

//打印双向链表里的数据
void Print(Package* S, int n)
{
    cout.setf(ios::left);
    Package* p;
    p = S->next;
    if (p == NULL) {
        cout << "货架" << n << "为空" << endl;
    }
    else {
        while (p != NULL) {
            cout << "取件码:" << p->code << "\t";
            cout << "取件人姓名:" << setw(10) << p->name;
            cout << "取件人手机号:" << p->phone << "\t";
            cout << "到达日期:" << p->day << "\n";
            total++;
            p = p->next;
        }
    }
}

//展现目前三个货架上的快递
void Show()
{
    total = 0;
    cout << "\n货架1:" << endl;
    Print(Shelve[1], 1);
    cout << "\n货架2:" << endl;
    Print(Shelve[2], 2);
    cout << "\n货架3:" << endl;
    Print(Shelve[3], 3);
    cout << "\n共有" << total << "件包裹" << endl;
}

//清理Package.dat文件中的数据
void Clear()
{
    fstream file1, file2;
    Package p;
    file1.open("Package.dat", ios::in | ios::binary); //只读打开Package.dat
    file2.open("Empty.dat", ios::out | ios::binary);  //只写覆盖打开空白文件
    if (file1.fail())
    {
        //文件打开失败,说明没有可清理的数据
        file1.close();
        file2.close();
        return;
    }
    if (file2.fail())
    {
        cout << "Empty.dat文件打开失败" << endl;
        exit(0);
    }
    file1.read((char*)&p, sizeof(p));
    while (!file1.eof())
    {
        if (today - p.day <= 7)
        {
            file2.write((char*)&p, sizeof(p));
        }
        file1.read((char*)&p, sizeof(p));
    }
    file1.close();
    file2.close();
    file1.open("Package.dat", ios::out | ios::binary); //只写覆盖打开Package.dat
    file2.open("Empty.dat", ios::in | ios::binary);    //只读打开空白文件
    if (file1.fail())
    {
        cout << "Package.dat文件打开失败" << endl;
        exit(0);
    }
    if (file2.fail())
    {
        cout << "Empty.dat文件打开失败" << endl;
        exit(0);
    }
    file2.read((char*)&p, sizeof(p));
    while (!file2.eof())
    {
        file1.write((char*)&p, sizeof(p));
        file2.read((char*)&p, sizeof(p));
    }
    file1.close();
    file2.close();
}

以上便是我对这道题的看法,很高兴与大家分享。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值