头像

小小蒟蒻




在线 



// main.cpp
#include "CList.h"
#include "CFrame.h"

int main()
{
    CFrame frm;
    return frm.Start();
}
// CFrame.h
#pragma once
#include "CList.h"
#include "CDelete.h"
#include "CModify.h"
#include "CFind.h"
#include "CSort.h"

class CFrame
{
public:
    CFrame() : m_delete(m_list), m_modify(m_list), m_find(m_list), m_sort(m_list) { }
    int Start();
private:
    int Menu();
    void Input();
    void Output();
    void Load();
    void Save();
    void Delete();
    void Modify();
    void Find();
    void Sort();
    inline CList& Entry() { return m_list; }
private:
    CList m_list;
    CDelete m_delete;
    CModify m_modify;
    CFind m_find;
    CSort m_sort;
};
// CFrame.cpp
#include <sstream>
#include <cstdio>
#include <string>
#include "CFrame.h"
#include "CInput.h"

int CFrame::Start()
{
    Load();
    int n;
    while (n = Menu())
    {
        switch (n)
        {
        case 1:
            Output();
            break;
        case 2:
            Input();
            break;
        case 3:
            Delete();
            break;
        case 4:
            Modify();
            break;
        case 5:
            Find();
            break;
        case 6:
            Sort();
        }
    }
    Save();
    return 0;
}

int CFrame::Menu()
{
    system("cls");
    puts("\t***************************");
    puts("\t*     1、浏览所有信息     *");
    puts("\t*     2、添加信息         *");
    puts("\t*     3、删除信息         *");
    puts("\t*     4、修改信息         *");
    puts("\t*     5、查找信息         *");
    puts("\t*     6、排序             *");
    puts("\t*     0、退出             *");
    puts("\t***************************");
    cout << "\t\t请选择:";
    int i = 0;
    scanf_s("%d", &i);
    return i;
}

void CFrame::Output()
{
    Entry().PrintAll();
}

void CFrame::Load()
{
    Entry().Load();
}

void CFrame::Save()
{
    Entry().Save();
}

void CFrame::Delete()
{
    m_delete.Start();
}

void CFrame::Modify()
{
    m_modify.Start();
}

void CFrame::Find()
{
    m_find.Start();
}

void CFrame::Sort()
{
    m_sort.Start();
}

void CFrame::Input()
{
    CInput in;
    SData* pData = new SData;
    if (!pData) return;
    pData->id = in.InputId(m_list, true);
    char str[50];
    in.InputName(str, 50);
    strcpy_s(pData->str, sizeof(pData->str), str);
    pData->pay = in.InputPay();
    Entry().PushBack(pData);
}
// CList.h
#pragma once
#include <iostream>
#include <string>
const int NAME_LEN = 20;
using namespace std;

enum ECompare { less = -1, equal = 0, greate = 1 };
enum ECompType { nothing = 0, id = 1, name = 2, pay = 3 };
enum ESortType { inc = ECompare::greate, dec = ECompare::less };

struct SParam
{
    SParam() { memset(this, 0, sizeof(SParam)); }
    int id;
    int idChange;
    bool bCmpNameDim;
    char str[NAME_LEN];
    char strChange[NAME_LEN];
    double payLow;
    double payUp;
    double pay;
    double payChange;
    bool bSortType;
};

struct SData
{
    int id;
    char str[NAME_LEN];
    double pay;
};

class CCompare
{
public:
    CCompare(SData* pData) : pInfo(pData) { }
    ~CCompare() { }
    ECompare operator()(const SParam& param);
    ECompType check(const SParam& param);
    void set(SData* pData) { pInfo = pData; }
private:
    SData* pInfo;
};

struct SNode
{
    SNode() : data(NULL), pred(NULL), succ(NULL) { }
    SNode(SData* const pPerson, SNode* pPred, SNode* pSucc)
        : data(pPerson), pred(pPred), succ(pSucc) { }
    SNode* AddAsPred(SData* d);
    SNode* AddAsSucc(SData* d);
    SData* data;
    SNode* pred;
    SNode* succ;
};

class CList
{
public:
    CList() { Init(); }                      // 默认构造函数
    CList(SNode* pNode, int n);              // 部分复制的构造函数
    CList(const CList& list, int r, int n);  // 部分复制的构造函数
    CList(const CList& list);                // 全部复制的构造函数 
    ~CList();                                // 析构函数
public:
    inline const bool Valid(SNode* pNode) const               // 节点有效性判断函数
    { return (pNode && pNode != m_head && pNode != m_tail); }
    inline const int Size() const { return m_size; }          // 返回链表的节点个数
    inline const bool Empty() const { return m_size <= 0; }   // 链表判空
    inline SNode* Head() const { return m_head; }             // 获取表头的地址
    inline SNode* Tail() const { return m_tail; }             // 获取表位的地址
    inline SNode* First() const;                              // 获取首个有效节点的地址 
    inline SNode* Last()  const;                              // 获取末个有效节点的地址
    inline void PrintTable() const;                           // 打印信息表头
    inline void PrintInformaion(SNode* pNode) const;          // 打印一条信息
    void PrintAll() const;                                    // 打印全部信息
    inline SNode* PushFront(SData* pPerson);                  // 新节点从首位压入
    inline SNode* PushBack(SData* pPerson);                   // 新节点从末尾压入
    inline void PopFront(); 
    inline void PopBack();
    void Remove(const SParam& param, ECompare nRule = ECompare::equal, bool bAllSame = false);       // 删除 
    int Find(const SParam& param, ECompare nRule = ECompare::equal, bool bAllSame = false) const;    // 查找
    void Modify(const SParam& param, ECompare nRule = ECompare::equal, bool bAllSame = false);       // 修改
    void Sort(ECompType nType, ESortType nRule);
    SNode* operator[](int r) const;                                               // 秩转地址
    const CList& operator=(const CList& list);                                    // 链表赋值
    void Load();
    void Save();
private:
    inline void Init();                                                      // 构造辅助函数
    void CopyNodes(SNode* pNode, int n);                                     // 复制辅助函数
    inline void Remove(SNode* pNode);                                        // 删除一个节点 
    void RemoveAll();                                                        // 删除所有节点
    void Modify(CCompare& comp, const SParam& param, SData& person);         // 修改一个节点的信息
private:
    int m_size;      // 有效节点的总数
    SNode* m_head;   // 头指针,指向头部的哨兵节点
    SNode* m_tail;   // 尾指针,指向尾部的哨兵节点
};
// CList.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "CList.h"
#include <string>
/////////////////////////////////////////////
// 处理比较的函数对象

ECompare CCompare::operator()(const SParam& param)
{
    if (check(param) == ECompType::id)
    {
        if (param.id < pInfo->id) 
            return ECompare::greate;  // 找出比参数id大的节点
        if (param.id == pInfo->id)
            return ECompare::equal;  // 找出与参数id相等的节点
        if (param.id > pInfo->id)
            return ECompare::less;   // 找出比参数id小的节点
    }
    if (check(param) == ECompType::name)
    {
        const char* str1 = pInfo->str;
        const char* str2 = param.str;
        if (param.bCmpNameDim)
        {
            if (strstr(str1, str2) == NULL) 
                return ECompare::less;
            return ECompare::equal;
        }
        else
        {
            if (strcmp(str1, str2) < 0) return ECompare::less;
            else if (!strcmp(str1, str2)) return ECompare::equal;
            else return ECompare::greate;
        }
    }
    if (check(param) == ECompType::pay)
    {
        if (pInfo->pay < param.payLow)
            return ECompare::greate;
        if (pInfo->pay >= param.payLow && pInfo->pay <= param.payUp)
            return ECompare::equal;
        if (pInfo->pay > param.payUp)
            return ECompare::less;
    }
    return ECompare::equal;
}

