This page looks best with JavaScript enabled

C++课设——快件管理系统

 ·  ☕ 14 min read · 👀... views

题目

快件管理系统

目的

通过设计一个小型的快件管理系统,训练综合运用所学知识处理实际问题的能力,强化面向对象的程序设计理念,使自己的程序设计与调试水平有一个明显的提高。

要求

1、每个学生必须独立完成;
2、课程设计时间为1周;
3、设计语言采用C++;
4、学生有事离校必须请假。课程设计期间,无故缺席按旷课处理;缺席时间达四分之一以上者,未按规定上交实验报告的学生,其成绩按不及格处理。

内容简介

有一个快递服务代收点,现在需要你为这个服务代收点开发一个简单的快件管理系统,使收件人能够查询自己的快件情况,服务人员能够使用该系统管理该点代收的所有快件,并通知收件人取件,加快工作效率,提高服务质量。

考核标准

该系统为两种角色的用户提供服务,一种是代收点服务人员,一种是收件人。代收点服务人员根据账号、密码登录系统。收件人无需登录即可使用系统。
1、 代收点服务人员可将快件信息录入系统,快件信息包括快递单号、快递公司、收件人、收件人联系电话、收件人地址、邮编、寄件人、寄件人联系电话、寄件人地址、邮编。系统自动为每个快递生成一个取件号,每个取件号都对应一个存放位置(假设站点有20个货架,每个货架有5层,每层可放10个快件),注意只有空的位置才能存放快件。如收件人来取件,服务人员可根据手机号或者取件号查询到该快件并标记取件成功。收件人可以通过手机号查询自己在该代收点的快件的取件号以及是否收取的情况,成绩≥60;
2、 系统退出后能保存当天的快件信息。代收点服务人员可以根据快递单号查找、删除、修改某个快件;可以查询所有未取快件;可以查询当天新进的快件和已取的快件,成绩≥80;
3、 系统可根据历史记录对收取件情况进行统计,根据服务人员的输入日期范围统计收取件情况并显示,包括收件量、取件量、未取件数量、各快递公司的收件量、各快递公司的取件量、各快递公司的未取件数量,成绩≥90;
要求:
用面向对象的程序设计方法设计该系统。本系统涉及的基本对象有快件对象、快递柜对象、快件管理对象、系统界面对象等。实现对这些对象的合理抽象和封装,正确定义类之间的关系。界面合理,代码文件组织清晰,命名符合规范,代码注释清楚,各功能展示清楚,课设报告书质量高。

部分代码

user.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef USER_H
#define USER_H
#include<cstdio>
#include<iostream>
#include<cstring>
#include<windows.h>
#pragma warning(disable:4996)
using namespace std;

class User {
    private:
        string username;   //访客username即为手机号
        string password;
        bool privilege;    //admin为1,guest为0

    public:
        User(string username, string password);
        User() = default;
        
        /** Access name
         * \return The current value of name
         */
        string getName() { return username; }
        /** Set name
         * \param val New value to set
         */
        User& setName(string val) { username = val; }
        /** Access password
         * \return The current value of password
         */
        string getPassword() { return password; }
        /** Set password
         * \param val New value to set
         */
        User& setPassword(string val) { password = val; }
        /** Access privilege
         * \return The current value of privilege
         */
        int getPrivilege() { return privilege; }
        /** Set privilege
         * \param val New value to set
         */
        User& setPrivilege(int val) { privilege = val; }


};

User::User(string username, string password = ""){
    this->username = username;
    this->password = password;
}

#endif

package.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifndef PACKAGE_H
#define PACKAGE_H
#include<cstdio>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<windows.h>

#include "date.h"
#pragma warning(disable:4996)
using namespace std;

class Package {
    private:
        string SN;               // 快递单号
        string company;          // 快递公司
        string pickNum;          // 取件号
        string recipient;        // 收件人
        string recipientPhone;   // 收件人联系电话
        string recipientAddress; // 收件人地址
        string recipientPostcode;// 收件人邮编
        string sender;           // 寄件人
        string senderPhone;      // 寄件人联系电话
        string senderAddress;    // 寄件人地址
        string senderPostcode;   // 寄件人邮编
        CDate date;              // 入库时间
        CDate takeoffDate;       // 取件时间
        bool takeoff;            // 快件是否被取走,1为取走,0为未取
    public:
        Package(string SN, string company, string pickNum, string recipient, string recipientPhone, string recipientAddress, string recipientPostcode, string sender, string senderPhone, string senderAddress, string senderPostcode, CDate date, CDate takeoffDate, bool takeoff);
        Package& operator=(const Package& rhs);

        string getPackageSN() { return SN; }
        string getCompany() { return company; }
        string getPackagePhone() { return recipientPhone; }
        string getPackagePickNum() { return pickNum; }
        bool getStatus() { return takeoff; }
        CDate getDate() { return date; }
        CDate getTakeoffDate() { return takeoffDate; }

