《数据结构(C++版)》课程设计—题目4 客户咨询系统

《数据结构(C++版)》课程设计报告

——客户咨询管理系统

一、课程设计目的

通过课程设计,学会运用数据结构知识,针对具体应用,自己设计合理数据结构,确定存储结构,并能设计具体操作算法,选择使用具体语言进行实现。掌握C++较复杂程序的组织和设计过程,调试技巧。学习解决实际问题的能力。

二、实习环境

计算机windows 7,开发软件VC6.0,C++语言环境。

三、  课程设计题目

题目4赵斌是一个信管专业的学生,大学四年顺利毕业了。在毕业季,他也像其他学子一样,投身于求职大军,投出一份又一份求职简历,在苦苦地等待之后,他接到了中国移动通信公司广东分司的面试通知书,通知他于本月1号10点到公司面试。当天,晴空万里,艳阳高照,他身着西装,高兴地早早来到公司楼下等待。10点钟整,他和其他新人一起,坐到公司的面试现场。他领取的一一份程序设计题: 假如你是我公司一名客服技术人员,现请你选择自己熟悉的语言,来设计一个程序,管理客户向公司打进来的咨询电话。请事行分析析使用方法和工具,说明自己的思路方法,写一份完整的程序,并实例测试。

四、总体要求和说明

使用数据结构相关知识来做。这里,我主要采用链队列相关的知识来完成本系统。

1、独立完成,设计算法并编写代码,调试通过。

2、写设计说明书。

内容:题目、功能、要求、分析、代码,收获和体会及不足等。

3、以个人独立完成。每一个选择一个题目。选题方式是:自己学号整除5所得的余数是几就做几号题。如学号为12做2号题,学号为5的做0号题。

五、需求分析

从实习题目和要求来看,本次的课程设计其依据的主要相关知识是线性表、队列和函数模版等以及一些基础的C++编程语言知识。

在题目要求中,发生的主要地点是中国移动通信公司广东分司,主人翁赵斌去面试,需要做一份管理客户向公司打进来的咨询电话的系统。

日常生活中,如果我们要打电话去10086咨询业务,就需要在一定的时间,稳定的客流量,系统不繁忙的时候才可能享受到其给我们的业务服务。

所以,在本系统中,这里主要采用特殊线性表——队列的逻辑结构以及其链接的存储结构来。

 

(一)、队列的定义

队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表。允许插入(入队、进队)的一端称为队尾,允许删除(出队)的另一端称为队头。

队列中的元素之间不仅具有线性关系,而且具有先进先出的特性。

例如:按顺序入队:a1,a2,a3;;如果要删除元素,其出队的顺序是:a1,a2,a3;

队列中的元素具有相同类型及先进先出特性,相邻元素具有前驱和后继的关系。

当客户打电话来咨询时,遇到多人同时需要办理业务,但是,考虑到客服人员不多,所以这里就要有一个先来后到的思想,即先进先出,刚好符合队列的逻辑思想,故而本系统采用队列的逻辑结构及其物理结构。

 

(二)、队列的顺序存储结构——循环队列

队列是特殊的线性表。 允许队列直接从数组中下标最大的位置延续到下标最小的位置,这个通过取模操比较容易实现,这种头尾相接的顺序存储结构称为循环队列。

队空和队满的判定方法:可以用一个数组的元素空间来实现队尾指针和队头指针相差1(类似于队满的临界状态),即队满的条件为:

(rear+1)%QueueSize=front

循环队列的实现:同样的因为队列元素的数据类型不是很确定,这个时候我们还是要采用C++模版机制。其时间复杂度为O(1)。

(三)、循环队列的链接存储——链队列

为了使空队列和非空队列的操作一致,链队列也加上头结点。设置头指针指向链队列的头结点,队尾指针指向终端结点。

链队列的实现;同样的因为队列元素的数据类型不是很确定,这个时候我们还是要采用C++模版机制。其时间复杂度为O(1)。

六、总体设计

(一)、系统流程图

注:“n<=3”这里是为了让系统测试的时候方便查看、省时省事,便只要求输入3个数据就可以了。