ECompType CCompare::check(const SParam& param)
{
    if (param.id != 0) 
        return ECompType::id;
    if (strlen(param.str) > 0) 
        return ECompType::name;
    if (param.payLow > 0 && param.payUp > 0 && param.payLow <= param.payUp)
        return ECompType::pay;
    return ECompType::nothing;
}

//////////////////////////////////////
// 一个节点作为另一个节点的前驱
SNode* SNode::AddAsPred(SData* pData)
{
    auto x = new SNode(pData, pred, this);
    if (!x) return NULL;
    pred->succ = x;
    pred = x;
    return x;
}

//////////////////////////////////////
// 一个节点作为另一个节点的后继
SNode* SNode::AddAsSucc(SData* pData)
{
    auto x = new SNode(pData, this, succ);
    if (!x) return NULL;
    succ->pred = x;
    succ = x;
    return x;
}

// CList的默认构造函数
CList::CList(SNode* pNode, int n)
{
    CopyNodes(pNode, n);
}

// 对另外一个链表进行复制构的造函数
CList::CList(const CList& list)
{
    CopyNodes(list.Head(), list.Size());
}

// 对另外一个链表进行部分复制的构造函数
CList::CList(const CList& list, int r, int n)
{
    CopyNodes(list[r], n);
}

// 构造辅助函数
void CList::Init()
{
    m_head = new SNode;
    m_tail = new SNode;

    m_tail->succ = NULL;
    m_tail->pred = m_head;
    m_head->succ = m_tail;
    m_head->pred = NULL;
    m_size = 0;
}

// 复制构造辅助函数
void CList::CopyNodes(SNode* pNode, int n)
{
    Init();
    for (int i = 0; i < n; i++, pNode = pNode->succ)
        PushBack(pNode->data);
}

CList::~CList()
{
    RemoveAll();
    delete m_head;
    delete m_tail;
}

void CList::PrintTable() const
{
    if (Empty())
    {
        puts("记录中没有任何信息");
        return;
    }
    printf("%-10s %-10s %-10s\n", "编号", "姓名", "工资");
}

void CList::PrintInformaion(SNode* pNode) const
{
    if (pNode->data == nullptr) return;
    printf("%-10d %-10s %-8.2lf \n", pNode->data->id, pNode->data->str, pNode->data->pay);
}

void CList::PrintAll() const
{
    PrintTable();
    for (auto p = First(); p && p != Tail(); p = p->succ)
        PrintInformaion(p);
    system("pause");
}

inline SNode* CList::First() const
{
    if (!Empty())
        return m_head->succ;
    return NULL;
}
inline SNode* CList::Last()  const
{
    if (!Empty())
        return m_tail->pred;
    return NULL;
}

inline SNode* CList::PushFront(SData* pData)
{
    m_size++;
    return m_head->AddAsSucc(pData);
}

inline SNode* CList::PushBack(SData* pData)
{
    m_size++;
    return m_tail->AddAsPred(pData);
}

inline void CList::PopFront()
{
    if (m_size <= 0) 
        return;
    Remove(First());
}

inline void CList::PopBack()
{
    if (m_size <= 0)
        return;
    Remove(Last());
}

SNode* CList::operator[](int r) const
{
    auto pNode = m_head->succ;
    for (int i = 0; i < r; i++, pNode = pNode->succ);
    return pNode;
}

const CList& CList::operator=(const CList& list)
{
    if (this == &list) return *this;       // 复制自己直接返回*this
    RemoveAll();                           // 清空节点
    CopyNodes(list.First(), list.Size());  // 复制list的所有节点
    return *this;                          // 复制完成返回*this
}

int CList::Find(const SParam& param, ECompare nRule, bool bAllSame) const
{
    int cnt = 0;
    PrintTable();
    for (auto p = First(); p && p != Head() && p != Tail(); p = p->succ)
    {
        CCompare comp(p->data);
        if (comp.operator()(param) == nRule)
        {
            PrintInformaion(p);
            cnt++;
            if (!bAllSame)
            {
                puts("找到一条符合条件的信息");
                system("pause");
                return 1;
            }
        }
    }
    printf("一共找到[ %d ]条符合条件的信息\n", cnt);
    system("pause");
    return cnt;
}

void CList::Modify(CCompare& comp, const SParam& param, SData& data)
{
    if (comp.check(param) == ECompType::id)
        data.id = param.idChange;
    else if (comp.check(param) == ECompType::name)
        strcpy_s(data.str, NAME_LEN, param.strChange);
    else if (comp.check(param) == ECompType::pay)
        data.pay = param.payChange;
    else if (comp.check(param) == ECompType::nothing)
        return;
}

void CList::Modify(const SParam& param, ECompare nRule, bool bAllSame)
{
    int cnt = 0;
    PrintTable();
    for (auto p = m_head->succ; p && p != m_tail; p = p->succ)
    {
        CCompare comp(p->data);
        if (comp.operator()(param) == nRule)
        {
            cnt++;
            puts("修改前后的信息");
            PrintInformaion(p);
            Modify(comp, param, *p->data);
            PrintInformaion(p);
            puts("");
            if (!bAllSame)
            {
                puts("修改一条符合条件的信息");
                system("pause");
                return;
            }
        }
    }
    printf("一共修改[ %d ]条符合条件的信息\n", cnt);
    system("pause");
}

void CList::Remove(const SParam& param, ECompare nRule, bool bAllSame) {
    if (!First()) return;
    int nSize = Size();
    PrintTable();
    for (auto p = First(); p && p != Head() && p!= Tail(); p = p->succ) {
        CCompare comp(p->data);
        auto q = p->pred;        
        if (comp.operator()(param) == nRule) {
            PrintInformaion(p);  // 删除前对信息打印
            Remove(p);
            if (!bAllSame) return;
            p = q;
        }
    }
    printf("一共删除[ %d ]条符合条件的信息\n", nSize - Size());
    system("pause");
}

void CList::Remove(SNode* pNode)
{
    pNode->succ->pred = pNode->pred;
    pNode->pred->succ = pNode->succ;
    delete pNode->data;  
    delete pNode;
    pNode = NULL;
    m_size--;
}

void CList::RemoveAll()
{
    while (!Empty()) 
        Remove(m_head->succ);
}


void CList::Load()
{
    FILE* fp;
    errno_t err = fopen_s(&fp, "test.bin", "rb");
    if (err || !fp) {
        perror("\t错误");
        return;
    } 
    int n = 0;
    int ans = fread(&n, sizeof(int), 1, fp);
    if (ans < 1 || !n)
    {
        perror("\t错误");
        return;
    }
    for (int i = 0; i < n; i++) 
    {
        SData* pData = new SData;
        if (!pData) return;
        int n = fread(pData, sizeof(SData), 1, fp);
        PushBack(pData);
    }
    fclose(fp);
}

void CList::Save()
{
    if (Empty()) return;
    FILE* fp;
    errno_t err = fopen_s(&fp, "test.bin", "wb");
    if (!fp || err)
    {
        perror("\t错误");
        return;
    }
    int ans = fwrite((const void*)&m_size, sizeof(int), 1, fp);
    if(ans < 1) 
    {
        perror("\t错误");
        return;
    }
    while (!Empty())
    {
        ans = fwrite((const void*)&(*(First()->data)), sizeof(SData), 1, fp);
        if (ans < 1)
        {
            perror("\t错误");
            return;
        }
        PopFront();
    }
    fclose(fp); 
}

template<typename T>
bool compare(T a, T b, ECompare nRule)
{
    if(ECompare::less == nRule) return a < b;
    if (ECompare::equal == nRule) return a == b;
    if (ECompare::greate == nRule) return a > b;
    return false;
}

template<>
bool compare(char* a, char* b, ECompare nRule)
{
    if (ECompare::less == nRule) return strcmp((const char*)a, (const char*)b) == -1;
    if (ECompare::equal == nRule) return strcmp((const char*)a, (const char*)b) == 0;
    if (ECompare::greate == nRule) return strcmp((const char*)a, (const char*)b) == 1;
    return false;
}