        /** signed package
         * \param 标记快件被取
         */
        void signPackage();

        /** Print package picknum and takeoff
         * \param 输出快件取件号和收取情况
         */
        void printPackage_Guest();

        /** Print Package All Message
         * \param 输出快件所有信息
         */
        void printPackage();

        /** edit package
         * \param 修改快件信息
         */
        void editPackage();


        void Fileout();
};

#endif

date.h

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef date_H
#define date_H
#include <iostream>
#include<ctime>
#include<cstdlib>
#include<string>
#include<cstdio>
#pragma warning(disable:4996)
using namespace std;
class CDate{
	int y,m,d,hh,mm,ss;
	const string df_s;//xxxx-xx-xx
	const string df_l;//xxxx年xx月xx日
	const string df_h;//xxxx年xx月xx日xx时xx分xx秒
public:
    /** Default constructor */
	CDate();

	/**  constructor */
	CDate(int y, int m, int d, int hh, int mm, int ss);

	/** Default constructor */
	~CDate();
	CDate& operator=(const CDate& rhs);
	/** Return Date String
     *  \param 获取固定格式日期字符串
     */
	string format(string df);
	/** Return Only Number Date String
     *  \param 获取纯数字日期字符串
     */
	string GetDateString();
	/** Return Date Form Only Number Date String
     *  \param 获取数字日期字符串的日期
     */
    string GetDateOfCN(string DateString);
private:
    /** Return At Least Two Bit Digit Form A Number
     *  \param 获取固定格式日期字符串
     */
    string twobitstr(int x);
};


CDate::CDate() : df_s("ddd"),df_l("DDD"),df_h("HHMMSS")    //初始化
{
	time_t now;

	time(&now);

	struct tm *t_now;

	t_now = localtime(&now);

	y = t_now -> tm_year + 1900;

	m = t_now -> tm_mon + 1;

	d = t_now -> tm_mday;

	hh = t_now -> tm_hour;

	mm = t_now -> tm_min;

	ss = t_now -> tm_sec;

	// cout<<y<<m<<d<<hh<<mm<<ss<<endl;
}
CDate::CDate(int y, int m, int d, int hh, int mm, int ss) : df_s("ddd"),df_l("DDD"),df_h("HHMMSS")    //初始化
{
	this->y = y;
	this->m = m;
	this->d = d;
	this->hh = hh;
	this->mm = mm;
	this->ss = ss;
}
CDate::~CDate()
{
    //dtor
}

CDate& CDate::operator=(const CDate& rhs) {
	if(this == &rhs) return *this;
	this->y = rhs.y;
	this->m = rhs.m;
	this->d = rhs.d;
	this->hh = rhs.hh;
	this->mm = rhs.mm;
	this->ss = rhs.ss;
	return *this;
}

string CDate::format(string df)
{
		char c_df[20];
		if(df == df_s)
		{
			sprintf(c_df, "%d-%d-%d", y, m, d);
			return string(c_df);
		}
		if(df == df_l)
		{
			sprintf(c_df, "%d年%d月%d日", y, m, d);
			return string(c_df);
		}
		if(df == df_h)
		{
			sprintf(c_df, "%d年%d月%d日%d时%d分%d秒", y, m, d,hh,mm,ss);
			return string(c_df);
		}
		return string("");
}
string CDate::GetDateString(){
    return twobitstr(y)+twobitstr(m)+twobitstr(d)+twobitstr(hh)+twobitstr(mm)+twobitstr(ss);
}
string CDate::GetDateOfCN(string DateString){
    char c_df[20];
    int year,month,day,hour,minute,second;
    sscanf(DateString.substr(0,4).c_str(),"%d",&year);
    sscanf(DateString.substr(4,2).c_str(),"%d",&month);
    sscanf(DateString.substr(6,2).c_str(),"%d",&day);
    sscanf(DateString.substr(8,2).c_str(),"%d",&hour);
    sscanf(DateString.substr(10,2).c_str(),"%d",&minute);
    sscanf(DateString.substr(12,2).c_str(),"%d",&second);
    sprintf(c_df, "%d年%d月%d日%d时%d分%d秒", year, month, day,hour,minute,second);
    return string(c_df);
}

string CDate::twobitstr(int x){
    string res="";
    int xx=x;
    while(x){
        res=char('0'+(x%10))+res;
        x/=10;
    }
    if(xx<10)
        res='0'+res;
    return res;
}
#endif

cabinet.h

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#ifndef CABINET_H
#define CABINET_H
#include<cstdio>
#include<iostream>
#include<string>
#include<vector>
#include<io.h>
#include<windows.h>
#include<algorithm>