(二)、算法总体设计

1、类


2、系统概要分析图


七、具体分析与详细设计

(一)、VC++编程工具的使用——控制台程序

Microsoft公司退出的Visual C++是Windows平台上最流行的C/C++集成开发环境。Win32控制台应用程序(Win 32 Console Application)是一类Windows程序,它不使用复杂的图形用户界面,程序与用户交互是在一个标准的正文窗口中。Microsoft Visual C++ 6.0,其开发环境如下图7.1所示:


VC++控制台应用程序的交互界面如7.2所示:


以前,做其它系统的时候,会编写上百行甚至是上千行代码,这样在后期修改和维护的时候,很难直接就可以很快地找到相应的代码位置,所以,本系统采用的是多文件结构,将类的定义、各个函数算法以及主函数都分开来了,便于修改和查找代码。

如果源程序的规模较大,应该采用C/C++语言的多文件结构,将源程序文件分解为几个程序文件模块。多文件结构通常包括一个或者多个永和自定义头文件和一个或多个源程序文件,每个文件称为程序文件模块。严格得讲,结构化程序应该使用多文件结构,尤其对于大型程序。

(二)、代码分析

1、头文件system.h

因为无法确定最后使用的是什么数据类型,所以这里采用函数模版template<classT>。

(1)struct node

node<T>*next;在头文件system.h中定义结构体node,其包含数据域   T data;和指针域node<T>*next;指针。结点如图7.2.1.1所示:

(2)class queue

私有成员:node<T>*front,*rear;一个是队列头结点,一个是队列尾结点。

公用成员:这里主要是函数。

头文件代码如下图7.2.1.2所示:


(3)全局变量

static int count;静态数据,可以在整个系统中使用,count是一个来电客户计数器。

可以通过getcount()函数查看还在等待办业务的客户人数。

2、源文件system_one.cpp

(1)#include"system.h"在本源文件中包含头文件system.h。

(2)无参构造函数queue()

定义一个头结点,让头结点为空,front=rear=s这样队列就为空。

(3)析构函数~queue()

析构函数可以释放存储空间,定义一个结点为空,其指针p所指向的头结点不为空时,就要进行删除操作,让不为空的头结点,指向新定义为空的指针P所指向的next域,即下一个空结点,删除不为空的头结点后,这个头结点被赋值为空指针P。


输入n表示要录入n个来电用户。采用for语句可以循环输入3个来电客户。定义一个新结点s为空,然后申请一个数据域为X的结点s,其nxet域为空,尾指针的next域被赋值为s,最后将结点s插入到队尾,如此循环。便实现录入来电客户信息了。

(5)删除队列函数delque()


同样的,要定义一个空结点,其指针为p,从前面的流程图可以看出,如果要删除现在正在办理的客户,需要有一个选择是否完成业务的过程。如果是y/Y,表示已经完成业务,则会进行删除操作,反之就会执行else语句。最后return 0;于此同时,每删除一个客户,计数器count就会自减1。

如果队列为空就会出现提示“输入错了!”。若不为空是,就要一步步地调动指针删除队头的信息。空结点指针p被赋值为头结点所指向的next域,x暂存队头元素,暂存客户,然后将队头元素所在的结点摘链,判断出队前队列长度是否为1,最后删除p;返回x,这样就实现删除,进而做下一个业务了。

(6)取队头元素函数getque()

//显示正在办理业务的客户号码。如果队列不为空的时候,就要返回队头元素的数据域。

(7)判断队列为空函数empty()


判断队列是否为空,如果为空,则返回1,否则返回0,这里用1和0做标识,成真为1,成假为0。具体的值或者是信息,在后来的定义中随意,最后是做到界面友好!

3、源文件system_main.cpp

在system_main.cpp中主要存放的是本系统的主函数void main()和一个显示信息的普通函数void output()。其头文件中包含了源文件system_one.cpp。

定义了一个队列queue类的对象,其数据类型是整型int,一个实参字符串q用来存放输入的号码。

(1) 显示信息函数output()


(1) 主函数void main()

Main()中主要是编写系统界面和功能选项的代码。将do-while循环语句和switch-case开关语句结合使用。


