序 言
借助现代信息技术和管理理论,建立学校管理信息系统势在必行。对学校而言,全面开发和应用计算机管理信息系统就是有必要的。在学校管理中,教师是学校的宝贵资源,也是学校的“生命线”,因此人事管理是学校的计算机管理信息系统重要组成部分。而工资管理又是人力资源管理的重中之重。实行电子化的工资管理,可以让人力资源管理人员从繁重琐碎的案头工作解脱出来,去完成更重要的工作。
在本次课程设计当中,我的课题就是设计“学校教师工资管理系统”的仿真软件。通过设计任务书中的要求以及介绍,大致确定了主要的目的是:学习和掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能。
为了更好的完成此次课程设计,我首先了解了学校教师的管理结构,并查询了大量书籍,制订了合理的方案,然后设计出大体的框架,接下来将各个部分慢慢的扩充起来,使其充盈丰实,然后完成了大致的雏形,并通过不断地测试和调试,完成了最终的成品。
最后,经过自己的一番努力以及指导老师的悉心指导,终于完成了此方针软件的设计,通过这次课程设计,我基本了解并且学习了如何分析研究数据对象的特性、数据的组织方法、如何选取合适的数据逻辑结构和存储结构。这对以后的学习都有着很大的帮助。
摘 要
本系统基本上能够满足学校教师工资管理的需求。工资管理系统中使用了各种表格,保存相关的工资信息,方便查询,浏览,修改等操作。本系统结合实际的人事、财务制度,经过实际的需求分析,采用功能强大的VC++作为开发工具开发出来的学校教师工资管理系统。
本文首先分析了学校教师工资管理的应用现状,阐述了本工资管理系统的开发目的。通过对一系列问题的分析,确定了系统的开发平台。接着详细给出了从学校教师工资管理系统分析到总体设计详细设计与实现及测试的各个环节,最后对本次课程设计作出了总结。
本系统以Visual C++ 6.0为平台,使用C++编程语言编写实现,包含冒泡排序的数据结构,和对文件夹的基本操作等基础知识。本系统能够打印报表,方便保存和管理。
关键词:面向对象、课程设计、计算机科学与技术学院、教师工资管理
1.系统需求及功能分析
(1)这是一个小型学院教工工资管理系统,工资管理的数据文件中存储有教工姓名、月工资、教工号、性别、年龄、电话号码,该程序可以录入和显示所有员工的相关资料。在录入所有教工后,系统会自动对教工按工资进行降序排列存入文件中。
(2)项目运行的软、硬件环境:
Windows操作系统以及相应的软硬件
Microsoft Visual C++ 6.0
(3)项目具体的功能要求:
数据录入:输入各种数据;
数据统计:各行政人员的工资计算最终按工资进行的冒
泡排序;
数据打印:打印表格;
数据备份:把相关数据写入文件;
退出:退出本系统。
(4)类层次结构图
类层次结构图如图1所示:
图1 类层次结构图
2. 设计方案
首先定义教工类employee;再通过employee类分别派生出讲师类technician、辅导员类manager、教授类seller;还有行政人员类sellermanager是从讲师类和教授类派生得到。各类中产成员函数就只是对数据成员的设置和取出操作。另外有四个函数inputmanager、inputseller、inputsellermanager、inputtechnician
分别对类manager、seller、sellermanager、technician四个类的对象的赋值操作。在本系统中我用的是数组操作所有的教工,因为此系统是为小型公司所设计,所以在系统中预设教工为1000个。一开始用“employee employeeall[EMP];”语句定义一个一维数组用来存放employee的对象。当操作员输入完成后,系统会自动调用一个函数(compositorall)对所有员工的工资进行降序排列。然后用函数(outputtofile)把排列好了的数据自动保存在“E:\小型公司工资管理系统文档.txt” 文件中。资料保存后,系统会提示:“是否打印?” ,若打印则显示出来打印,若不打印则就直接退出系统。本程序从整体上来看是通过函数之间的调用来实现的。
3. 数据结构表
数据成员结构图如图1所示:
表1 数据成员结构图
序号 成员名 数据类型 长度 字段含义
1 Age Int 2 年龄
2 Employees Long 4 学院教工总人数
3 Monthwages Double 4 教工工的月工资
4 Name Char 10 姓名
5 Number Char 10 教工号
6 Post Char 10 职位
7 Sex Char 10 性别
8 Telephone Char 15 电话号码
9 Managers Static int 2 辅导员的总人数
10 Sellers Static int 2 教授的总人数
11 Sellroom Static double 4 个人课程量
12 Sellrooms Static double 4 同专业的课程总量
13 Technicians Static int 2 讲师的人数
4. 数据测试表
数据测试表如表2所示:
表2 数据测试表
姓名 吴满星 周国礼 黄聪 张雪梅 姜海燕
职位 讲师 教授 讲师 教授 教授
性别 男 男 男 女 女
年龄 21 39 20 30 21
电话号码 15974485450 09317185886 15873697236 15886655745 15886632946
教工号 101 102 103 104 105
课程量 108 109 109
工作时间 101 98
姓名 全欢 屈华海 赵湘季 戴赛玉 张自轩
职位 辅导员 讲师 讲师 行政人员 教授
性别 男 男 男 女 男
年龄 20 21 21 20 21
电话号码 13875088220 15873690339 15886643480 15886668149 15974485474
教工号 106 107 108 109 110
课程量 106
工作时间 99 97
5. 运行和调试
输入第1个教工的资料如图3所示:
图3 输入第1个教工的资料
输入第2个教工的资料如图4所示:
图4 输入第2个教工的资料
输入第3个教工的资料如图5所示:
图5 输入第3个教工的资料
输入第4个教工的资料如图6所示:
图6 输入第4个教工的资料
输入“5”退出程序并自动排序、保存文件如图7所示:
图7 输入“5”退出程序并自动排序、保存文件
问题1、在以下这段程序段中:
……
……
int n;
cin>>n;
switch(n)
{
case 1:
inputtechnician(employeeall[i]);
i++;
break;
case 2:
inputmanager(employeeall[i]);
i++;
break;
case 3:
inputseller(employeeall[i]);
i++;
break;
case 4:
inputsellermanager(employeeall[i]);
i++;
break;
case 5:
system(“cls”);//刷新屏幕****
compositorall(employeeall);//教工的工资降序排列 outputtofile(employeeall);//把资料保存到文件中*
cout<<“是否打印资料(y/n)”;
char a[5];
cin>>a;
if(a[0]‘y’||a[0]‘Y’)
printfile();//把文件中的资料显示到显示器上 return 1;
default:
cout<<“\t错误!请重新输入!\n”;
}
……
……
若输入的是整数程序可以正常运行,如果误输入了非数字字符(比如:a)则程序运行到这里时会是一个“死循环”中。
解决方法:
把int型变量“n”定义为一个字符数组char[5];再把switch(n)改为switch(n[0]),通过比较字符数组中的第一个元素。但是如果用户输入“145”
这样的话,程序比较字符数组中的第一个字符是“1”程序还是会正确运行下去。这个问题的解决方案是在switch(n[0])前加一条语句if(strlen(n)1),else
cout<<“\t错误!请重新输入!\n”。修改后的程序段如下:
……
……
char n[5];
cin>>n;
if(strlen(n)1)
{
switch(n[0])
{
case ‘1’:
inputtechnician(employeeall[i]);
i++;
break;
case ‘2’:
inputmanager(employeeall[i]);
i++;
break;
case ‘3’:
inputseller(employeeall[i]);
i++;
break;
case ‘4’:
inputsellermanager(employeeall[i]);
i++;
break;
case ‘5’:
system(“cls”); //刷新屏幕**********************
compositorall(employeeall);//教工的工资降序排列
outputtofile(employeeall);//把资料保存到文件中*
cout<<“是否打印资料(y/n)”;
char a[5];
cin>>a;
if(a[0]‘y’||a[0]‘Y’)
printfile();//把文件中的资料显示到显示器上
return 1;
default:
cout<<“\t错误!请重新输入!\n”;
}
}
else
cout<<“\t错误!请重新输入!\n”;
……
……
问题2、提高数据录入的正确性
解决方法:
A、在录入数据的时候由于性别只有男、女两性别不可能有另外的第三性别出现,所以录入性别时是通过选择的方式录入而不是键入性别这样就能有效的避免第三性别的出现。
B、一个人的姓名都会在英文15个字母、汉字4个内,所以通过加一条语句:if(strlen(temp)>15来判断姓名的长度,若不符合则要求重新输入,符合则继续运行下去。
C、在录入年龄的时候,年龄不可能是一个小于0的数,也不可能是太大的数,通过if(temp<=18||temp>65)语句来判断该年龄是否在18至65之间。年龄在大于18是因为我们国家的法定成年年龄是18岁,要满18岁才能参加工作;而小于65周岁呢,一般年高60岁就是退休年龄不再参加工作了。
设计总结
面向对象课程设计是计算机专业一门重要的专业基础课。此次课程设计的目的是以C++程序设计语言为基础,通过完成一些具有一定难度的课程设计题目的编写、调试、运行工作,使我进一步掌握面向过程和面向对象程序设计的基本方法和编程技巧,巩固所学理论知识,使理论与实际相结合。从而提高自我分析问题、解决问题的能力。培养独立的C++语言程序实际与算法设计方法,具备初步的独立分析和设计能力;软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;能够综合运用所学的理论知识和方法进行独立分析和解决问题的能力。
总的来说这次课设让我学到了很多东西,在网上找的参考资料不仅仅对这次课设有用处,而且对以后的学习也有不小的帮助,因为从中我学到了不少很实用的编程技巧。
参考文献
[1]陈维兴,林小茶.c++面向对象程序设计教程. 北京: 清华大学出版社,1996.2004.
[2]谭浩强. C++面向对象程序设计. 北京: 清华大学出版社,2009.
[3]张松梅. C++语言教程. 电子科技大学出版社,1993.
[4]阎龙. C程序员的C++指南. 北京航空航天大学出版社,1992.
[5]王博. 面向对象的建模、设计技术与方法. 北京希望电脑公司,1990.
[6]汪成为. 面向对象分析、设计及应用. 国防工业出版社,1992.
[7]江明德. 面向对象程序设计. 电子工业出版社,1993.
[8]吕凤翥.C++语言程序设计.电子工业出版社,2001.
附录:源代码(带注释)
#include<iostream.h>
#include<string.h>
#include<fstream.h>
#include<stdlib.h>
const int EMP=1000;//学院教工总人数(跟据需要可以放缩)************************
void numbertochar(char*,double);
//定义基类教工类employee******************************************************
class employee{
private:
// 姓名 教工号 职位 性别 电话号码************************
char name[10],number[10],post[10],sex[10],telephone[15];
int age;//年龄*************************************************************
double monthwages;//月工资*************************************************
static long employees;//学院教工人数***************************************
public:
long getemployees()
{
return employees;
}
char*getnumber()
{
return number;
}
char*getname()
{
return name;
}
char*getpost()
{
return post;
}
char*getsex()
{
return sex;
}
char*gettelephone()
{
return telephone;
}
int getage()
{
return age;
}
double getmonthwages()
{
return monthwages;
}
void setnumber(char temp[])
{
renumber: if(strlen(temp)>15)
{
cout<<"输入错误(不能多余15个字母或5个汉字)!请重新输入。\n";
char temp1[15];
cout<<"教 工 号:\t";
cin>>temp1;
if(strlen(temp1)>15)
goto renumber;
else
strcpy(number,temp1);
}
else
strcpy(number,temp);
}
void setname(char temp[])
{
renumber: if(strlen(temp)>15)
{
cout<<"输入错误(不能多余15个字母或5个汉字)!请重新输入。\n";
char temp1[10];
cout<<"姓 名:\t";
cin>>temp1;
if(strlen(temp1)>15)
goto renumber;
else
strcpy(name,temp1);
}
else
strcpy(name,temp);
employees++;
}
void setpost(char temp[])
{
renumber: if(strlen(temp)>10)
{
cout<<"输入错误(不能多余十个字母或五个汉字)!请重新输入。\n";
char temp1[10];
cout<<"职 位\t";
cin>>temp1;
if(strlen(temp1)>10)
goto renumber;
else
strcpy(post,temp1);
}
else
strcpy(post,temp);
}
void setsex()
{
cout<<"性别(1、男;2、女):";
resex: char temp1[5];
cin>>temp1;
if(strlen(temp1)==1)
{
switch(temp1[0])
{
case '1':
strcpy(sex,"男");
break;
case '2':
strcpy(sex,"女");
break;
default:
cout<<"错误(请选择1或2)";
goto resex;
}
}
else
{
cout<<"错误(请选择1或2)";
goto resex;
}
}
void settelephone(char temp[])
{
retelephone: if(strlen(temp)>20)
{
cout<<"输入错误(不能多余二十个数字)!请重新输入。\n";
char temp1[20];
cout<<"电 话 号 码:\t";
cin>>temp1;
if(strlen(temp1)>20)
goto retelephone;
else
strcpy(telephone,temp1);
}
else
strcpy(telephone,temp);
}
void setage(int temp)
{
renumber: if(temp<=18||temp>65)
{
cout<<"输入错误!请重新输入。\n";
int temp1;
cout<<"年 龄:\t";
cin>>temp1;
if(temp1<=0||temp1>120)
goto renumber;
else
age=temp1;
}
else
age=temp;
}
void setmonthwages(double temp)
{
monthwages=temp;
}
};
long employee::employees=0;
//讲师类的定义*****************************************************************
class technician: public employee{
protected:
static int technicians;//用来记数讲师的数量********************************
public:
int gettechnicians()
{
return technicians;
}
void setnumber(char temp[])
{
technicians++;
employee::setnumber(temp);
}
void monthly_wages(double temp)
{
setmonthwages(temp*100);
//讲师的工资为课程量*课时工资100每课时**************************
}
};
int technician::technicians=0;
//辅导员类的定义***************************************************************
class manager:public employee{
static int managers;//辅导员的数量*****************************************
public:
int getmanagers()
{
return managers;
}
void monthly_wages()
{
setmonthwages(5000);//辅导员的工资为五千固定***************************
managers++;
}
};
int manager::managers=0;
//教授类的定义*****************************************************************
class seller:public employee{
protected:
static double sellroom;
static double sellrooms;
static int sellers;
public:
int getsellers()
{
return sellers;
}
double getsellroom()
{
return sellroom;
}
double getsellrooms()
{
return sellrooms;
}
void setsellroom(double temp)
{
sellroom=temp;
sellrooms=sellrooms+temp;
}
void monthly_wages()
{
setmonthwages(sellroom*0.04);
sellers++;
}
};
double seller::sellroom=0;
double seller::sellrooms=0;
int seller::sellers=0;
//行政人员类的定义*************************************************************
class sellermanager:public seller{
static int sellermanagers;//行政人员的数量*********************************
public:
int getsellermanagers()
{
return sellermanagers;
}
double getsellrooms()
{
return sellrooms;
}
void monthly_wages()
{
setmonthwages(sellrooms*0.005+5000);
sellermanagers++;
}
};
int sellermanager::sellermanagers=0;
//各数据输入的原函数声明*******************************************************
void inputtechnician(employee&);
void inputmanager(employee&);
void inputseller(employee&);
void inputsellermanager(employee&);
void compositorall(employee*);//对所有教工的工资降序排列***********************
int printfile();//把文件中的资料显示到显示器上*********************************
void outputtofile(employee*);//把资料保存到文件中******************************
//主函数***********************************************************************
int main()
{
employee employeeall[EMP];
int i=0;
while(i<EMP)
{
system("cls"); //刷新屏幕**********************************************
cout<<"*** 本系统能存入"<<EMP<<"个教工的资料 ***\n";
cout<<" *** 已经输入了"<<employeeall[0].getemployees()
<<"教工的资料 ****\n";
cout<<" ********************************\n";
cout<<" *** 1、输入讲 师的资料; ***\n";
cout<<" *** 2、输入辅 导 员的资料; ***\n";
cout<<" *** 3、输入教 授的资料; ***\n";
cout<<" *** 4、输入行政人员的资料; ***\n";
cout<<" *** 5、退出输入! ***\n";
cout<<" ********************************\n";
cout<<"请选择:";
char n[5];
cin>>n;
if(strlen(n)==1)
{
switch(n[0])
{
case '1':
inputtechnician(employeeall[i]);
i++;
break;
case '2':
inputmanager(employeeall[i]);
i++;
break;
case '3':
inputseller(employeeall[i]);
i++;
break;
case '4':
inputsellermanager(employeeall[i]);
i++;
break;
case '5':
system("cls"); //刷新屏幕**************************************
compositorall(employeeall);//对所有教工的工资降序排列**********
outputtofile(employeeall);//把资料保存到文件中*****************
cout<<"是否打印资料(y/n)";
char a[5];
cin>>a;
if(a[0]=='y'||a[0]=='Y')
printfile();//把文件中的资料显示到显示器上*****************
return 1;
default:
cout<<"\t错误!请重新输入!\n";
}
}
else
cout<<"\t错误!请重新输入!\n";
}
compositorall(employeeall);//对所有教工的工资降序排列**********************
outputtofile(employeeall);//把资料保存到文件中*****************************
printfile();//把文件中的资料显示到显示器上*********************************
return 0;
}
//教工基本信息的输入函数*******************************************************
void inputtechnician(employee &empl)
{
technician tech;
cout<<"\n★★教工资料:\n";
char temp[20];
cout<<"姓 名:\t";
cin>>temp;
empl.setname(temp);
cout<<"教 工 号:\t";
cin>>temp;
empl.setnumber(temp);
empl.setpost("讲 师");
empl.setsex();
cout<<"电 话 号 码:\t";
cin>>temp;
empl.settelephone(temp);
int tempq=0;
cout<<"年 龄:\t";
cin>>tempq;
empl.setage(tempq);
double tempp=0;
cout<<"工作时间(课时):\t";
cin>>tempp;
tech.monthly_wages(tempp);
empl.setmonthwages(tech.getmonthwages());
}
//辅导员的基本信息的输入函数***************************************************
void inputmanager(employee &empl)
{
manager mana;
cout<<"\n★★辅导员资料:\n";
char temp[20];
cout<<"姓 名:\t";
cin>>temp;
empl.setname(temp);
cout<<"教 工 号:\t";
cin>>temp;
empl.setnumber(temp);
empl.setpost("辅 导 员");
empl.setsex();
cout<<"电 话 号 码:\t";
cin>>temp;
empl.settelephone(temp);
int tempq=0;
cout<<"年 龄:\t";
cin>>tempq;
empl.setage(tempq);
mana.monthly_wages();
empl.setmonthwages(mana.getmonthwages());
}
//教授的基本信息的输入函数*****************************************************
void inputseller(employee &empl)
{
seller sell;
cout<<"\n★★教授资料:\n";
char temp[20];
cout<<"姓 名:\t";
cin>>temp;
empl.setname(temp);
cout<<"教 工 号:\t";
cin>>temp;
empl.setnumber(temp);
empl.setpost("教 授");
empl.setsex();
cout<<"电 话 号 码:\t";
cin>>temp;
empl.settelephone(temp);
int tempq=0;
cout<<"年 龄:\t";
cin>>tempq;
empl.setage(tempq);
double tempp=0;
cout<<"课 程 量:\t";
cin>>tempp;
sell.setsellroom(tempp);
sell.monthly_wages();
empl.setmonthwages(sell.getmonthwages());
}
//行政人员的基本信息的输入函数*************************************************
void inputsellermanager(employee &empl)
{
sellermanager sellmana;
cout<<"\n★★行政人员资料:\n";
char temp[20];
cout<<"姓 名:\t";
cin>>temp;
empl.setname(temp);
cout<<"教 工 号:\t";
cin>>temp;
empl.setnumber(temp);
empl.setpost("行政人员");
empl.setsex();
cout<<"电 话 号 码:\t";
cin>>temp;
empl.settelephone(temp);
int tempq=0;
cout<<"年 龄:\t";
cin>>tempq;
empl.setage(tempq);
sellmana.setsellroom(sellmana.getsellrooms());
sellmana.monthly_wages();
empl.setmonthwages(sellmana.getmonthwages());
}
//把资料保存到文件中***********************************************************
void outputtofile(employee *empl)
{
ofstream fout;
fout.open("E:\\ 计算机与通信学院教师工资管理系统文档.txt");
if(!fout)
cout<<"Open file error!";
else
{
fout<<"姓 名"<<"\t";
fout<<"教工号"<<"\t";
fout<<"职 位"<<"\t";
fout<<"性别"<<"\t";
fout<<"年龄"<<"\t";
fout<<"电话号码"<<"\t";
fout<<"月工资"<<"\n";
for(int i=0;i<empl[0].getemployees();i++)
{
fout<<empl[i].getname()<<"\t";
fout<<empl[i].getnumber()<<"\t";
fout<<empl[i].getpost()<<"\t";
fout<<empl[i].getsex()<<"\t";
fout<<empl[i].getage()<<"\t";
fout<<empl[i].gettelephone()<<"\t";
fout<<empl[i].getmonthwages()<<"\n";
}
}
}
//把文件中的资料显示到显示器上*************************************************
int printfile()
{
system("cls");
ifstream fcin;
fcin.open("E:\\计算机与通信学院教师工资管理系统文档.txt");
if(!fcin)
{
cout<<"打开文件失败,系统自动退出!";
return 4;
}
char ch;
while(fcin.get(ch))
{
cout<<ch;
}
fcin.close();
return 0;
}
//用冒泡法对所有教工的工资降序排列*********************************************
void compositorall(employee *temp)
{
employee temp1;
for(int j=0;j<temp[0].getemployees();j++)
for(int i=temp[0].getemployees()-1;i>j;i--)
{
if(temp[i].getmonthwages()>temp[i-1].getmonthwages())
{
temp1=temp[i];
temp[i]=temp[i-1];
temp[i-1]=temp1;
}
}
}