#include "package.h"
#include "date.h"
#pragma warning(disable:4996)
using namespace std;

class Cabinet {
    private:
        bool packagesShelves[20][5][10] = {0};
        int packagenum;
        vector<Package> packageList;
    public:

        // Cabinet& operator=(const Cabinet& other);
        /** Default constructor */
        Cabinet();

        /** Default destructor */
        ~Cabinet();

        /** Add package
         *  \param 添加快件
         */
        void addPackage();

        /** Read Package Messages in data/Package/*
         *  \param 读取文件夹data/Package内的所有快件信息
         */
        void readAllPackage();

        /** Read Package Messages in data/Package/filename
         *  \param 读取文件内的快件信息
         */
        void readPackage(string filename);

        /** Write Package Messages To File in data/Package/Package
         *  \param 写入文件内的快件信息
         */
        void writePackage();

        /** Delete package
         *  \param 删除快件
         */
        void delPackage(string delpackageID);

        /** Print All package Goods List
         *  \param 输出快件列表
         */
        void printList();

        /** Search package And Return A Iterator Of Vector
         *  \param 通过单号搜索快件,并且返回Vector的迭代器
         */
        vector<Package>::iterator searchPackageBySN(string SN);

        /** Search package And Return A Iterator Of Vector
         *  \param 通过取件号搜索快件,并且返回Vector的迭代器
         */
        vector<Package>::iterator searchPackageByPickNum(string pickNum);

        /** Search package And Return A Iterator Of Vector
         *  \param 通过手机号搜索快件,并且返回Vector的迭代器
         */
        vector<vector<Package>::iterator> searchPackageByPhone(string phone);

        /** Search package
         *  \param 搜索快件
         */
        void searchPackage(string SN);

        /** Admin Sign package by phone
         *  \param 管理员通过手机号标记取件
         */
        void adminSignByPhone(string phone);

        /** Admin Sign package by pickNum
         *  \param 管理员通过取件号标记取件
         */
        void adminSignByPicknum(string pickNum);

        /** ghost query package
         *  \param 取件人通过手机号查询取件号及是否收取情况
         */
        void ghostQueryByPhone(string phone);

        /** Edit package
         *  \param 编辑快件
         */
        void adminEditPackage(string SN);

        /** print all untakeoff package
         *  \param 服务人员查询所有未取快件
         */
        void printAllUntakeoff();

        /** print today new package
         *  \param 输出今天新进快件
         */
        void printNewToday(CDate today);

        /** print today takeoff package
         *  \param 输出今天已取快件
         */
        void printTakeoffToday(CDate today);

        /** print packages statistic result
         *  \param 统计快件
         */
        void statisticPackage(string startdate, string enddate);

        /** Rank package
         *  \param 以公司名字排序快件
         */
        void rankPackageByCompany();





        /** Get Package Num
         *  \param i 货架
         *  \param j 层数
         *  \param k 位置
         */
        string GetpackageNum(int i, int j, int k);      // 根据位置返回五位取件号

        /** Store new Package
         *  \param 新快件存入
         */
        string store();                      // 搜索空位,并调用GetpackageNum函数返回5位取件号

        /** sort cmp by company's name func
         *  \param 以公司名为排序依据的排序函数
         */
        static bool packageCmpByCompany(Package x, Package y);
        
        /** Get files' name
         *  \param 获得路径下所有文件名
         */
        static void getFilesName( string path, vector<string>& files );

};


void Cabinet::readPackage(string filename){
    ifstream infile("data/Package/"+filename, ios::in);
    string title[14];
    string SN, company, pickNum, recipient, recipientPhone, recipientAddress, recipientPostcode, sender, senderPhone, senderAddress, senderPostcode, date, takeoffDate;
    int y, m, d, hh, mm, ss;
    int t_y, t_m, t_d, t_hh, t_mm, t_ss;
    bool takeoff;
    for(int i=0;i<14;i++){   // 读掉标题
        infile>>title[i];
    }
    // infile>>SN>>company>>pickNum>>recipient>>recipientPhone>>recipientAddress>>recipientPostcode>>sender>>senderPhone>>senderAddress>>senderPostcode>>date>>takeoffDate>>takeoff;
    while(!infile.eof()){
        infile>>SN>>company>>pickNum>>recipient>>recipientPhone>>recipientAddress>>recipientPostcode>>sender>>senderPhone>>senderAddress>>senderPostcode>>date>>takeoffDate>>takeoff;
        sscanf(date.substr(0,4).c_str(),"%d",&y);
        sscanf(date.substr(4,2).c_str(),"%d",&m);
        sscanf(date.substr(6,2).c_str(),"%d",&d);
        sscanf(date.substr(8,2).c_str(),"%d",&hh);
        sscanf(date.substr(10,2).c_str(),"%d",&mm);
        sscanf(date.substr(12,2).c_str(),"%d",&ss);
        sscanf(takeoffDate.substr(0,4).c_str(),"%d",&t_y);
        sscanf(takeoffDate.substr(4,2).c_str(),"%d",&t_m);
        sscanf(takeoffDate.substr(6,2).c_str(),"%d",&t_d);
        sscanf(takeoffDate.substr(8,2).c_str(),"%d",&t_hh);
        sscanf(takeoffDate.substr(10,2).c_str(),"%d",&t_mm);
        sscanf(takeoffDate.substr(12,2).c_str(),"%d",&t_ss);
        Package package(SN, company, pickNum, recipient, recipientPhone, recipientAddress, recipientPostcode, sender, senderPhone, senderAddress, senderPostcode, *(new CDate(y,m,d,hh,mm,ss)),*(new CDate(t_y,t_m,t_d,t_hh,t_mm,t_ss)), takeoff);
        packageList.push_back(package);
        // cout<<SN<<"快件 读取成功"<<endl;
        if(!takeoff) {
            packagesShelves[atoi(pickNum.substr(0,2).c_str())][atoi(pickNum.substr(2,1).c_str())][atoi(pickNum.substr(3,2).c_str())] = 1;
        }
    }
    infile.close();
    remove(("data/package/"+filename).c_str());
}