对应屏幕输出各个功能选项,来做switch-case算法,在case语句中调用相应的queue类的函数,当然在system_main.cpp中已经在函数外声明了一个类对象,面向对象编程,所以这里只要通过对象调用queue类的各个成员函数就可以实现相应功能项应用了。


八、程序测试与调试


例如有来电客户,便输入人数,接下来程序调用input()函数,输入电话号码。同时计数器count++。打印出“共有”count“个客户在等待!”因为还没有开始办业务,所以这里的还是输入的n个人。

再选择功能输入客户队列,输入1,系统会提示还有排队客户,因为队列里还有没有办理业务的客户,但是也可以进行新来电客户的入队操作。


选择功能3,就可以进入完成客户业务模块,然后选择是否完成,如果输入y/Y,就表示已经完成,系统就会执行删除刚刚办完业务的客户信息。计数器count--。如果输入n/N,则会提示还没有完成业务,返回到上一层界面,即进入主界面。


选择功能2,就可以得到现在还有多少个来电客户需要办理业务。


刚刚输入y后,可以进入功能项2中,系统显示还有3个客户在等待,这里又新加了2个来电客户,在次执行上次的操作,可以看到现在共有5个人在等待。


输入4就进入正在办理业务的信息界面,这里可以得到信息是正在办理业务客户的号码。

输入5就进入查看等待信息界面,这里可以看到正在办理业务客户的号、办理情况、所在窗口,以及其后还有多少个人在等待。


选择6就退出了本系统了!

九、收获和不足

经过了一个学期《数据结构(C++版)》的学习,其实我感觉对数据结构还是没有很好地掌握,这是不足也是遗憾。信息技术在计算机领域显得尤为重要,所以学习或是遇到各种困难都要不懈努力去克服。学习数据结构后,在编写代码是都要习惯上地想一想,我接下来是主要采用什么样的逻辑结构和物理结构,进而利用选定的数据结构进行编程,这是一个很好的习惯,也是一个很大的收获,希望坚持保持和发展下去。

  作为一种程序设计语言,C++语言有很多优点。书中讲到它既可以进行过程化程序设计,也可以进行面向对象程序设计,很多复杂的算法和设计可以比较容易地通过C++来实现。

  在本次程序设计前,仍要将书中有关队列和单链表的理论知识浏览一遍以期达到编写是能够融会贯通。本系统的思考、分析、编写代码等用C++语言来编写能让我更加熟悉地掌握链队列在程序中的应用及其重要的地位,在添加、修改、删除和显示和界面的显示等都用到了循环。

这里系统有两个不足的地方,一是没有输入常用的11位数字的手机号码进行测试,这是后期发现的,而且测试的结果是进入死循环。二是系统的功能过于简单,例如多窗口办理业务也没有实现,表示遗憾,在接下来的时间里,会着重这个方面学习将系统进行相应的修改。

而且在编写代码时要有一个良好的书写习惯,最好同级的在平行的行而不同级的最好用阶梯形式来呈现。而且一个工程需要难以计数的命名,这时程序员就非常容易混乱,所以还要有及时注释的好习惯。

程序的编写当然离不开数据结构和各种数学计数,以及对于我来讲不可避免的各种错误。遇到问题要迎难而上,错了就要不断地研究,查看相关书籍文献或是与同学探讨,经过多次修改、调试、运行和再次修改周而复始,最后每成功写成功一个新的函数,都一种愉悦的心情油然而生。

理论与实践的结合是知识真正融合贯通的伊始。不仅学习如此,生活也应如此。

十、附录:源程序清单

/*头文件:system.h*/
#ifndef system_H
#define system_H
static int count;
template<class T>
struct node
{
	T data;
	node<T>*next;
};
template<class T>
class queue
{
private:
	node<T>*front,*rear;
	
public:
	queue();
	~queue();
	void input(T x);//入队函数,电话客户X入队
	T delque();//将队头元素出队,电话客户完成业务后就办理下一个客户业务
	T getque();//取链队列的队头元素,正在办理业务的客户
	int empty();//判断队列是否为空
	int getcount(){return count-1;}

};
#endif;