void CList::Sort(ECompType nType, ESortType nRule)
{
    for (auto p = First(); p != Tail(); p = p->succ) {
        auto min = p;
        for (auto q = First(); q != Tail(); q = q->succ) {
            if (nType == ECompType::id) {
                if (compare(q->data->id, min->data->id, (ECompare)nRule))
                    min = q;
            }
            else if (nType == ECompType::name) {
                if (compare(q->data->str, min->data->str, (ECompare)nRule))
                    min = q;
            }
            else if (nType == ECompType::pay) {
                if (compare(q->data->pay, min->data->pay, (ECompare)nRule))
                    min = q;
            }
            SData** x = &min->data;
            SData** y = &p->data;
            SData* t = *x;
            *x = *y;
            *y = t;
        }
    }
    PrintAll();
}
// CInput.h 
#pragma once
#include "CList.h"
const int MAX_LEN = 1024;

class CInput
{
public:
    bool CheckId(int nId, CList& list, bool bCheck);
    int InputId(CList& list, bool bCheck = false);
    void InputName(char* str, int n);
    double InputPay();
    void  CheckInput(char* str, int n, bool bCheckAlpha,
        const char* buf1, const char* buf2);
    void Str2Digit(const char* buf, bool bInt, int& nId, double& fPay);
};
// CInput.cpp
#include "CInput.h"
#include <sstream>
#include <cstdio>
#include "CFrame.h"
#include <string>
using namespace std;

bool CInput::CheckId(int nId, CList& list, bool bCheck)
{
    if (!bCheck) return false;
    for (auto p = list.First(); p && p != list.Tail(); p = p->succ)
        if (p->data->id == nId) return true;
    return false;
}

int CInput::InputId(CList& list, bool bCheck)
{
    char buf[MAX_LEN];
Lab:
    CheckInput(buf, MAX_LEN, true, "请输入员工的编号",
        "请正确输入员工的编号,不含有字母与符号");
    double x = 0.0f;
    int nId = 0;
    Str2Digit(buf, true, nId, x);
    if (CheckId(nId, list, bCheck))
    {
        puts("请正确输入员工的编号,不能用相同的数字做编号");
        goto Lab;
    }
    return nId;
}

void CInput::InputName(char* str, int n)
{
    char buf[MAX_LEN];
Lab:
    CheckInput(buf, MAX_LEN, false, "请输入员工的姓名:",
        "请正确输入员工的姓名,不含有数字与符号");
    if (strlen(buf) > 50)
    {
        puts("请输入员工姓名的字符数小于50个字符");
        goto Lab;
    }
    strcpy_s(str, n, buf);
}

double CInput::InputPay()
{
    char buf[MAX_LEN];
Lab:
    CheckInput(buf, MAX_LEN, true, "请输入员工的工资",
        "请正确输入员工的工资,不含有字母与符号");
    double fPay = 0.0f;
    int x = 0;
    Str2Digit(buf, false, x, fPay);
    if (fPay <= 0 || fPay > 1e8)
    {
        puts("请正确输入工资,金额非负");
        goto Lab;
    }
    return fPay;
}

void CInput::CheckInput(char* str, int n, bool bCheckAlpha,
    const char* buf1, const char* buf2)
{
    cin.sync_with_stdio(false);
    while (1)
    {
        puts(buf1);
        rewind(stdin);
        cin.getline(str, n, '\n');  // 读取一行数据到字符串
        bool bValid = true;        // 假定读入有效 
        for (int i = 0; str[i] != '\0'; i++)
        {
            if (bCheckAlpha)
            {
                if (isalpha(str[i]) || ispunct(str[i]))
                {
                    puts(buf2);
                    bValid = false;
                    break;
                }
            }
            else if (isdigit(str[i]) || ispunct(str[i]))
            {
                puts(buf2);
                bValid = false;
                break;
            }
        }
        if (!bValid)
        {
            memset(str, 0, MAX_LEN);
            continue;
        }
        break;
    }
}

void CInput::Str2Digit(const char* buf, bool bInt, int& nId, double& fPay)
{
    stringstream ss;
    string str = buf;
    ss << str;
    if (bInt) ss >> nId;
    else ss >> fPay;
    ss.clear();
}
// CDelete.h
#pragma once
#include "CList.h"

class CDelete
{
public:
    CDelete(CList& list) : m_list(list) { }
    int Start();
private:
    int Menu();
    void RemoveId();
    void RemoveName();
    void RemovePay();
private:
    CList& m_list;
};
// CDelete.cpp
#include "CDelete.h"
#include "CInput.h"
#include "CList.h"
#include <string.h>

int CDelete::Start()
{
    int n;
    while (n = Menu())
    {
        switch (n)
        {
        case 1:
            RemoveId();
            break;
        case 2:
            RemoveName();
            break;
        case 3:
            RemovePay();
            break;
        case 0:
            return 0;
        }
    }
    return 0;
}

int CDelete::Menu()
{
    system("cls");
    puts("\t***************************");
    puts("\t*     删  除  菜  单      *");
    puts("\t*     1、按员工编号       *");
    puts("\t*     2、按姓名           *");
    puts("\t*     3、按工资范围       *");
    puts("\t*     0、退出             *");
    puts("\t***************************");
    cout << "\t\t请选择:";
    int i = 0;
    scanf_s("%d", &i);
    return i;
}