void Cabinet::rankPackageByCompany(){
    sort(packageList.begin(),packageList.end(),packageCmpByCompany);
}

string Cabinet::store() {                      // 搜索空位,并调用GetpackageNum函数返回5位取件号
    for(int i=0;i<20;++i) {
        for(int j=0;j<5;++j) {
            for(int k=0;k<10;++k) {
                if(packagesShelves[i][j][k] == 0){
                    packagesShelves[i][j][k] = 1;
                    return GetpackageNum(i, j, k);
                }
            }
        }
    }
    throw -1;
}

bool Cabinet::packageCmpByCompany(Package x, Package y){
    // string xDate = x.getDate().GetDateString();
    // string yDate = y.getDate().GetDateString();
    return x.getCompany() < y.getCompany();
}


void Cabinet::getFilesName( string path, vector<string>& files )  
{  
    //文件句柄  
    long   hFile   =   0;  
    //文件信息  
    struct _finddata_t fileinfo;  
    string p;  
    if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
    {  
        do  
        {  
            //如果不是目录,加入列表  
            if(!(fileinfo.attrib &  _A_SUBDIR)) {  
                files.push_back(fileinfo.name );  
            }
            // cout<<fileinfo.name<<endl;  

        }while(_findnext(hFile, &fileinfo)  == 0);  
        _findclose(hFile);  
    }  
}


#endif
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#ifndef MENU_H
#define MENU_H
#include<cstdio>
#include<fstream>
#include<iostream>
#include<string>
#include<windows.h>

#include "cabinet.h"
#include "date.h"
#include "user.h"
#pragma warning(disable:4996)
using namespace std;

class Menu {
    private:

        /** Error Messages
         *  \param 提示用户的非法操作
         */
        void invalid();

        /** Exit System
         *  \param 退出系统
         */
        void exit();

        /** MenuList
         *  \param 系统操作菜单
         */
        void menuList(int item);

        /** Check User Messages
         *  \param 验证身份信息
         */
        bool check_login(string user,string psd);

        /** Set User Messages
         *  \param 设置当前系统用户的身份信息
         */
        void setUser(bool type,string username,string password);

        /** Login
         *  \param 登录
         */
        void login();

        /** Logout
         *  \param 登出
         */
        void logout();

        /** Admin Main Page
         *  \param 系统主页面
         */
        void admin_run();

        /** Ghost Main Page
         *  \param 系统主页面
         */
        void ghost_run();

        /** Initialize
         *  \param 初始化系统信息
         */
        void init();

        /** admin get package
         *  \param 管理员标记取件   
         */
        void adminSignPackage();

        /** admin search package
         *  \param 管理员查询取件   
         */
        void adminSearchPackage();

        /** admin delete package
         *  \param 管理员删除取件   
         */
        void adminDelPackage();

        /** admin edit package
         *  \param 管理员删除取件   
         */
        void adminEditPackage();

        /** admin statistic packages
         *  \param 管理员统计快件 
         */
        void adminStatistic();

        /** ghost query package
         *  \param 收件人查询快件  
         */
        void ghostQueryPackage();

        CDate MenuDate;//时间日期对象
        bool on;//系统开启状态标记
        bool online;//用户在线标记
        User NowUser;//当前用户
        Cabinet cabinet;//快递柜对象

    public:
        Menu();
        ~Menu();
        void Start();
};