/*源文件:system_one.cpp*/
#include "system.h"
template<class T>
queue<T>::queue()
{
	node<T>*s=NULL;
	s=new node<T>;
	s->next=NULL;
	front=rear=s;
}
template<class T>
queue<T>::~queue()
{
	node<T>*p=NULL;
	while(front!=NULL)
	{
		p=front->next;
		delete front;
		front=p;
	}
}

template<class T>
void queue<T>::input(T x)
{
	int n;
	cout<<"请输入要录入的来电客户人数:";
	cin>>n;
	for(int i=1;i<=n;i++)
	{ count++;
		cout<<"请输入排队的客户号码:"<<endl;
		cin>>x;		
		node<T> *s=NULL;
    	s=new node<T>;
		s->data=x;//申请一个数据域为X的结点s
		s->next=NULL;
		rear->next=s;
		rear=s;//将结点S插入到队尾
	}
}

template<class T>
T queue<T>::delque()
{
	char sc7;
	node<T> *p=NULL;
	int x;	
	cout<<"是否完成该客户业务(是:y/Y,否:n/N):";
	cin>>sc7;  
	if(sc7=='y'||sc7=='Y')
	{count--;
	if(rear==front)throw"输入错了!(下溢)";
	p=front->next;
	x=p->data; //暂存队头元素,暂存客户
	front->next=p->next;//将队头元素所在的结点摘链
	if(p->next==NULL) rear=front;//判断出队前队列长度是否为1
	delete p;
	return x;	
	}
	else {cout<<"亲~还没有完成该客户的业务哦!"<<endl;
	return 0;}

}

template<class T>
T queue<T>::getque()
{
	if(front!=rear)
		return front->next->data;
}

template<class T>
int queue<T>::empty()
{
	if(front==rear)
		return 1;
	else return 0;
}

/*源文件:system_main.cpp*/
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
#include"system_one.cpp"
queue<int> q1;	char q;
void output()
{
	int t;
	cout<<endl;
	if(q1.empty())
	{
		cout<<setw(4)<<"所在窗口"<<setw(20)<<"客户等待个数"<<setw(24)<<"正在办理业务客户号码"<<setw(14)<<"办理情况"<<endl;
		cout<<setw(4)<<"窗口1"<<setw(18)<<q1.getcount()<<setw(24)<<"无客户办理业务"<<setw(24)<<"空闲等待中..."<<endl;
	}
	else
	{
		cout<<setw(4)<<"所在窗口"<<setw(20)<<"客户等待个数"<<setw(24)<<"正在办理业务客户号码"<<setw(14)<<"办理情况"<<endl;
cout<<setw(4)<<"窗口1"<<setw(18)<<q1.getcount()<<setw(20)<<q1.getque()<<setw(24)<<"办理中..."<<endl;cout<<endl;
	}
}
void main()
{
	int choice;
	do
	{
		cout<<setw(60)<<"|**********************欢迎使用********************|"<<endl;
		cout<<setw(60)<<"|     -- 中国移动通信公司广东分公司客服系统 --     |"<<endl;
		cout<<setw(60)<<"|                                                  |"<<endl;
		cout<<setw(60)<<"|                   1、输入客户队列                |"<<endl;
		cout<<setw(60)<<"|                   2、客户等待数量                |"<<endl;
		cout<<setw(60)<<"|                   3、完成客户业务                |"<<endl;
		cout<<setw(60)<<"|                   4、正在办理业务                |"<<endl;
		cout<<setw(60)<<"|                   5、查看等待信息                |"<<endl;
		cout<<setw(60)<<"|                   6、EXIT(退出)                |"<<endl;
		cout<<setw(60)<<"|                                                  |"<<endl;
		cout<<setw(60)<<"|**************************************************|"<<endl;
		cout<<setw(8)<<"请输入业务选项(1—5):";
		cin>>choice;
		switch(choice)
		{
		case 1:cout<<endl;
				if(q1.empty())
{cout<<"没有排队的客户!"<<endl;	 q1.input(q);}
				else	
				{cout<<"还有排队的客户哦!"<<endl;q1.input(q);break;}	
		case 2:cout<<endl;
				cout<<"共有"<<q1.getcount()+1<<"个客户在等待!"<<endl;break;
		case 3:cout<<endl;
				output();
				q1.delque();break;
		case 4:cout<<endl;
				cout<<"正在办理业务的客户号码:"<<q1.getque()<<endl;break;
		case 5:output();break;
		case 6:cout<<endl;	
				cout<<"感谢您的使用,已安全退出系统!祝您生活愉快!*^-^*"<<endl;break;
		default:cout<<endl;
				cout<<"您好!您所输入的有误!请重新输入:"<<endl;break;
		}
	}while(choice!=6);
}







  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