void CDelete::RemoveId()
{
    while (1)
    {
        system("cls");
        puts("\t***********************************");
        puts("\t*       编  号  删  除  菜  单    *");
        puts("\t*     1、删除小于输入编号的信息   *");
        puts("\t*     2、删除等于输入编号的信息   *");
        puts("\t*     3、删除大于输入编号的信息   *");
        puts("\t*     0、退出                     *");
        puts("\t***********************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        int id = in.InputId(m_list, false);
        auto p = m_list.First();
        for (; p && p != m_list.Tail(); p = p->succ)
            if (p->data->id == id) break;
        if (p == NULL) return;
        SParam param;
        param.id = id;
        bool bAllSame;
        ECompare comp;
        if (i == 1) comp = ECompare::less, bAllSame = true;
        else if (i == 2) comp = ECompare::equal, bAllSame = false;
        else if (i == 3) comp = ECompare::greate, bAllSame = true;
        m_list.Remove(param, comp, bAllSame);
    }
}

void CDelete::RemoveName()
{
    while (1)
    {
        system("cls");
        puts("\t***************************");
        puts("\t*  姓  名  删  除  菜  单 *");
        puts("\t*     1、按姓名精确删除   *");
        puts("\t*     2、按姓名模糊删除   *");
        puts("\t*     0、退出             *");
        puts("\t***************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        char buf[MAX_LEN];
        in.InputName(buf, NAME_LEN);
        SParam param;
        memset((void*)&param, 0, sizeof(SParam));
        strcpy_s(param.str, NAME_LEN, buf);
        bool bAllSame;
        if (i == 1) bAllSame = false;
        else param.bCmpNameDim = true, bAllSame = true;
        m_list.Remove(param, ECompare::equal, bAllSame);
    }
}

void CDelete::RemovePay()
{
    while (1)
    {
        system("cls");
        puts("\t*******************************");
        puts("\t*   工  资  删  除  菜  单    *");
        puts("\t*     1、按范围删除一人       *");
        puts("\t*     2、删除范围内的所有人   *");
        puts("\t*     0、退出                 *");
        puts("\t*******************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        SParam param;
        memset((void*)&param, 0, sizeof(SParam));
        puts("输入要删除的工资范围");
        double low = in.InputPay();
        double up = in.InputPay();
        if (low > up) swap(low, up);
        param.payLow = low, param.payUp = up;
        if (i == 2) param.pay = in.InputPay();
        m_list.Remove(param, ECompare::equal, true);
    }
}
//CFind.h
#pragma once
#include "CList.h"
#include "CInput.h"

class CFind
{
public:
    CFind(CList& list) : m_list(list) { }
    int Start();
    int Find_Menu();
    void FindId();
    void FindName();
    void FindPay();
private: 
    CList& m_list;
};
// CFind.cpp
#include "CFind.h"

int CFind::Start()
{
    int n;
    while (n = Find_Menu())
    {
        switch (n)
        {
        case 1:
            FindId();
            break;
        case 2:
            FindName();
            break;
        case 3:
            FindPay();
            break;
        case 0:
            return 0;
        }
    }
    return 0;
}

int CFind::Find_Menu()
{
    system("cls");
    puts("\t***************************");
    puts("\t*     修  改  菜  单      *");
    puts("\t*     1、按员工编号       *");
    puts("\t*     2、按姓名           *");
    puts("\t*     3、按工资范围       *");
    puts("\t*     0、退出             *");
    puts("\t***************************");
    cout << "\t\t请选择:";
    int i = 0;
    scanf_s("%d", &i);
    return i;
}

void CFind::FindId()
{
    CInput in;
    int id = in.InputId(m_list, false);
    SParam param;
    param.id = id;
    m_list.Find(param, ECompare::equal, false);
}

void CFind::FindName()
{
    while (1)
    {
        system("cls");
        puts("\t***************************");
        puts("\t*  姓  名  查  找  菜  单 *");
        puts("\t*     1、按姓名精确查找   *");
        puts("\t*     2、按姓名模糊查找   *");
        puts("\t*     0、退出             *");
        puts("\t***************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        char buf[MAX_LEN];
        in.InputName(buf, NAME_LEN);
        SParam param;
        strcpy_s(param.str, NAME_LEN, buf);
        bool bAllSame;
        if (i == 1) bAllSame = false;
        else param.bCmpNameDim = true, bAllSame = true;
        m_list.Find(param, ECompare::equal, bAllSame);
    }
}

void CFind::FindPay()
{
    while (1)
    {
        system("cls");
        puts("\t*******************************");
        puts("\t*   工  资  查  找  菜  单    *");
        puts("\t*     1、按范围查找一人       *");
        puts("\t*     2、查找范围内的所有人   *");
        puts("\t*     0、退出                 *");
        puts("\t*******************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        SParam param;
        memset((void*)&param, 0, sizeof(SParam));
        puts("输入要删除的工资范围");
        double low = in.InputPay();
        double up = in.InputPay();
        if (low > up) swap(low, up);
        param.payLow = low, param.payUp = up;
        bool AllSame;
        i == 1 ? AllSame = false : AllSame = true;
        m_list.Find(param, ECompare::equal, AllSame);
    }
}
// CModify.h
#pragma once
#include "CList.h"
#include "CInput.h"

class CModify
{
public:
    CModify(CList& list) : m_list(list) { }
    int Start();
    int Menu();
    void ModifyId();
    void ModifyName();
    void ModifyPay();
private:
    CList& m_list;
};
// CModify.cpp
#include "CModify.h"

int CModify::Start()
{
    int n;
    while (n = Menu())
    {
        switch (n)
        {
        case 1:
            ModifyId();
            break;
        case 2:
            ModifyName();
            break;
        case 3:
            ModifyPay();
            break;
        case 0:
            return 0;
        }
    }
    return 0;
}

int CModify::Menu()
{
    system("cls");
    puts("\t***************************");
    puts("\t*     修  改  菜  单      *");
    puts("\t*     1、按员工编号       *");
    puts("\t*     2、按姓名           *");
    puts("\t*     3、按工资范围       *");
    puts("\t*     0、退出             *");
    puts("\t***************************");
    cout << "\t\t请选择:";
    int i = 0;
    scanf_s("%d", &i);
    return i;
}

void CModify::ModifyId()
{
    CInput in;
    puts("输入要修改的员工原来的编号");
    int id = in.InputId(m_list, false);
    auto p = m_list.First();
    for (; p && p != m_list.Tail(); p = p->succ)
        if (p->data->id == id) break;
    if (p == NULL) return;
    puts("输入要修改的员工现在的编号");
    int idChange = in.InputId(m_list, false);
    SParam param;
    param.id = id;
    param.idChange = idChange;
    m_list.Modify(param, ECompare::equal, false);   // -1 大于 0 等于 1 小于
}

void CModify::ModifyName()
{
    while (1)
    {
        system("cls");
        puts("\t***************************");
        puts("\t*  姓  名  修  改  菜  单 *");
        puts("\t*     1、按姓名精确修改   *");
        puts("\t*     2、按姓名模糊修改   *");
        puts("\t*     0、退出             *");
        puts("\t***************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        char bufBefore[MAX_LEN], bufAfter[MAX_LEN];
        puts("输入想要修改的员工姓名");
        in.InputName(bufBefore, NAME_LEN);
        puts("输入想要改成的员工姓名");
        in.InputName(bufAfter, NAME_LEN);
        SParam param;
        param.bCmpNameDim = false;
        strcpy_s(param.str, NAME_LEN, bufBefore);
        strcpy_s(param.strChange, NAME_LEN, bufAfter);
        bool bAllSame;
        if (i == 1) bAllSame = false;
        else param.bCmpNameDim = true, bAllSame = true;
        m_list.Modify(param, ECompare::equal, bAllSame);
    }
}

void CModify::ModifyPay()
{
    while (1)
    {
        system("cls");
        puts("\t*******************************");
        puts("\t*   工  资  修  改  菜  单    *");
        puts("\t*     1、按范围修改一人       *");
        puts("\t*     2、修改范围内的所有人   *");
        puts("\t*     0、退出                 *");
        puts("\t*******************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        CInput in;
        SParam param;
        puts("输入要修改的工资范围的下限");
        double low = in.InputPay();
        puts("输入要修改的工资范围的上限");
        double up = in.InputPay();
        puts("输入要修改成的工资金额");
        double payChange = in.InputPay();
        if (low > up) swap(low, up);
        param.bCmpNameDim = false, param.payLow = low;
        param.payUp = up, param.payChange = payChange;
        bool bAllSame;
        i == 1 ? bAllSame = false : bAllSame = true;
        m_list.Modify(param, ECompare::equal, bAllSame);
    }
}
//CSort.h
#pragma once
#include "CList.h"

class CSort
{
public:
    CSort(CList& list) : m_list(list) { }
    int Start();
private:
    int Menu();
    void SortId();
    void SortName();
    void SortPay();
private:
    CList& m_list;

};
//CSort.cpp
#include "CSort.h"
#include "CInput.h"
#include "CList.h"

int CSort::Menu()
{
    system("cls");
    puts("\t***************************");
    puts("\t*     排  序  菜  单      *");
    puts("\t*     1、按员工编号       *");
    puts("\t*     2、按姓名           *");
    puts("\t*     3、按工资           *");
    puts("\t*     0、退出             *");
    puts("\t***************************");
    cout << "\t\t请选择:";
    int i = 0;
    scanf_s("%d", &i);
    return i;
}

int CSort::Start()
{
    int n;
    while (n = Menu())
    {
        switch (n)
        {
        case 1:
            SortId();
            break;
        case 2:
            SortName();
            break;
        case 3:
            SortPay();
            break;
        case 0:
            return 0;
        }
    }
    return 0;
}

void CSort::SortId()
{
    while (1)
    {
        system("cls");
        puts("\t***************************");
        puts("\t*  姓  名  删  除  菜  单 *");
        puts("\t*     1、按编号升序排序   *");
        puts("\t*     2、按编号降序排序   *");
        puts("\t*     0、退出             *");
        puts("\t***************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        if (i == 1) m_list.Sort(ECompType::id, ESortType::inc);
        else if(i == 2) m_list.Sort(ECompType::id, ESortType::dec);
    }
}

void CSort::SortName()
{
    while (1)
    {
        system("cls");
        puts("\t***************************");
        puts("\t*  姓  名  删  除  菜  单 *");
        puts("\t*     1、按姓名升序排序   *");
        puts("\t*     2、按姓名降序排序   *");
        puts("\t*     0、退出             *");
        puts("\t***************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        if (i == 1) m_list.Sort(ECompType::name, ESortType::inc);
        else if (i == 2) m_list.Sort(ECompType::name, ESortType::dec);
    }
}

void CSort::SortPay()
{
    while (1)
    {
        system("cls");
        puts("\t*******************************");
        puts("\t*   工  资  排  序  菜  单    *");
        puts("\t*     1、按工资升序排序       *");
        puts("\t*     2、按工资降序排序       *");
        puts("\t*     0、退出                 *");
        puts("\t*******************************");
        cout << "\t\t请选择:";
        int i = 0;
        scanf_s("%d", &i);
        if (i == 0) return;
        if (i == 1) m_list.Sort(ECompType::pay, ESortType::inc);
        else if (i == 2) m_list.Sort(ECompType::pay, ESortType::dec);
    }
}



// CList.h
#pragma once
#include <iostream>
using namespace std;

struct __POSITION { };
typedef __POSITION* POSITION;

typedef void (*PRINT) (void*);

template<typename TYPE, typename ARG_TYPE = const TYPE&>
class CList
{
protected:
    struct CNode
    {
        CNode* pNext;
        CNode* pPrev;
        TYPE data;
    };
public:
    // Construction
    CList() : m_pHead(nullptr), m_pTail(nullptr), m_nCount(0) { }

    // Attributes (head and tail)
        // count of elements
    int GetCount() const { return m_nCount; }
    bool IsEmpty() const { return m_nCount <= 0; }

    // peek at head or tail
    TYPE& GetHead() { return m_pHead->data; }
    const TYPE& GetHead() const { return m_pHead->data; }
    TYPE& GetTail() { return m_pTail->data; }
    const TYPE& GetTail() const { return m_pTail->data; }

    // Operations
        // get head or tail (and remove it) - don't call on empty list !
    void RemoveHead();
    void RemoveTail();

    // add before head or after tail
    POSITION AddHead(ARG_TYPE newElement);
    POSITION AddTail(ARG_TYPE newElement);

    // add another list of elements before head or after tail
    void AddHead(CList* pNewList);
    void AddTail(CList* pNewList);

    // remove all elements
    void RemoveAll();

    // iteration
    POSITION GetHeadPosition() const { return (POSITION)m_pHead; }
    POSITION GetTailPosition() const { return (POSITION)m_pTail; }
    TYPE& GetNext(POSITION& rPosition); 
    const TYPE& GetNext(POSITION& rPosition) const; // return *Position++
    TYPE& GetPrev(POSITION& rPosition);
    const TYPE& GetPrev(POSITION& rPosition) const; // return *Position--

    // getting/modifying an element at a given position
    TYPE& GetAt(POSITION position);
    const TYPE& GetAt(POSITION position) const;
    void SetAt(POSITION pos, ARG_TYPE newElement);
    void RemoveAt(POSITION position);
    void Remove(CList<TYPE, ARG_TYPE>& list, ARG_TYPE arg, bool bDelSame = false);

    // inserting before or after a given position
    POSITION InsertBefore(POSITION position, ARG_TYPE newElement);
    POSITION InsertAfter(POSITION position, ARG_TYPE newElement);

    // helper functions (note: O(n) speed)
    POSITION Find(ARG_TYPE searchValue, POSITION startAfter = nullptr) const;
    // defaults to starting at the HEAD, return NULL if not found
    POSITION FindIndex(int nIndex) const;
    void Print(int s, int e) const;
    // get the 'nIndex'th element (may return NULL)
// Implementation
protected:
    CNode* m_pHead;
    CNode* m_pTail;
    int m_nCount;
    CNode* NewNode(ARG_TYPE newElement)
    {
        CNode* p = new CNode;
        if (p == nullptr) return nullptr;
        p->pPrev = p->pNext = nullptr;
        p->data = newElement;
        return p;
    }
public:
    ~CList() { 
        cout << "CList has been destroy\n";
        RemoveAll(); 
    }
};


template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::RemoveHead()
{
    if (m_pHead == nullptr) return;
    else {
        CNode* p = m_pHead;
        m_pHead = m_pHead->pNext;
        m_pHead->pPrev = nullptr;
        delete p;
    }
}

template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::RemoveTail()
{
    if (m_pTail == nullptr) return;
    else {
        CNode* p = m_pTail;
        m_pTail = m_pTail->pPrev;
        m_pTail->pNext = nullptr;
        delete p;
    }
} 

template<class TYPE, class ARG_TYPE>
inline POSITION CList<TYPE, ARG_TYPE>::AddHead(ARG_TYPE newElement)
{
    CNode* p = NewNode(newElement);
    if(IsEmpty()) m_pHead = m_pTail = p;
    else 
    {
        p->pNext = m_pHead;
        p->pNext->pPrev = p;
        m_pHead = p;
    }
    m_nCount++;
    return (POSITION)p;
}

template<class TYPE, class ARG_TYPE>
inline POSITION CList<TYPE, ARG_TYPE>::AddTail(ARG_TYPE newElement)
{
    CNode* p = NewNode(newElement);
    if (IsEmpty()) m_pHead = m_pTail = p;
    else
    {
        p->pPrev = m_pTail;
        p->pPrev->pNext = p;
        m_pTail = p;
    }
    m_nCount++;
    return (POSITION)p;
}

template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::AddHead(CList* pNewList)
{
    if (pNewList->IsEmpty()) return;
    for (auto p = pNewList->GetTailPosition(); p != nullptr; pNewList->GetPrev(p))
    {
        CNode* q = NewNode(pNewList->GetAt(p));
        if (q == nullptr) return;
        q->data = ((CNode*)p)->data;
        AddHead(q->data);
    }

}

template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::AddTail(CList* pNewList)
{
    if (pNewList == nullptr) return;
    for (auto p = pNewList->GetHeadPosition(); p != nullptr; pNewList->GetNext(p))
    {
        CNode* q = NewNode(pNewList->GetAt(p));
        if (!q) return;
        q->data = ((CNode*)p)->data;
        AddTail(q->data);
    }
}

template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::RemoveAll()
{
    if (!IsEmpty()) RemoveHead();
    m_nCount = 0;
    m_pHead = m_pTail = nullptr;
}

template<class TYPE, class ARG_TYPE>
inline TYPE& CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition)
{
    TYPE& t = ((CNode*)rPosition)->data;
    rPosition = (POSITION)(((CNode*)rPosition)->pNext);
    return t;
}

template<class TYPE, class ARG_TYPE>
inline const TYPE& CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) const
{
    TYPE& t = ((CNode*)rPosition)->data;
    rPosition = (POSITION)((CNode*)rPosition)->pNext;
    return t;
}

template<class TYPE, class ARG_TYPE>
inline TYPE& CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition)
{
    TYPE& t = ((CNode*)rPosition)->data;
    rPosition = (POSITION)((CNode*)rPosition)->pPrev;
    return t;
}

template<class TYPE, class ARG_TYPE>
inline const TYPE& CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) const
{
    TYPE& t = ((CNode*)rPosition)->data;
    rPosition = ((CNode*)rPosition)->pPrev;
    return t;
}

template<class TYPE, class ARG_TYPE>
inline TYPE& CList<TYPE, ARG_TYPE>::GetAt(POSITION position)
{
    return ((CNode*)position)->data;
}

template<class TYPE, class ARG_TYPE>
inline const TYPE& CList<TYPE, ARG_TYPE>::GetAt(POSITION position) const
{
    return ((CNode*)position)->data;
}

template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::SetAt(POSITION pos, ARG_TYPE newElement)
{
    ((CNode*)pos)->data = newElement;
}

template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::RemoveAt(POSITION position)
{
    if (IsEmpty()) return;
    CNode* p = (CNode*)position;
    if (p == nullptr) return;
    if (p == m_pHead) {
        m_pHead = m_pHead->pNext;
        m_pHead->pPrev = nullptr;
    }
    else if (p == m_pTail) {
        m_pTail = m_pTail->pPrev;
        m_pTail->pNext = nullptr;
    }
    else {
        p->pNext->pPrev = p->pPrev;
        p->pPrev->pNext = p->pNext;
    }
    delete p;
}

template<typename TYPE, typename ARG_TYPE>
void CList<TYPE, ARG_TYPE>::Remove(CList<TYPE, ARG_TYPE>& list, ARG_TYPE arg, bool bDelSame) {
    POSITION p = list.GetHeadPosition();
    while (p) {
        auto q = p;
        list.GetNext(p);
        if (list.GetAt(q) == arg) {
            list.RemoveAt(q);
            if (!bDelSame) return;
        }
    }
}

template<class TYPE, class ARG_TYPE>
inline POSITION CList<TYPE, ARG_TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement)
{
    CNode* p = (CNode*)position;
    CNode* q = NewNode(newElement);
    if (p == nullptr || p == m_pHead) 
        AddHead(newElement);
    else {
        q->pNext = p;
        q->pPrev = p->pPrev;
        p->pPrev->pNext = q;
        p->pPrev = q;
        m_nCount++;
    }
    return (POSITION)p;
}

template<class TYPE, class ARG_TYPE>
inline POSITION CList<TYPE, ARG_TYPE>::InsertAfter(POSITION position, ARG_TYPE newElement)
{
    CNode* p = (CNode*)position;
    CNode* q = NewNode(newElement);
    if (p == nullptr || p == m_pTail)
        AddTail(newElement);
    else {
        q->pNext = p->pNext;
        q->pPrev = p;
        p->pNext->pPrev = q;
        p->pNext = q;
        m_nCount++;
    }
    return (POSITION)p;
}

#include <iostream>
template<class TYPE, class ARG_TYPE>
inline POSITION CList<TYPE, ARG_TYPE>::Find(ARG_TYPE searchValue, POSITION startAfter) const
{
    int cnt = 0;
    POSITION p = nullptr;
    startAfter == nullptr ? p = GetHeadPosition() : p = startAfter;
    p = GetHeadPosition();
    while (p) {
        if (GetAt(p) == searchValue)
            cnt++;
        GetNext(p);
    }
    std::cout << "找到" << cnt << "个" << "[ " << searchValue << " ]";
    return p;
}

template<class TYPE, class ARG_TYPE>
inline POSITION CList<TYPE, ARG_TYPE>::FindIndex(int nIndex) const
{
    if (nIndex < 0) return (POSITION)m_pHead;
    if (nIndex >= m_nCount) return (POSITION)m_pTail;
    POSITION p = GetHeadPosition();
    for (int i = 0; i < nIndex; i++, GetNext(p));
    return (POSITION)p;
}


template<class TYPE, class ARG_TYPE>
inline void CList<TYPE, ARG_TYPE>::Print(int s, int e) const
{
    if (s <= 0) s = 0;
    if (e >= m_nCount) e = m_nCount;
    for (int i = s; i < e; i++)
        cout << ((CNode*)FindIndex(i))->data << " ";
    cout << endl;
}
// test.h
#include "Clist.h"
#include <iostream>

void print(void* p) {
    if (p == nullptr) return;
    std::cout << *(int*)p << " ";
}

int main() {
    CList<int, const int&> l, l1;

    l.AddHead(1);

    l.AddHead(2);

    l.AddHead(3); 

    l.AddTail(4);

    l.AddTail(5);

    l.AddTail(6);

    l1.AddTail(9);

    l1.AddTail(9);

    l1.AddTail(7);

    l1.AddTail(9);

    l.AddTail(&l1);
    l.AddHead(&l1);
    l.Print(0, l.GetCount());

    POSITION p = l.GetHeadPosition();
    for (int i = 0; i < 3; i++) {
        l.InsertAfter(p, i);
    } 

    p = l.GetHeadPosition();
    for (int i = 0; i < 3; i++) {
        l.InsertBefore(p, i);
    } 

    l.Print(0, l.GetCount());

    l.Print(2, 5);
    return 0; 
}



// list.h
#include <memory>
#include <iostream>

template<typename T> struct node;  // node提前申明
#define ptr std::shared_ptr<node<T>>  

template<typename T> struct node {
    node() : succ(nullptr) {  }
    ~node() { std::cout << "[ " << data << " ] has auto released\n"; }
    node(T e) : data(e), succ(nullptr) { }
    ptr AsSucc(T const& e);
    ptr succ;
    T data;
};

template<typename T> inline ptr node<T>::AsSucc(T const& e) {
    ptr x = std::make_shared<node<T>>(e);
    if (x == nullptr) return nullptr;
    x->succ = succ;
    succ = x;
    return nullptr;
}


// list
template<typename T> class list {
public:
    list() { init(); }
    ~list() { std::cout << "list has been destroyed\n"; }
public:
    const int size() const { return m_size; }
    const bool empty() const { return m_size <= 0; }
    ptr PushFront(T const& e);
    ptr PushBack(T const& e);
    ptr InsertAsSucc(T const& e, ptr p);
    void PopFront();
    void PopBack();
    void Remove(T const& e, bool bDelSame);
    void travel();
private:
    void init();
    void Remove(ptr p);
    void remove_all();
    ptr tail();
    ptr pred_tail();
private:
    ptr m_head;
    int m_size;
};

template<typename T> void list<T>::init() {
    m_head = std::make_shared<node<T>>();
    if (m_head == nullptr) return;
    m_head->succ = nullptr;
    m_size = 0;
}

template<typename T> inline void list<T>::remove_all() {
    // 由于是智能指针,无需释放节点。
}

template<typename T> inline ptr list<T>::PushFront(T const& e) {
    m_size++;
    return m_head->AsSucc(e);
}

template<typename T> ptr list<T>::PushBack(T const& e) {
    auto p = tail();
    m_size++;
    return p->AsSucc(e);
}

template<typename T> ptr list<T>::InsertAsSucc(T const& e, ptr p) {
    m_size++;
    return p->AsSucc(e);
}

template<typename T> void list<T>::PopFront() {
    std::cout << "pop from front ";
    m_size--;
    ptr p = m_head->succ;
    m_head->succ = p->succ;
    p = nullptr;
}

template<typename T> void list<T>::PopBack() {
    std::cout << "pop from back ";
    m_size--;
    ptr p = pred_tail();
    if(p == nullptr) return;
    p->succ = nullptr;
    p = nullptr;
}

// 此处是删除当前节点的后继节点,传入的是当前节点的地址值
template<typename T> void list<T>::Remove(ptr p) {
    if (p == nullptr || p->succ == nullptr) return;
    auto q = p->succ;
    std::cout << "remove element ";
    p->succ = p->succ->succ;
    q->succ = nullptr;
    q = nullptr;
}

template<typename T> void list<T>::Remove(T const& e, bool bDelSame) {
    if (m_size <= 0) return;
    for (auto curr = m_head->succ; curr->succ != nullptr; curr = curr->succ)  {
        while (curr->data == e || curr->succ->data == e)  {
            if (curr->data == e)  {  // 当前节点恰好是要删的节点
                PopFront();          // 只有是头节点时,才符合此时的场景
                if (!bDelSame || (curr = m_head) == nullptr) // 更新判断当前节点
                    return;
            }
            else if (curr->succ->data == e) { // 当前节点的后继节点是要删除的节点
                Remove(curr);                 // 删除当前节点的后继节点
                if (!bDelSame || curr->succ == nullptr) // 更新判断当前节点
                    return;
            }
        }
    }
}

template<typename T> void list<T>::travel() {
    for (auto p = m_head->succ; p != nullptr; p = p->succ)
        std::cout << p->data << " ";
    std::cout << std::endl;
}

template<typename T> ptr list<T>::tail() {
    ptr tail = nullptr;
    for (tail = m_head; tail != nullptr && tail->succ != nullptr; tail = tail->succ);
    return tail;
}

// 可恶,没有指向前驱的指针,所以还得重新找尾节点的前驱 
template<typename T> ptr list<T>::pred_tail() {
    ptr pred = NULL;
    for (pred = m_head; pred != nullptr && pred->succ != nullptr 
        && pred->succ->succ != nullptr; pred = pred->succ);
    return pred;
}

// test.cpp
#include "list.h"

int main() {
    list<int> l;
    l.PushBack(3);
    l.PushBack(6);
    l.PushBack(3);
    l.PushBack(4);
    l.PushBack(5);
    l.PushBack(3);
    l.PushBack(4);
    l.PushBack(3);
    l.travel();
    l.Remove(3, true);
    l.Remove(4, true);
    l.travel();
    return 0;
}

测试结果:

test.png




https://en.cppreference.com/
http://www.cplusplus.com/



#include <memory>
#include <iostream>
#include <string>
using namespace std;
const int MAX_LEN = 10;

int main()
{
    // 利用stl的allocator构造int数组
    allocator<int> type_int;
    int* a = type_int.allocate(MAX_LEN);
    for (int i = 0; i < MAX_LEN; i++)
    {
        type_int.construct(a + i, i);
        cout << a[i] << " ";
    }
    cout << endl;

    for (int i = 0; i < MAX_LEN; i++)
    {
        type_int.destroy(a + i);
    }
    type_int.deallocate(a, MAX_LEN);

    return 0;
}



// dynCreateBase.h
#pragma once

#include <map>
#include <string>
using  namespace std;

typedef  void* (*CREATE_FUNC)();
class Register;

class DynObjectFactory {
public:
    static void* CreateObject(const string& name);
    static void  Register(const string& name, CREATE_FUNC func);

private:
    static map<string, CREATE_FUNC> mapCls;
};

class Register {
public:
    Register(const string& name, CREATE_FUNC func);
};

// 用謷牙诘屈的宏,定义类。谁能告诉我,这样的宏怎么注释
// #:它是一个指示符,指示其及后面的变量名替代一个字符串;
// ##:它是一个连接符,表示它和他后面的变量名合并在一起。
// class_name##Register 表示类名  ##是class_name与Regigister类名的连接符
// Register class_name##Register::reg(#class_name, class_name##Register::NewInstance)
// 对类的静态成员变量进行初始化
// 在宏定义时,太长。每一次的换行都必须加上\表示这一行结束。
#define REGISTER_CLASS(class_name) \
class class_name##Register { \
public: \
    static void* NewInstance() { \
        return  new class_name; \
    } \
private: \
    static Register reg; \
}; \
Register class_name##Register::reg(#class_name, class_name##Register::NewInstance)
// 用类名Circle来做例子
// Register CircleRegister::reg(Circle, CircleRegister::NewInstance)

#include "dynCreateBase.h"

// g++
// __attribute ((weak))
__declspec(selectany) map<string, CREATE_FUNC> DynObjectFactory::mapCls;
//头文件被包含多次,也只定义一次mapCls_;

void* DynObjectFactory::CreateObject(const string& name) {
    map<string, CREATE_FUNC>::const_iterator it = mapCls.find(name);
    if (it == mapCls.end())
        return  0;
    else
        return it->second();  //func();

}

void DynObjectFactory::Register(const string& name, CREATE_FUNC func) {
    DynObjectFactory::mapCls[name] = func;
}

Register::Register(const string& name, CREATE_FUNC func) {
    DynObjectFactory::Register(name, func);
}

// shape.h
#pragma once

class Shape {  // 虚基类
public:
    // 对于形状这种类,谁也画不出来。so...就让绘图接口成为纯虚函数
    virtual  void Draw() = 0; 
    // 虚基类的析构函数要定义成虚函数
    virtual ~Shape() {}       
};

// 实际的形状,都可以绘制,所以,就得分别实现这些绘图的接口
class Circle : public Shape {
public:
    void Draw();
    ~Circle();
};

class Square : public Shape {
public:
    void Draw();
    ~Square();
};

class Rectangle : public Shape {
public:
    void Draw();
    ~Rectangle();
};

#include  "shape.h"
#include  "dynCreateBase.h"
#include <iostream>
using  namespace std;

void Circle::Draw() {
    cout << "Circle::Draw() ..." << endl;
}
Circle::~Circle() {
    cout << "~Circle ..." << endl;
}

void Square::Draw() {
    cout << "Square::Draw() ..." << endl;
}
Square::~Square() {
    cout << "~Square ..." << endl;
}

void Rectangle::Draw() {
    cout << "Rectangle::Draw() ..." << endl;
}

Rectangle::~Rectangle() {
    cout << "~Rectangle ..." << endl;
}

REGISTER_CLASS(Circle);
REGISTER_CLASS(Square);
REGISTER_CLASS(Rectangle);

// main.cpp
#include  "shape.h"
#include  "dynCreateBase.h"
#include <iostream>
#include <vector>
#include <string>
using  namespace std;

void DrawAllShapes(const vector<Shape*>& v) {
    for (vector<Shape*>::const_iterator it = v.begin(); it != v.end(); ++it) {
        (*it)->Draw();
    }
}

void DeleteAllShapes(const vector<Shape*>& v)
{
    vector<Shape*>::const_iterator it;
    for (it = v.begin(); it != v.end(); ++it) {
        delete(*it);
    }
}

Shape* CreateClass(const string& strName) {
    return static_cast<Shape*>(DynObjectFactory::CreateObject(strName));
}

int main(void) {
    vector<Shape*> v;

    Shape* ps;
    ps = CreateClass("Circle");
    v.push_back(ps);
    ps = CreateClass("Square");
    v.push_back(ps);
    ps = CreateClass("Rectangle");
    v.push_back(ps);

    DrawAllShapes(v);
    DeleteAllShapes(v);

    return  0;
}



// ListNode.hpp
///////////////////////////////
#pragma once
#define NULL 0

template<typename T> 
struct ListNode {
    ListNode() : pred(NULL), succ(NULL) { }
    ListNode(T e, ListNode<T>* p = NULL, ListNode<T>* s = NULL)
        : pred(p), succ(s), data(e) { }
    ListNode<T>* insertAsPred(T const& e);
    ListNode<T>* insertAsSucc(T const& e);
    ListNode<T>* pred;
    ListNode<T>* succ;
    T data;
};

template<typename T>
ListNode<T>* ListNode<T>::insertAsPred(T const& e) {
    auto x = new ListNode(e, pred, this); //创建新节点
    if (!x) return NULL;
    pred->succ = x; //设置正向链接 
    pred = x;
    return x;       //返回新节点的位置
}

template<typename T>
ListNode<T>* ListNode<T>::insertAsSucc(T const& e) {
    auto x = new ListNode(e, this, succ); //创建新节点
    if (!x) return NULL;
    succ->pred = x;  //设置逆向链接 
    succ = x;
    return x;        //返回新节点的位置
}

// List.hpp
/////////////////////////////////////
#pragma once
#include "ListNode.h"

template<typename T> 
struct ListNode;

template<typename T>
class list {
public:
    list() { init(); }
    list(ListNode<T>* p, int n);
    list(list<T> const& lst);
    list(list<T> const& lst, int r, int n);
    ~list();
public:
    bool valid(ListNode<T>* p);
    int size() { return _size; }
    bool empty() { return _size <= 0; }
    ListNode <T>* first() const { return _head->succ; }
    ListNode <T>* last( ) const { return _tail->pred; }
    T& operator[](int r) const;
    // 无序链表中的查找
    ListNode<T>* find(T const& e, int n = size(), ListNode<T>* p = tail()) const; 
    // 有序链表中的查找
    ListNode<T>* search(T const& e, int n = size(), ListNode<T>* p = tail()) const; 
    ListNode<T>* insertAsLast(T const& e);
    ListNode<T>* insertAsFirst(T const& e);
    ListNode<T>* insertAfter(T const& e, ListNode<T>* p);
    ListNode<T>* insertBefore(T const& e, ListNode<T>* p);
    T remove(ListNode<T>* p);
    int remove(T const& e, bool bDelSame = false);
    int duplicate();
    int uniquify();
    void travel();
    void reverseAboutMid();  // 关于中间对称轴颠倒节点
    void reverseAdjacent();  // 颠倒两两相邻的节点
    void reverseAround();    // 整个链表的颠倒
protected:
    void init();
    int clear();
    ListNode<T>* head() { return _head; }
    ListNode<T>* tail() { return _tail; }
    void copyNodes(ListNode<T>* p, int n);

private:
    int _size;
    ListNode<T>* _head;  // 头哨兵
    ListNode<T>* _tail; // 尾哨兵
};

template<typename T>
list<T>::~list() { 
    clear();
    delete _head;
    delete _tail;
    _size = 0;
    _head = _tail = NULL;
}

template<typename T>
list<T>::list(ListNode<T>* p, int n) {
    copyNodes(p, n);
}

template<typename T>
list<T>::list(list<T> const& lst) {
    copyNodes(lst.header, lst.size());
}

template<typename T>
list<T>::list(list<T> const& lst, int r, int n) {
    copyNodes(list[r], n);
}

template<typename T>
void list<T>::init() {
    _head = new ListNode<T>;
    _tail = new ListNode<T>;

    _head->succ  = _tail;
    _head->pred  = NULL;
    _tail->succ = NULL;
    _tail->pred = _head; 
    _size = 0;
}

template<typename T>
T& list<T>::operator[](int r) const {
    ListNode<T>* p = first();
    while (0 < r--) p = p->succ;
    return p->data;
}

template<typename T>
bool list<T>::valid(ListNode<T>* p) {
    if (p == head() || p == tail()) 
        return false;
    return true;
}

template<typename T>
ListNode<T>* list<T>::find(T const& e, int n, ListNode<T>* p) const { 
    while (0 <= n--)  // [0, n - 1)
        if (e == (p = p->pred)->data) break;
    if (!valid(p)) 
        return NULL;
    return p;
}

template<typename T>
ListNode<T>* list<T>::search(T const& e, int n, ListNode<T>* p) const {
    while (0 <= n--) // [0, n)
        if (e >= ((p = p->pred)->data)) 
            break;
    if (!valid(p)) 
        return NULL;
    return p;
} 

template<typename T>
ListNode<T>* list<T>::insertAsFirst(T const& e) {
    _size++;
    return head()->insertAsSucc(e);
}

template<typename T>
ListNode<T>* list<T>::insertAsLast(T const& e) {
    _size++;
    return tail()->insertAsPred(e);
}

template<typename T>
ListNode<T>* list<T>::insertAfter(T const& e, ListNode<T>* p) {
    _size++;
    return p->insertAsSucc(e);
}

template<typename T>
ListNode<T>* list<T>::insertBefore(T const& e, ListNode<T>* p) {
    _size++;
    return p->insertAsPred(e);
}

template<typename T>
void list<T>::copyNodes(ListNode<T>* p, int n) {
    init();
    for ( ; n--; p = p->succ) 
        insertAsLast(p->data);
}

template<typename T>
T list<T>::remove(ListNode<T>* p) { 
    T e = p->data;
    p->succ->pred = p->pred;
    p->pred->succ = p->succ;
    delete p;
    _size--;
    return e;
}

template<typename T>
int list<T>::remove(T const& e, bool bDelSame) {
    int nSize = 0;
    if (!(nSize = size())) return 0;
    for (auto p = head(), q = p->succ; q; q = q->succ) {
        while (p->data == e || q->data == e) {
            if (p->data == e) {
                remove(p);    // 删除符合条件的前驱节点
                p = q;        // 用后继节点的地址更新前驱节点的地址
            }
            else if (q->data == e) {
                remove(q);   // 删除符合条件的后继节点
                q = p->succ; // 用前驱的后继节点的地址更新后驱节点的地址
            }
            else if (q == tail()) break;
        }
    }
    return nSize - size();
}

template<typename T>
int list<T>::clear() {
    int tmp = size();
    while (!empty())
        remove(head()->succ);
    return tmp;
}

template<typename T>
int list<T>::duplicate() {
    if (size() < 2) return 0;
    int tmp = size();
    auto p = head;
    int r = 0;
    while (tail() != (p = p->succ)) {
        auto q = find(p->data, r, p);
        q ? remove(q) : r++;
    }
    return tmp - size();
}

template<typename T>
int list<T>::uniquify() {
    if (size() < 2) return 0;
    int tmp = size();
    auto p = first(), q = last();
    while (tail() != (q = p->succ))
        if (p->data != q->data) p = q;
        else remove(q);
    return tmp - size();
}

template<typename T>
void list<T>::reverseAboutMid() {
    auto p = head(), q = tail();
    for (int i = 1; i < size(); i += 2)
        swap((p = p->succ)->data, (q = q->pred)->data);
}

template<typename T>
void list<T>::reverseAdjacent() {
    if (size() < 2) return;
    for (auto p = head(); p; p = p->succ)
        swap(p->pred, p->succ);
    swap(head, tail);
}

template<typename T>
void list<T>::reverseAround() {
    if (size() < 2) return;
    for (auto p = head(), q = p->succ; p != tail(); p = q, q = q->succ) 
        p->pred = q;
    tail()->pred = NULL;
    for (auto p = tail(), q = p->pred; p != head(); p = q, q = q->pred)
        q->succ = p;
    head()->succ = NULL;

}

#include <iostream>
using namespace std;

template<typename T>
void list<T>::travel() {
    for (auto p = first(); p != tail(); p = p->succ) 
        cout << "[ " << p->data << " ]" << " " << "[ " << p << " ]" << endl;
}



#include <iostream>
#include <regex>
using namespace std;
int main() {
    string str = "yAgfy@qq.com";
    regex x(R"((\w+)@(\w+).(\w+))");

    regex_iterator Begin(str.begin(), str.end(), x);
    regex_iterator<typename string::iterator> End;

    while (Begin != End) {
        cout << (*Begin)[0] << endl;  // 输出全串
        cout << (*Begin)[1] << endl;  // 输出第一个分割串
        cout << (*Begin)[2] << endl;  // 输出第二个分割串
        cout << (*Begin)[3] << endl;  // 输出第三个分割串    
        ++Begin;
    }
    return 0;
}



QQ图片20201013190641.png




#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <io.h>
#include <time.h>
using namespace std;

string path;

//深度优先递归遍历当前目录下文件夹和文件及子文件夹和文件
void DfsFolder()
{
    _finddata_t file;
    path += "/*";
    long handle = 0;
    if (-1L == (handle = _findfirst(path.c_str(), &file))) return; //返回值为-1则查找失败

    do {
        tm* pt = localtime(&file.time_write);
        printf("%04d/%02d/%02d  %02d:%02d ", 
            pt->tm_year + 1900, pt->tm_mon, pt->tm_mday, pt->tm_hour, pt->tm_min);
        if (file.attrib & _A_SUBDIR) {  //判断是否是子目录
            printf("  %-12s %-4s\n", "<DIR>", file.name);
            //.是当前目录,..是上层目录,遇到这样两种情况是曾经路过的地方,不必重复再经过
            if (strcmp(file.name, ".") && strcmp(file.name, "..")) {
                path = path + '/' + file.name;  // 在下一次递归之前设定好下一次要搜索的路径 
                DfsFolder();
            }
        }
        else printf("  %12u %-4s\n", file.size, file.name);  // 能到这里就是文件,打印文件的大小以及文件名
    } while (!_findnext(handle, &file));  //返回0则遍历完
    //关闭文件句柄
    _findclose(handle);
}

int main(int argc, char* argv[]) {
    //递归遍历文件夹和文件夹中所有的文件
    printf("输入全路径的路径名:");
    getline(cin, path, '\n');
    DfsFolder();
    return 0;
}