Menu::Menu() {
    SetConsoleOutputCP(65001);  //修改控制台编码格式以支持UTF-8中文编码
    cout<<"系统初始化中..."<<endl;
    on=false;
    online=false;
    init();//初始化系统
    //ctor
}
Menu::~Menu()
{
    if(on)  
        exit();  //非正常退出存储数据
    //dtor
}


void Menu::menuList(int item){
    /*
    1:登录菜单
    2:管理员主页面菜单
    3:顾客主页面菜单
    4:购买菜单

    */

    switch(item){
        case 1://用户选择页面
            {
                cout<<"  ----请选择用户类型----  "<<endl;
                cout<<"  |  1.管理员          |  "<<endl;
                cout<<"  |  2.收件人          |  "<<endl;
                cout<<"  |  3.退出            |  "<<endl;
                cout<<"  ----------------------  "<<endl;
                break;
            }

        case 2://管理员主页面
            {
                cout<<"  ------请选择操作------  "<<endl;
                cout<<"  | 1.快件录入         |  "<<endl;
                cout<<"  | 2.取件             |  "<<endl;
                cout<<"  | 3.快件查询         |  "<<endl;
                cout<<"  | 4.快件删除         |  "<<endl;
                cout<<"  | 5.快件修改         |  "<<endl;
                cout<<"  | 6.列出所有未取快件 |  "<<endl;
                cout<<"  | 7.列出今天新进快件 |  "<<endl;
                cout<<"  | 8.列出今天已取快件 |  "<<endl;
                cout<<"  | 9.统计             |  "<<endl;
                cout<<"  | 10.退出登录        |  "<<endl;
                cout<<"  | 11.退出系统        |  "<<endl;
                cout<<"  ----------------------  "<<endl;
                break;
            }

        case 3://顾客主页面
            {
                cout<<"  ------请选择操作------  "<<endl;
                cout<<"  | 1.快件查询         |  "<<endl;
                cout<<"  | 2.退出登录         |  "<<endl;
                cout<<"  | 3.退出系统         |  "<<endl;
                cout<<"  ----------------------  "<<endl;
                break;
            }

        case 4://管理员取快件
            {
                cout<<"  ------请选择操作------  "<<endl;
                cout<<"  | 1.手机号           |  "<<endl;
                cout<<"  | 2.取件号           |  "<<endl;
                cout<<"  | 3.返回上一级       |  "<<endl;
                cout<<"  ----------------------  "<<endl;
                break;
            }


        default:invalid();break;
    }

}

void Menu::ghost_run(){
    cout<<"  ------欢迎"<<NowUser.getName()<<"------  "<<endl;
    while(on&&online){
        int op;
        menuList(3);
        scanf("%d",&op);
        switch(op){
            case 1:ghostQueryPackage();break;
            case 2:logout();break;
            case 3:exit();break;
            default:invalid();break;
        }
    }
}

bool Menu::check_login(string user,string psd){
    cout<<"正在验证身份..."<<endl;
    typedef string(*EncryptoFunc)(string a);      // 调用dll获取加密函数
    HINSTANCE HDLL=LoadLibrary(TEXT("encrypto.dll"));
    EncryptoFunc Encrypto = (EncryptoFunc)GetProcAddress(HDLL,"Encrypto");
    if(!Encrypto) {
        cout<<"缺少encrypto.dll!"<<endl;
        return 0;
    }
    string cipher = Encrypto(psd);  //获取加密函数的返回值即加密结果

    ifstream infile("data/User/Admin", ios::in);
    string fname,fpsd;
    infile>>fname>>fpsd;//抛弃文件标题行
    bool res=0;//正确性标记
    while(!infile.eof()){
        infile>>fname>>fpsd;
        //cout<<fname<<" "<<fpsd<<endl;
        if(user==fname&&cipher==fpsd){
            res=1;
            break;
        }
    }
    infile.close();
    return res;
}

void Menu::login(){
    if(online){
        cout<<"  --------已登录--------  "<<endl;
        return;
    }
    while(on){
        menuList(1);
        int op;
        scanf("%d",&op);
        switch(op){
            case 1://管理员登录
                {
                    cout<<"  -----请输入账号-----  "<<endl;
                    string username="";
                    cin>>username;
                    cout<<"  -----请输入密码-----  "<<endl;
                    string password="";
                    cin>>password;
                    if(check_login(username,password)){
                        setUser(1, username,password);
                        cout<<"  ------登录成功------  "<<endl;
                        admin_run();
                    }else{
                        cout<<"  ---账号或密码错误---  "<<endl;
                    }
                    break;
                }
            case 2://顾客登录
                {
                    cout<<"  -----请输入手机号-----  "<<endl;
                    string username="";
                    cin>>username;
                    setUser(0,username,"");
                    ghost_run();//运行主程序
                    break;
                }
            case 3:exit();break;
            default:invalid();break;
        }
    }
}



#endif

encrypto.cpp