C++课程设计题目,包括1、输出10至99之间每位数的乘积大于每位数的和的数,例如对于数字12,有1*22+7,故输出该数。 2、求任意n个数中的最大数和最小数:先输入一个正整数n(个数),而后再输入任意n个实数,找出这n个数中的最大数及最小数并显示出来。3、对两个有序数组进行合并:设有如下数组A、B,并假设两个数组的元素都已经有序(从大到小降序排列)。编程序,合并A、B数组形成一个新的数组C,并使C的元素仍有序(从大到小降序排列)。 int A[10]={123, 86,80, 49,33,15,7,0,-1,-3}; int B[10]={100,64,51,50,27,19,15,12,5,2}; 4、有一个分数序列:1/2,1/3,1/4,1/5,1/6,1/7,……,编写函数求序列前n项之和,要求在主程序中提示用户输入整数n,并判断所输入数是否合法(大于1为合法),如果合法则调用求和函数并输出结果。 5、计算两个日期之间的间隔天数:从键盘输入两个日期(如以year1,month1,day1以及year2,month2,day2的方式来输入它们),而后计算出这两个日期的间隔天数并在屏幕上显示出结果。 要求编制具有如下原型的函数difs2Date: long GetDayDifference(int y1,int m1,int d1,int y2,int m2,int d2); 并在主函数中调用向屏幕上输出计算结果。7、声明并定义一个日期类CDate,其中数据成员m_iYear,m_iMonth,m_iDay,分别表示年、月、日,成员函数SetDate()用来设置年、月、日,成员函数IsLeapYear()用来判断当前的年份是否为闰年,构造函数带有默认形参值,可接收外部参数对m_iYear, m_iMonth, m_iDay进行初始化,另要求编写测试程序,定义一个CDate类对象,将其日期设置为2005年1月1日, 调用成员函数IsLeapYear()判断该年份是否为闰年,并输出判断结果. 说明:闰年的年份可以被4整除而不能被100整除,或者能被400整除. 8、编写一个程序计算两个给定长方形的面积,其中在设计类成员函数GetTotalArea()(用于计算两个长方形的总面积)时使用对象作为参数。 9、设计一个时间类Time,包括3个数据成员,时(h)、分(m)、秒(s),另外包括存取各数据成员和设置时间的成员函数,按上、下午各12小时或按24小时输出时间的成员函数,以及默认构造函数,默认时间值为0时0分0秒。 10、编写一个程序,输入3个学生的英语和计算机成绩,并按总分从高到低排序(要求设计一个学生类Student)。 11. 求解一元二次方程。 一元二次方程的定义为: ax2+bx+c=0 (1)如果b2 -4ac>0,方程有两个不同的实根,分别是: (2)如果b2 -4ac< 0,方程没有实根,但有虚根; (3)如果b2 -4ac= 0,方程有一个实根。 请你编写一个程序,使其能求出多个二次方程的根。该程序要询问用户是否想继续解下一个方程。用户输入1来继续,输入其它数字,则终止程序。程序要求用户输入a,b和c,然后根据前面的条件计算,并输出答案。 要求:使用类实现, (1) a,b,c为该类的私有成员变量; (2) 求根的实现为该类的成员函数,形式为: //函数返回值:实根的个数; //参数:x- 用以返回实根值的数组; int CalResult(double x[]); (3) 该类还包含有参构造函数、析构函数。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值