程序设计基础课程设计报告(c语言实现附源码)(员工工资管理系统)
- 格式:doc
- 大小:256.00 KB
- 文档页数:34
《程序设计基础》课程设计报告题目:员工工资管理系统院(系):信息科学与工程学院专业班级:学生姓名:学号:指导教师:20 16 年 12 月 12 日至20 16 年 12 月 23 日武昌首义学院制程序设计基础课程设计任务书目录1需求与总体设计 (1)2详细设计 (1)3编码实现 (4)4运行结果 (21)总结 (24)1需求与总体设计1.1需求描述设计一个利用文件处理方式实现对员工工资(包括员工编号、员工姓名、年月、岗位工资、奖金、扣款和实发)进行管理,具有增加数据、更新数据、查询数据、删除数据、列表显示数据以及重组文件的功能。
1.2总体设计先以登陆函数登陆,再进入主菜单,菜单中显示各个要实现的操作,以菜单将各个函数联系起来,对菜单操作以实现系统的目的。
1.3数据结构struct user //登陆者信息{char un[10];char up[10];}us[3] = { "aaa","111","bbb","222","ccc","333" };struct yg //员工结构体{short zt; //数据状态long bh; //编号char name[20]; //名字char time[11]; //时间long money; //基本工资long jj; //奖金long kk; //扣款long sf; //实发工资};整个程序只运用了结构体的数据结构,结构体运用于登陆者信息和员工信息,将员工信息封装在一个结构体里,再创建结构体数组,将多个员工信息储存在结构体数组中。
2详细设计2.1 系统功能设计主函数和子函数:系统包含一个主函数,和子函数,分别有登陆子函数,菜单子函数,增加数据子函数,更新数据子函数,查询数据子函数,删除数据子函数,统计数据子函数,重组文件子函数,排序数据子函数,最后两个分别是读取文件和写入文件子函数。
各个函数的功能:主函数是一个入口程序从这里进入,再进入登陆函数,实现登陆操作。
登陆函数,只有拥有正确账号密码,正确的操作才可以进入菜单界面进行下一步的操作,并且输入错误三次后将会提示并强制退出。
菜单界面利用switch()函数将各个函数联系起来实现真正的菜单,输入正确的序号可以进行后续的各个操作。
读取函数,将特定文件中的信息,以特定的方式读取到正在运行的程序中,实现读写操作。
写入函数,在添加、更新、删除、重组操作过后进行写入操作,将变换后的数据重新写入文件中。
注:每次写入都是将程序中的所有数据重新写入文件。
增加函数,可以新添员工,并将员工的数据输入,并利用写入函数,写入文件中。
在增加后会提示是否继续增加,提供了方便。
并且如果原数据中有相同编号的员工,会在输入编号后提示有相同的编号的员工,并重新输入编号。
增加了程序的健全性。
更新数据函数,以编号来确定更新的员工,更新将重新输入该编号员工的信息,并在更新后执行写入。
删除函数,执行该函数后,将有两种选择,按编号删除,或按名字删除,正确输入后将会将该编号或姓名的数据中的一项zt的值更改为1,使其在其他操作时不被识别,以达到不删除数据,但达到相同的效果的逻辑删除。
显示函数,有两种显示方式,按学号显示或按名字显示,学号显示为从小到大显示。
重组函数,将文件中逻辑删除的数据物理删除,用来节省储存空间,并可以加快运算速度。
统计数据,将文件中的数据统计、计算,并输出,给人以直观的方式显示数据。
排序函数,将数据以实发工资从大到小排序。
2.2 系统流程设计3编码实现#define MAX 100#include<stdio.h>#include<string.h>#include<stdlib.h>struct user //登陆者信息{char un[10];char up[10];}us[3] = { "aaa","111","bbb","222","ccc","333" };struct yg //员工结构体{short zt; //数据状态long bh; //编号char name[20]; //名字char time[11]; //时间long money; //基本工资long jj; //奖金long kk; //扣款long sf; //实发工资};yg y[MAX]; //定义数据体数组int r = 0; //全局变量,人数,包括逻辑删除人数int p = 0; //登陆的次数,用全局变量能在登陆三次失败时退出程序void read() //读取文件函数{FILE *fp;char b;int i;b = '0';printf("即将读取文件员工信息.dat\n");if ((fp = fopen("员工信息.dat", "rb")) == NULL) //读取文件{printf("员工信息.dat 文件不存在\n");printf("是否重新创建该文件?\n");printf("创建(y) 员工信息.dat 或退出(n)\n");getchar();b = getchar();while (getchar() != '\n')if (b == 'Y' || b == 'N')b += 32;while (b != 'y'&&b != 'n'){printf("输入错误!请重新输入!\n");b = getchar();while (getchar() != '\n')if (b == 'Y' || b == 'N')b += 32;}if (b == 'y')if ((fp = fopen("员工信息.dat", "wb")) == NULL) //文件不存在则创建文件{printf("创建文件失败!\n");printf("按下任意键以退出程序!\n");getchar();exit(1);}}if (b == '0'){fread(&r, 4, 1, fp);printf("读取成功!\n");}elseprintf("创建文件成功!\n");if (r != 0)for (i = 0; i < r; i++)fread(&y[i], sizeof(yg), 1, fp);fclose(fp);}void save() //保存文件函数{FILE *fp;int i;if ((fp = fopen("员工信息.dat", "wb")) == NULL){printf("保存文件失败!\n");printf("按下任意键以退出程序!\n");getchar();exit(1);}else{fwrite(&r, 4, 1, fp);if (r != 0)for (i = 0; i < r; i++)fwrite(&y[i], sizeof(yg), 1, fp);}fclose(fp);}void zj_data() //增加数据函数{yg yuangong;char b;int i;int k = 0;yuangong.zt = 0; //新建员工信息时,状态为0 do //用循环来寻找、避免相同编号的员工{printf("编号:(例如:123456)\n");scanf("%d", &yuangong.bh);for (i = 0; i < r; i++)if (y[i].bh == yuangong.bh&&y[i].zt==0){printf("已有同编号员工无法添加!\n");printf("请重新输入!\n");k = 1;break;}else if (i == r - 1)k = 0;} while (k == 1);printf("姓名:(例如:张三(or tom))\n");scanf("%s", );printf("年月:(例如:2015.11.11)\n");scanf("%s", yuangong.time);printf("岗位工资:(例如:50000)\n");scanf("%d", &yuangong.money);printf("奖金:(例如:2000)\n");scanf("%d", &yuangong.jj);printf("扣款:(例如:100)\n");scanf("%d", &yuangong.kk);printf("实发工资为:(岗位工资+奖金-扣款)\n");yuangong.sf = yuangong.money + yuangong.jj - yuangong.kk;printf("%d\n", yuangong.sf);y[r] = yuangong;r++; //新建员工信息时人数r++ save();printf("添加成功!\n");getchar(); //防止下面一个%c读取到上一个的回车printf("是否继续添加员工?(y/n)\n");b = getchar();while (getchar() != '\n');if (b == 'Y' || b == 'N')b += 32;while (b != 'y'&&b != 'n'){printf("输入错误!请重新输入!\n");b = getchar();while (getchar() != '\n')if (b == 'Y' || b == 'N')b += 32;}if (b == 'y')zj_data();}void gx_data() //更新数据{yg yuangong;long num;int i;printf("\n请输入要更新的员工的编号!\n");scanf("%d", &num);for (i = 0; i < r; i++)if (y[i].bh == num&&y[i].zt == 0){yuangong = y[i];printf("当前该员工信息为:\n");printf("编号:%d\n", yuangong.bh);printf("姓名:%s\n", );printf("年月:%s\n", yuangong.time);printf("岗位工资:%d\n", yuangong.money);printf("奖金:%d\n", yuangong.jj);printf("扣款:%d\n", yuangong.kk);printf("实发工资:%d\n", yuangong.sf);printf("按下任意键输入更新后的信息!\n");getchar();getchar();printf("编号:(例如:123456)\n");scanf("%d", &yuangong.bh);printf("姓名:(例如:张三(or tom))\n");scanf("%s", );printf("年月:(例如:2015.11.11)\n");scanf("%s", yuangong.time);printf("岗位工资:(例如:50000)\n");scanf("%d", &yuangong.money);printf("奖金:(例如:2000)\n");scanf("%d", &yuangong.jj);printf("扣款:(例如:100)\n");scanf("%d", &yuangong.kk);printf("实发工资为:(岗位工资+奖金-扣款)\n");yuangong.sf = yuangong.money + yuangong.jj - yuangong.kk;printf("%d\n", yuangong.sf);y[i] = yuangong;save();printf("更新成功!\n");break;}else if (i == r - 1)printf("查无此人!\n");}void cz_data() //查询数据{yg yuangong;int a, i;long num;char na[10];printf("\n请选择查询方式!\n"); //分为按编号查询和姓名查询printf(" *******************\n");printf(" * 1、编号查询 *\n");printf(" * 2、姓名查询 *\n");printf(" * 3、返回菜单 *\n");printf(" *******************\n");scanf("%d", &a);if (a == 1){printf("请输入查询员工的编号:");scanf("%d", &num);for (i = 0; i < r; i++) //编号查询则循环r次,查找状态为0且编号与所输入的数字相同的数据if (y[i].zt == 0 && y[i].bh == num){yuangong = y[i];printf("当前该员工信息为:\n");printf("编号:%d\n", yuangong.bh);printf("姓名:%s\n", );printf("年月:%s\n", yuangong.time);printf("岗位工资:%d\n", yuangong.money);printf("奖金:%d\n", yuangong.jj);printf("扣款:%d\n", yuangong.kk);printf("实发工资:%d\n", yuangong.sf);break;}else if (i == r - 1)printf("查无此人!\n");}else if (a == 2){printf("请输入查询员工的姓名:");scanf("%s", na);for (i = 0; i < r; i++) //姓名查询则循环r次,查找状态为0且编号与所输入的字符串相同的数据if ((strcmp(y[i].name, na) == 0) && y[i].zt == 0){yuangong = y[i];printf("当前该员工信息为:\n");printf("编号:%d\n", yuangong.bh);printf("姓名:%s\n", );printf("年月:%s\n", yuangong.time);printf("岗位工资:%d\n", yuangong.money);printf("奖金:%d\n", yuangong.jj);printf("扣款:%d\n", yuangong.kk);printf("实发工资:%d\n", yuangong.sf);break;}else if (i == r - 1)printf("查无此人!\n");}else if (a == 3){}else{printf("输入错误!\n");cz_data();}}void sc_data() //删除数据{yg yuangong;long num;int a, i, b;char na[10];printf("\n请选择!\n"); //删除也按编号删除和姓名删除printf(" *********************\n");printf(" * 1、按编号删除 *\n");printf(" * 2、按姓名删除 *\n");printf(" * 3、返回主菜单 *\n");printf(" *********************\n");scanf("%d", &a);if (a == 1){printf("请输入要删除员工的编号:");scanf("%d", &num);for (i = 0; i < r; i++)if (y[i].zt == 0 && y[i].bh == num){yuangong = y[i];printf("当前该员工信息为:\n");printf("编号:%d\n", yuangong.bh);printf("姓名:%s\n", );printf("年月:%s\n", yuangong.time);printf("岗位工资:%d\n", yuangong.money);printf("奖金:%d\n", yuangong.jj);printf("扣款:%d\n", yuangong.kk);printf("实发工资:%d\n", yuangong.sf);y[i].zt = 1;save();printf("删除成功!\n");getchar(); //防止下面一个%c 读取到上一个的回车printf("是否继续删除员工?(y/n)\n");b = getchar();while (getchar() != '\n');if (b == 'Y' || b == 'N')b += 32;while (b != 'y'&&b != 'n'){printf("输入错误!请重新输入!\n");b = getchar();while (getchar() != '\n')if (b == 'Y' || b == 'N')b += 32;}if (b == 'y')sc_data();break;}else if (i == r - 1)printf("查无此人,无法删除!\n");}else if (a == 2){printf("请输入删除员工的姓名:");scanf("%s", na);for (i = 0; i < r; i++)if ((strcmp(y[i].name, na) == 0) && y[i].zt == 0){yuangong = y[i];printf("当前该员工信息为:\n");printf("编号:%d\n", yuangong.bh);printf("姓名:%s\n", );printf("年月:%s\n", yuangong.time);printf("岗位工资:%d\n", yuangong.money);printf("奖金:%d\n", yuangong.jj);printf("扣款:%d\n", yuangong.kk);printf("实发工资:%d\n", yuangong.sf);y[i].zt = 1;save();printf("删除成功!\n");getchar(); //防止下面一个%c 读取到上一个的回车printf("是否继续删除员工?(y/n)\n");b = getchar();while (getchar() != '\n');if (b == 'Y' || b == 'N')b += 32;while (b != 'y'&&b != 'n'){printf("输入错误!请重新输入!\n");b = getchar();while (getchar() != '\n')if (b == 'Y' || b == 'N')b += 32;}if (b == 'y')sc_data();break;}else if (i == r - 1)printf("查无此人,无法删除!\n");}else if (a == 3) //输入为3时不执行操作返回主菜单{}else{printf("输入错误!\n");sc_data();}}void xs_data() //显示数据{yg yuangong[MAX], t;int a;int i, j;int k = 0;printf("\n请选择显示方式!\n");printf(" *********************\n");printf(" * 1、按编号显示 *\n");printf(" * 2、按姓名显示 *\n");printf(" * 3、返回主菜单 *\n");printf(" *********************\n");scanf("%d", &a);for (i = 0; i < r; i++){yuangong[i] = y[i];if (y[i].zt == 1)k++;}if (k == r){printf("无员工信息!\n");a = 3;}if (a == 1) //按编号显示时用冒泡排序从大到小排序{for (i = 1; i <= r; i++)for (j = 0; j<r - i; j++)if (yuangong[j].bh > yuangong[j + 1].bh){t = yuangong[j];yuangong[j] = yuangong[j + 1];yuangong[j + 1] = t;}printf("按编号排列如下:\n");printf("%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", "编号", "姓名", "年月", "岗位工资", "奖金", "扣款", "实发工资");for (i = 0; i<r; i++)if (yuangong[i].zt == 0)printf("%-10d%-10s%-10s%-10d%-10d%-10d%-10d\n",yuangong[i].bh, yuangong[i].name, yuangong[i].time, yuangong[i].money, yuangong[i].jj, yuangong[i].kk, yuangong[i].sf);printf("显示完毕!\n");}else if (a == 2) //按名字显示时用冒泡排序从大到小排序,用strcmp来比较字符串的大小{for (i = 1; i <= r; i++)for (j = 0; j<r - i; j++)if (strcmp(yuangong[j].name, yuangong[j + 1].name) > 0){t = yuangong[j];yuangong[j] = yuangong[j + 1];yuangong[j + 1] = t;}printf("按姓名排列如下:\n");printf("%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", "编号", "姓名", "年月", "岗位工资", "奖金", "扣款", "实发工资");for (i = 0; i<r; i++)if (yuangong[i].zt == 0)printf("%-10d%-10s%-10s%-10d%-10d%-10d%-10d\n",yuangong[i].bh, yuangong[i].name, yuangong[i].time, yuangong[i].money, yuangong[i].jj, yuangong[i].kk, yuangong[i].sf);printf("显示完毕!\n");}else if (a == 3){}else{printf("输入错误!\n");cz_data();}}void chongz_data() //重组文件{int i, j;int k = 0;for (i = 0; i < r; i++) //循环r次,将状态为1的数据剔除,并将剔除数据的个数记录if (y[i].zt == 1){for (j = i; j < r; j++)y[j] = y[j + 1];k++;}r -= k; //将人数r重新计算save();printf("重组成功!\n");}void tj_data() //统计数据{yg yuangong[MAX];int max, m, k = 0;double ave = 0;int n = 0;int i;for (i = 0; i < r; i++) //计算文件中逻辑删除的数据个数k{16yuangong[i] = y[i];if (yuangong[i].zt == 1)k++;}for (i = 0; i < r; i++) //将数组中第一个状态为0的数据的实发工资赋给max,并记录是第几位,跳出循环if (yuangong[i].zt == 0){max = yuangong[i].sf;m = i;break;}if (yuangong[0].zt == 0) //第一个数据是否逻辑删除?否,将实发工资赋给ave未计算的平均值ave = yuangong[0].sf;for (i = 1; i < r; i++) //循环找出最大值,并将所有正常数据加入未计算的ave中{if ((max < yuangong[i].sf) && (yuangong[i].zt == 0))m = i;if (yuangong[i].zt == 0)ave += yuangong[i].sf;}ave = ave / (r - k); //计算avefor (i = 0; i < r; i++) //将数据中所有大于ave的数据,统计if ((yuangong[i].sf > ave) && (yuangong[i].zt == 0))n++;printf("\n最高实发工资员工信息为:\n"); //输出结果printf("%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", "编号", "姓名", "年月", "岗位工资", "奖金", "扣款", "实发工资");printf("%-10d%-10s%-10s%-10d%-10d%-10d%-10d\n", yuangong[m].bh, yuangong[m].name, yuangong[m].time, yuangong[m].money, yuangong[m].jj, yuangong[m].kk, yuangong[m].sf);printf("平均工资为:%.2f\n", ave);printf("超过平均工资人数为:%d\n\n", n);}void px_data() //排序数据{yg yuangong[MAX], t;int num = 0;int i, j;for (i = 0; i < r; i++)yuangong[i] = y[i];for (i = 1; i <= r; i++) //冒泡排序排序所有数据for (j = 0; j < r - i; j++)if (yuangong[j].sf<yuangong[j + 1].sf){t = yuangong[j];yuangong[j] = yuangong[j + 1];yuangong[j + 1] = t;}printf("\n所有员工信息为:\n");printf("%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n", "编号", "姓名", "年月", "岗位工资", "奖金", "扣款", "实发工资");for (i = 0; i<r; i++)if (yuangong[i].zt == 0)printf("%-10d%-10s%-10s%-10d%-10d%-10d%-10d\n", yuangong[i].bh, yuangong[i].name, yuangong[i].time, yuangong[i].money, yuangong[i].jj, yuangong[i].kk, yuangong[i].sf);}void cd() //菜单函数{int l;do{printf("欢迎进入员工工资管理系统菜单!\n");printf(" ________________\n");printf(" *| 1.增加数据 |*\n");printf(" *| 2.更新数据 |*\n");printf(" *| 3.查询数据 |*\n");printf(" *| 4.删除数据 |*\n");printf(" *| 5.显示数据 |*\n");printf(" *| 6.重组数据 |*\n");printf(" *| 7.统计输出 |*\n");printf(" *| 8.排序数据 |*\n");printf(" *| 9.退出 |*\n");printf(" *|[其它输入为退出]|*\n");printf(" *|________________|*\n\n");printf("请输入你的选择:\n");scanf("%d", &l);switch (l){case 1:zj_data(); printf("即将返回主菜单\n"); system("PAUSE"); break; //system用于返回主菜单时等待一下case 2:gx_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 3:cz_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 4:sc_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 5:xs_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 6:chongz_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 7:tj_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 8:px_data(); printf("即将返回主菜单\n"); system("PAUSE");break;case 9:break;}} while (l != 9 && (l == 1 || l == 2 || l == 3 || l == 4 || l == 5 || l== 6 || l == 7 || l == 8));}void dl() //登陆函数{int i;char a[10], b[10];printf("请输入用户名:\n");scanf("%s", a);printf("请输入密码:\n");scanf("%s", b);for (i = 0; i<3; i++)if (strcmp(us[i].un, a) == 0 && strcmp(us[i].up, b) == 0){printf("登录成功!\n");read();cd();break;}if (i == 3){printf("登录失败!\n");p++;if (p >= 3){printf("登录失败超过3次,系统将强制退出!\n");printf("按下任意键以退出程序!\n");getchar();getchar();exit(1);}elsedl();}}int main() //主函数{dl();return 0;}4运行结果输入三次登陆失败输出:登陆成功读取文件,无文件时:创建文件成功后进入菜单界面:增加数据输入界面:当输入数据中原本就有的员工编号时:所有数据输入完成后,显示所有数据:有两种显示方式将其中一人的数据执行更新操作:编号错误时:正确时:查询:两种方式删除数据:两种方式重组完成:数据处理完成后,显示所有数据:统计数据:以实发工资高到低排序数据:总结拿到课设题目时,以为很简单,只是将一些函数堆叠在一起就行了,写的时候也没觉得很难,但在调试程序时,各种各样的bug眼花缭乱,如何找出、修改bug占了大部分时间。