这个库用于加密密码,因此这里我用“-shared”参数编译成了dll动态链接库,在menu.h中的登录检测函数里动态的调用库里的加密函数。这种方法相较于直接将加密逻辑写在头文件里或者写在lib库里更加安全

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include   <stdio.h>  
#include   <stdlib.h> 
#include   <time.h>  
#include   <string.h>  
#include   <iostream>
#pragma warning(disable:4996)
using namespace std;
typedef   unsigned   char   *POINTER;
typedef   unsigned   short   int   UINT2;
typedef   unsigned   long   int   UINT4;
 
typedef   struct
{
	UINT4   state[4];
	UINT4   count[2];
	unsigned   char   buffer[64];
}   MD5_CTX;
 
void   MD5Init(MD5_CTX   *);
void   MD5Update(MD5_CTX   *, unsigned   char   *, unsigned   int);
void   MD5Final(unsigned   char[16], MD5_CTX   *);
 
#define   S11   7  
#define   S12   12  
#define   S13   17  
#define   S14   22  
#define   S21   5  
#define   S22   9  
#define   S23   14  
#define   S24   20  
#define   S31   4  
#define   S32   11  
#define   S33   16  
#define   S34   23  
#define   S41   6  
#define   S42   10  
#define   S43   15  
#define   S44   21  
 
static   unsigned   char   PADDING[64] = {
  0x80,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
};
 
#define   F(x,   y,   z)   (((x)   &   (y))   |   ((~x)   &   (z)))  
#define   G(x,   y,   z)   (((x)   &   (z))   |   ((y)   &   (~z)))  
#define   H(x,   y,   z)   ((x)   ^   (y)   ^   (z))  
#define   I(x,   y,   z)   ((y)   ^   ((x)   |   (~z)))  
 
#define   ROTATE_LEFT(x,   n)   (((x)   <<   (n))   |   ((x)   >>   (32-(n))))  
 
#define   FF(a,   b,   c,   d,   x,   s,   ac)   {     (a)   +=   F   ((b),   (c),   (d))   +   (x)   +   (UINT4)(ac);     (a)   =   ROTATE_LEFT   ((a),   (s));     (a)   +=   (b);       }  
#define   GG(a,   b,   c,   d,   x,   s,   ac)   {     (a)   +=   G   ((b),   (c),   (d))   +   (x)   +   (UINT4)(ac);     (a)   =   ROTATE_LEFT   ((a),   (s));     (a)   +=   (b);       }  
#define   HH(a,   b,   c,   d,   x,   s,   ac)   {     (a)   +=   H   ((b),   (c),   (d))   +   (x)   +   (UINT4)(ac);     (a)   =   ROTATE_LEFT   ((a),   (s));     (a)   +=   (b);       }  
#define   II(a,   b,   c,   d,   x,   s,   ac)   {     (a)   +=   I   ((b),   (c),   (d))   +   (x)   +   (UINT4)(ac);     (a)   =   ROTATE_LEFT   ((a),   (s));     (a)   +=   (b);   }  
 
extern "C" __declspec(dllexport) string Encrypto(string text);   // 声明暴露接口

inline   void   Encode(unsigned   char   *output, UINT4   *input, unsigned   int   len)
{
	unsigned   int   i, j;
 
	for (i = 0, j = 0; j < len; i++, j += 4) {
		output[j] = (unsigned   char)(input[i] & 0xff);
		output[j + 1] = (unsigned   char)((input[i] >> 8) & 0xff);
		output[j + 2] = (unsigned   char)((input[i] >> 16) & 0xff);
		output[j + 3] = (unsigned   char)((input[i] >> 24) & 0xff);
	}
}
 
inline   void   Decode(UINT4   *output, unsigned   char   *input, unsigned   int   len)
{
	unsigned   int   i, j;
 
	for (i = 0, j = 0; j < len; i++, j += 4)
		output[i] = ((UINT4)input[j]) | (((UINT4)input[j + 1]) << 8) |
		(((UINT4)input[j + 2]) << 16) | (((UINT4)input[j + 3]) << 24);
}
 
inline   void   MD5Transform(UINT4   state[4], unsigned   char   block[64])
{
	UINT4   a = state[0], b = state[1], c = state[2], d = state[3], x[16];
	Decode(x, block, 64);
	FF(a, b, c, d, x[0], S11, 0xd76aa478);   /*   1   */
	FF(d, a, b, c, x[1], S12, 0xe8c7b756);   /*   2   */
	FF(c, d, a, b, x[2], S13, 0x242070db);   /*   3   */
	FF(b, c, d, a, x[3], S14, 0xc1bdceee);   /*   4   */
	FF(a, b, c, d, x[4], S11, 0xf57c0faf);   /*   5   */
	FF(d, a, b, c, x[5], S12, 0x4787c62a);   /*   6   */
	FF(c, d, a, b, x[6], S13, 0xa8304613);   /*   7   */
	FF(b, c, d, a, x[7], S14, 0xfd469501);   /*   8   */
	FF(a, b, c, d, x[8], S11, 0x698098d8);   /*   9   */
	FF(d, a, b, c, x[9], S12, 0x8b44f7af);   /*   10   */
	FF(c, d, a, b, x[10], S13, 0xffff5bb1);   /*   11   */
	FF(b, c, d, a, x[11], S14, 0x895cd7be);   /*   12   */
	FF(a, b, c, d, x[12], S11, 0x6b901122);   /*   13   */
	FF(d, a, b, c, x[13], S12, 0xfd987193);   /*   14   */
	FF(c, d, a, b, x[14], S13, 0xa679438e);   /*   15   */
	FF(b, c, d, a, x[15], S14, 0x49b40821);   /*   16   */
	GG(a, b, c, d, x[1], S21, 0xf61e2562);   /*   17   */
	GG(d, a, b, c, x[6], S22, 0xc040b340);   /*   18   */
	GG(c, d, a, b, x[11], S23, 0x265e5a51);   /*   19   */
	GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);   /*   20   */
	GG(a, b, c, d, x[5], S21, 0xd62f105d);   /*   21   */
	GG(d, a, b, c, x[10], S22, 0x2441453);   /*   22   */
	GG(c, d, a, b, x[15], S23, 0xd8a1e681);   /*   23   */
	GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);   /*   24   */
	GG(a, b, c, d, x[9], S21, 0x21e1cde6);   /*   25   */
	GG(d, a, b, c, x[14], S22, 0xc33707d6);   /*   26   */
	GG(c, d, a, b, x[3], S23, 0xf4d50d87);   /*   27   */
	GG(b, c, d, a, x[8], S24, 0x455a14ed);   /*   28   */
	GG(a, b, c, d, x[13], S21, 0xa9e3e905);   /*   29   */
	GG(d, a, b, c, x[2], S22, 0xfcefa3f8);   /*   30   */
	GG(c, d, a, b, x[7], S23, 0x676f02d9);   /*   31   */
	GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);   /*   32   */
	HH(a, b, c, d, x[5], S31, 0xfffa3942);   /*   33   */
	HH(d, a, b, c, x[8], S32, 0x8771f681);   /*   34   */
	HH(c, d, a, b, x[11], S33, 0x6d9d6122);   /*   35   */
	HH(b, c, d, a, x[14], S34, 0xfde5380c);   /*   36   */
	HH(a, b, c, d, x[1], S31, 0xa4beea44);   /*   37   */
	HH(d, a, b, c, x[4], S32, 0x4bdecfa9);   /*   38   */
	HH(c, d, a, b, x[7], S33, 0xf6bb4b60);   /*   39   */
	HH(b, c, d, a, x[10], S34, 0xbebfbc70);   /*   40   */
	HH(a, b, c, d, x[13], S31, 0x289b7ec6);   /*   41   */
	HH(d, a, b, c, x[0], S32, 0xeaa127fa);   /*   42   */
	HH(c, d, a, b, x[3], S33, 0xd4ef3085);   /*   43   */
	HH(b, c, d, a, x[6], S34, 0x4881d05);   /*   44   */
	HH(a, b, c, d, x[9], S31, 0xd9d4d039);   /*   45   */
	HH(d, a, b, c, x[12], S32, 0xe6db99e5);   /*   46   */
	HH(c, d, a, b, x[15], S33, 0x1fa27cf8);   /*   47   */
	HH(b, c, d, a, x[2], S34, 0xc4ac5665);   /*   48   */
	II(a, b, c, d, x[0], S41, 0xf4292244);   /*   49   */
	II(d, a, b, c, x[7], S42, 0x432aff97);   /*   50   */
	II(c, d, a, b, x[14], S43, 0xab9423a7);   /*   51   */
	II(b, c, d, a, x[5], S44, 0xfc93a039);   /*   52   */
	II(a, b, c, d, x[12], S41, 0x655b59c3);   /*   53   */
	II(d, a, b, c, x[3], S42, 0x8f0ccc92);   /*   54   */
	II(c, d, a, b, x[10], S43, 0xffeff47d);   /*   55   */
	II(b, c, d, a, x[1], S44, 0x85845dd1);   /*   56   */
	II(a, b, c, d, x[8], S41, 0x6fa87e4f);   /*   57   */
	II(d, a, b, c, x[15], S42, 0xfe2ce6e0);   /*   58   */
	II(c, d, a, b, x[6], S43, 0xa3014314);   /*   59   */
	II(b, c, d, a, x[13], S44, 0x4e0811a1);   /*   60   */
	II(a, b, c, d, x[4], S41, 0xf7537e82);   /*   61   */
	II(d, a, b, c, x[11], S42, 0xbd3af235);   /*   62   */
	II(c, d, a, b, x[2], S43, 0x2ad7d2bb);   /*   63   */
	II(b, c, d, a, x[9], S44, 0xeb86d391);   /*   64   */
	state[0] += a;
	state[1] += b;
	state[2] += c;
	state[3] += d;
	memset((POINTER)x, 0, sizeof(x));
}
 
inline   void   MD5Init(MD5_CTX   *context)
{
	context->count[0] = context->count[1] = 0;
	context->state[0] = 0x67452301;
	context->state[1] = 0xefcdab89;
	context->state[2] = 0x98badcfe;
	context->state[3] = 0x10325476;
}
 
inline   void   MD5Update(MD5_CTX   *context, unsigned   char   *input, unsigned   int   inputLen)
{
	unsigned   int   i, index, partLen;
 
	index = (unsigned   int)((context->count[0] >> 3) & 0x3F);
	if ((context->count[0] += ((UINT4)inputLen << 3))
		< ((UINT4)inputLen << 3))
		context->count[1]++;
	context->count[1] += ((UINT4)inputLen >> 29);
 
	partLen = 64 - index;
 
	if (inputLen >= partLen) {
		memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
		MD5Transform(context->state, context->buffer);
 
		for (i = partLen; i + 63 < inputLen; i += 64)
			MD5Transform(context->state, &input[i]);
		index = 0;
	}
	else
		i = 0;
 
	memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen - i);
}
 
inline   void   MD5Final(unsigned   char   digest[16], MD5_CTX   *context)
{
	unsigned   char   bits[8];
	unsigned   int   index, padLen;
 
	Encode(bits, context->count, 8);
	index = (unsigned   int)((context->count[0] >> 3) & 0x3f);
	padLen = (index < 56) ? (56 - index) : (120 - index);
	MD5Update(context, PADDING, padLen);
	MD5Update(context, bits, 8);
	Encode(digest, context->state, 16);
	memset((POINTER)context, 0, sizeof(*context));
}
 
void   MD5Digest(char   *pszInput, unsigned   long   nInputSize, char   *pszOutPut)
{
	MD5_CTX   context;
	unsigned   int   len = strlen(pszInput);
 
	MD5Init(&context);
	MD5Update(&context, (unsigned   char   *)pszInput, len);
	MD5Final((unsigned   char   *)pszOutPut, &context);
}
 
string Encrypto(string text)
{
	char szDigest[16]; 
	string ciper = "";
	char tmp[10];
	MD5Digest((char*)text.c_str(), strlen(text.c_str()), szDigest);
	int i;
	for (i = 0; i < 16; i++) {
		sprintf(tmp, "%02X", (unsigned char)szDigest[i]);
		ciper += tmp;
	}
	// cout<<ciper<<endl;
	return ciper;
}

main.cpp

函数主部分,主要就是调用一下menu类的启动函数。这里我注册了一个SEH,以能捕获线程发生的所有异常,个人感觉这种结构相较于try/catch结构更加模块化。异常处理函数内可以加一个进程内存的dump就可以实现一个错误反馈的功能了。然后因为这个SEH是自己手动注册的,如果用VS编译要关一下项目的SAFESEH选项。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<cstdio>
#include<fstream>
#include<iostream>
#include<vector>
#include <iomanip>
#include<io.h>
#include<cstring>
#include<windows.h>

# include "menu.h"
#pragma warning(disable:4996)
using namespace std;

EXCEPTION_DISPOSITION __cdecl _except_handler(struct _EXCEPTION_RECORD* _ExceptionRecord, void* _EstablisherFrame, struct _CONTEXT* _ContextRecord, void* _DispatcherContext)
{
	printf("Error!\n");
    /* 这里可以添加内存dump代码 */
	__asm
	{
		mov ECX, [_ContextRecord]
		mov EBX, [ECX + 0xB8]  //EIP
		add EBX, 5             //这条call指令长度为5
		mov[ECX + 0xB8], EBX
	}
	return ExceptionContinueExecution;
}


int main() {

    SetConsoleOutputCP(65001);  //修改控制台编码格式以支持UTF-8中文编码


	_asm     //注册SEH
	{
		push _except_handler
		push FS : [0]
		mov FS : [0] , ESP
	}

    Menu menu;
    menu.Start();

	__asm   //卸载SEH
	{
		MOV EAX, [ESP]
		MOV FS : [0] , EAX
		ADD ESP, 8
	}
    return 0;
}

大体框架就是这样了,说是课设其实也就是稍微大一点的demo。有疑问欢迎反馈Mail: root@qfrost.com

Share on

Qfrost
WRITTEN BY
Qfrost
CTFer, Anti-Cheater, LLVM Committer