本课题解决的主要问题
(1)职员的基本信息录入。
(2)职员的工资信息查询。
(3)职员的工资信息统计。
(4)设置一个简易的界面。
技术要求
对结构体和指针的使用:职员工资管理系统需要用到结构体来定义职员信息和工资数据,而指针则可以用于动态管理这些数据。
文件操作的知识:职员信息和工资数据需要存储在文件中,因此需要掌握c语言中的文件操作相关知识,如fopen,fclose,fwrite,fread等函数。
数组和字符串的处理:在职员工资管理系统中,可能需要用到数组和字符串来存储和处理职员信息和工资数据,需要掌握相关知识。
循环和条件语句的应用:职员工资管理系统需要实现各种功能,如添加,删除,修改,查询职员信息和计算工资数据等,这些功能可以通过循环和条件语句来实现。
动态内存分配的使用:职员工资管理系统需要用到动态内存分配的技术,以便动态管理职员信息和工资数据。
函数的定义与调用:为了实现职员工资管理系统的各种功能,需要将不同的功能模块封装成函数,并进行函数调用,以便提高代码的复用性和可维护性。
程序功能
(1)职员信息录入:系统可以将每一个职员的姓名以及基本工资、职务工资、岗位津贴、医疗保险、公积金的数据作为一个记录。该软件能建立一个新的数据文件或给已建立好的数据文件增加记录。
(2)职员信息显示:系统根据用户提供的记录或者根据职员姓名显示一个或几个职员的各项工资和平均工资。
(3)职员信息修改:系统可以对数据文件的任意记录的数据进行修改并在修改前后对记录内容进行显示。
(4)职员信息查找:系统可以对数据文件的任意记录的数据进行查找并在查找前后对记录内容进行显示。
(5)职员信息删除:系统可删除数据文件中的任一记录。
(6)职员信息统计:
①计算各项工资平均工资及总工资;
②统计符合指定条件(如职员工资前三项之和在3000元以上、3000~2000元、2000~1000元)以内的工资职员人数及占总职员人数的百分比。
③按字符表格形式打印全部职员工资信息表及平均工资(包括各项总的平均工资)。
(7)保存数据文件功能。
职员工资管理系统介绍
通过编写一个职员工资管理系统,通过键盘式选择菜单实现功能选择(比如输入数字1表示创建职员数据)。功能包括:数据输入,数据输出,数据添加,数据修改,数据删除,数据查找,数据统计等,各功能模块使用独立的函数来表示,通过主函数直接或间接调用。
功能需求分析
职员工资管理系统采用的开发工具是visual studio,主要用于对大量的职员信息,包括职员的工号,姓名,基本工资,岗位津贴,医疗保险,公积金的数据作为一个记录。该系统能建立一个新的数据文件或给已建立好的数据文件增加记录。
功能模块设计
- 输入职员信息:void input()函数
- 显示职员信息:void display()函数
- 查询职员信息:void search()函数
----(分别按职员号、姓名查询:void search_num(),void search_name())
- 添加职员信息:void add()函数
- 删除职员信息:void del()函数
- 修改职员信息:void modify()函数
- 统计职员信息:void sta()函数
- 保存到文件:void save(int m)函数
- 从文件装载:int load()函数
- 退出:exit_system()函数
界面设计
(1)职员员工工资管理系统的界面设计主要遵循方便易用,界面友好的原则,当程序运行时,代码会在控制台中输出一段带有特定格式的欢迎信息,包括学校名字,学院名字以及职员工资管理系统的名称,旨在引导用户进入系统并提供必要的信息。此外,设置控制台的颜色为淡黄色和红色的组合,以增加界面的可读性和吸引力。最后,调用系统函数清屏,以确保在开始界面之前没有其他信息。具体设计如图所示。
主要函数说明
- 输入:输入职员工资资料
通过结构体的数组来进行操作,先头定义数组em[],先输入需要输入的职员人数m,然后进入循环,每次循环将各项输入结构体数组对应项的对应成员中,当循环次数等于人数时,完成全部员工的资料输入,退出循环。同时将数据储存在ckerk_list文件中并自动保存至磁盘。
注:1)如首次使用,尚未输入数据,请先输入数据。输入的数据将自动保存。
2)再次选择输入功能时原数据将被覆盖。
- 保存:将输入的资料存入磁盘
读取文件clerk_list,若文件不存在,打印“打开失败”并退出。若存在,则通过循环语句将输入到结构体数组的数据逐个输入磁盘。
- 读取:读取磁盘中的资料
打开文件clerk_list ,若文件不存在,打印“打开失败”并退出。若存在,读取文件中的数据,并返回职员人数。
- 显示:显示职员工资资料
先通过读取函数的返回值确定职员人数m,再通过循环将员工工资资料逐个打印,当循环次数达到m时退出循环。(其中总工资由程序计算,总工资=基本工资+职务工资+津贴-医疗保险-公积金)
- 删除:删除某员工的资料
打印员工资料并提示输入要删除职员的姓名,输入后若该职员不存在则打印“查无此人”;若存在,则显示该职员资料并询问是否确定删除。若确定,则删除。删除时,通过对比输入的姓名与资料中的姓名做对比从而确定要删除的项i,从第i项开始,将后一项的各成员的值赋给前一项各对应的成员,完成对第i项的删除。
- 添加:添加新的员工资料而不覆盖原有资料
打印原有职员资料,询问要添加的职员人数并询问是否确定添加。逐个逐项输入员工信息,之后程序计算其总工资。完成后显示“添加成功”,打印新的员工资料并自动保存。添加的方法为:定义一个相同类型的结构体数组,将原有项复制后增添新的项,并保存新的数组。
- 查找:按ID号查询与按姓名查找员工资料
根据提示输入要查询的ID号或姓名,程序通过循环语句将输入的数字与以保存的结构体数组中的数据对比,若相同,则打印“已找到”及该员工的资料;当循环次数等于人数时结束循环,若至结束循环时也没有找到相同的,则打印“查无此人”。
- 修改:修改特定员工的特定资料
打印员工信息并提示输入要修改资料的职员姓名。按提示确定要修改,确定要修改的项目,输入要修改成的结果并将该结果赋给对应项的对应成员,完成对特定职员特定项目的修改。
- 统计
通过循环对结构体数组中的每一项经行统计,计算工资总额为,将工资总额除以人数计算出平均工资。
小结
《C语言程序设计》是一门实践性很强的课程,该课程的学习有其自身的特点,听不会,也看不见,只能练会。因此我们必须通过大量的编程训练,在实践中培养程序设计的基本能力,对C语言的基础知识进行查漏补缺,并逐步理解和掌握程序设计的思想和方法。
通过在职员工资管理系统的C语言课程设计中,我通过编写代码和测试程序,深入了解了C语言编程的基础知识和一些实际编程技能。在这个过程中,我遇到了许多挑战,但也从中获得了许多有价值的经验。
首先,我意识到了代码的规范和结构对于程序可读性和可维护性的重要性。在编写代码时,我严格按照规范化的风格和命名规则进行编写,这使得我的代码更易于阅读和理解。同时,我还按照设计原则和模块化思想将代码分成多个函数,从而实现了代码的结构化和复用,为后续的调试和维护工作打下了基础。
其次,我深刻体会到了程序调试和错误处理的重要性。在编写代码和测试程序时,我发现很多错误和异常情况,并通过调试器和日志信息来定位和解决这些问题。我也经常使用printf语句来输出变量值和调试信息,这有助于我更好地理解程序的运行过程和状态,及时发现和解决错误。同时,我也积极采用异常处理机制,以避免程序在出现错误时崩溃或产生未预期的行为。
另外,我学会了如何将C语言的基础知识和实际编程技能应用于具体问题的解决。在职员工资管理系统的设计中,我需要用到结构体、指针、文件读写等C语言的高级特性。通过深入学习和练习这些知识点,我逐渐掌握了它们的应用场景和使用方法,使得我的程序功能更加完善和稳定。
最后,我认识到了团队合作和分享的重要性。在编写代码和测试程序的过程中,我和同组的同学互相协作和交流,分享彼此的经验和技巧。这不仅提高了我们的工作效率,还加深了我们对C语言的理解和应用,让我们更加熟练地掌握了这门语言。
总的来说,职员工资管理系统的C语言课程设计让我受益匪浅。通过实践和反思,我不仅掌握了C语言编程的基本技能和思想,还培养了良好的编程习惯和团队合作能力,为我未来的学习和工作打下了坚实的基础
//头文件
#include<stdio.h>
#include<string.h>
struct clerk
{
int num;
char name[20];
int jbgz;
int zwgz;
int jt;
int yb;
int gjj;
int total;
}em[100];
void menu(); //菜单界面
void input(); //录入
void save(); //保存文件
void display(); //显示职员信息
void del(); //删除
void search(); //查询
void search_num(); //按职员号查询
void search_name(); //按姓名查询
void modify(); //修改
void sta(); //统计
void start(); //开始界面
int main()//主函数
{
int n, button;
char a;
start();
getchar();
menu();
do
{
printf(" 功能选择(1--6):");
scanf("%d", &n);
if (n >= 1 && n <= 6)
{
button = 1;
break;
}
else
{
button = 0;
printf("您输入有误,请重新选择!");
}
} while (button == 0);
while (button == 1)
{
switch (n)
{
case 1: input(); break;
case 2: display(); break;
case 3: search(); break;
case 4:del(); break;
case 5:modify(); break;
case 6:sta(); break;
default:break;
}
getchar();
printf("\n");
printf("按Enter键继续\n");
getchar();
system("cls"); //清屏
menu(); //调用菜单函数
printf(" 功能选择(1--6):");
scanf("%d", &n);
printf("\n");
}
return 0;
}
void start() //开始界面
{
system("cls");
system("color E4");
printf("\n\n\n\n\n\n");
printf(" *************************************************************************************\n");
printf(" ****************************某某大学**********************************\n");
printf(" ****************************信工学院*******************************\n");
printf(" *****************************欢迎进入职员工资管理系统*****************************\n");
printf(" **************************************************************************************\n\n\n\n");
}
void menu() //菜单界面
{
printf("\n\t\t\t\t\t\t\t>>>>>菜单<<<<<\n\n\n\n");
printf("\t\t\t\t\t\t\t>>>>> 1 输入 \n\n");
printf("\t\t\t\t\t\t\t>>>>> 2 显示 \n\n");
printf("\t\t\t\t\t\t\t>>>>> 3 查找 \n\n");
printf("\t\t\t\t\t\t\t>>>>> 4 删除 \n\n");
printf("\t\t\t\t\t\t\t>>>>> 5 修改 \n\n");
printf("\t\t\t\t\t\t\t>>>>> 6 统计 \n\n");
printf("\n\n\n\t\t\t 请先输入数据 \n\n\n");
}
void input() //录入
{
int i, m;
system("cls");
printf("职员人数(1--100):\n");
scanf("%d", &m);
for (i = 0; i < m; i++)
{
printf("请输入职员号: ");
scanf("%d", &em[i].num);
printf("请输入姓名: ");
scanf("%s", &em[i].name);
getchar();
printf("请输入基本工资: ");
scanf("%d", &em[i].jbgz);
printf("请输入职务工资: ");
scanf("%d", &em[i].zwgz);
printf("请输入津贴: ");
scanf("%d", &em[i].jt);
printf("请输入医疗保险: ");
scanf("%d", &em[i].yb);
printf("请输入公积金: ");
scanf("%d", &em[i].gjj);
em[i].total = ((em[i].jbgz) + (em[i].zwgz) + (em[i].jt) - (em[i].yb) - (em[i].gjj));//计算总工资
printf("\n");
}
printf("\n创建完毕!\n");
save(m);//保存职员人数m
}
void save(int m) //保存文件
{
int i;
FILE* fp; //声明fp是指针,用来指向FILE类型的对象
if ((fp = fopen("clerk.txt", "wb")) == NULL) //打开职员列表文件为空
{
printf("打开失败\n");
exit(0);
}
for (i = 0; i < m; i++) //将内存中职员的信息输出到磁盘文件中去
if (fwrite(&em[i], sizeof(struct clerk), 1, fp) != 1)//写入数据块
printf("文件读写错误\n");
fclose(fp);//关闭文件
}
int load()
{
FILE* fp;
int i = 0;
if ((fp = fopen("clerk.txt", "rb")) == NULL)
{
printf("cannot open file\n");
exit(0);
}
else
{
do
{
fread(&em[i], sizeof(struct clerk), 1, fp); //读取
i++;
} while (feof(fp) == 0); //检测文件结束符
}
fclose(fp);
return(i - 1);//返回人数
}
void display() //显示职员信息
{
int i, sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0;
int m = load();
system("cls");
printf("职员号 姓名 基本工资 职务工资 津贴 医疗保险 公积金 总工资 \n");
for (i = 0; i < m; i++) //m为输入部分的职员人数
{
printf("\n %-6d%-6s %-8d %-8d %-8d %-8d %-8d %-8d ", em[i].num, em[i].name, em[i].jbgz, em[i].zwgz, em[i].jt, em[i].yb, em[i].gjj, em[i].total);
sum0 += em[i].jbgz;
sum1 += em[i].zwgz;
sum2 += em[i].jt;
sum3 += em[i].yb;
sum4 += em[i].gjj;
sum5 += em[i].total;
}
printf("\n\n职员平均工资为: %-8d %-8d %-8d %-8d %-8d %-8d\n", sum0 / m, sum1 / m, sum2 / m, sum3 / m, sum4 / m, sum5 / m);
}
void del() //删除
{
int m = load();
int i, j, n, t, button;
char name[20];
printf("\n 原来的职员信息:\n");
display(); //显示删除前的员工信息
printf("\n");
printf("按姓名删除:\n");
scanf("%s", name);
for (button = 1, i = 0; button && i < m; i++)//主函数中确定button==1时各函数才可以被调用
{
if (strcmp(em[i].name, name) == 0)//按员工姓名查找到某员工 并调出其资料
{
printf("\n此人原始记录为:\n");//显示选定员工的信息
printf("职员号 姓名 基本工资 职务工资 津贴 医疗保险 公积金 总工资 \n");
printf("\n %-6d%-6s %-8d %-8d %-8d %-8d %-8d %-8d ", em[i].num, em[i].name, em[i].jbgz, em[i].zwgz, em[i].jt, em[i].yb, em[i].gjj, em[i].total);
printf("\n确定删除 请按1,不删除请按0\n");
scanf("%d", &n);
if (n == 1)
{
for (j = i; j < m - 1; j++)//从第i项开始 将后一项的各成员的值赋给前一项各对应的成员 完成对第i项的删除
{
strcpy(em[j].name, em[j + 1].name);
em[j].num = em[j + 1].num;
em[j].jbgz = em[j + 1].jbgz;
em[j].zwgz = em[j + 1].zwgz;
em[j].jt = em[j + 1].jt;
em[j].yb = em[j + 1].yb;
em[j].gjj = em[j + 1].gjj;
em[j].total = em[j + 1].total;
}
button = 0;
}
}
}
if (!button)//button==0表明删除已完成
m = m - 1;//总员工数减少一人
else
printf("\n查无此人!\n");
printf("\n 删除后的所有职员信息:\n");
save(m); //保存删除后的职员信息
display(); //显示删除后的职员信息
printf("\n继续删除请按1,不再删除请按0\n");
scanf("%d", &t);
switch (t)
{
case 1:del(); break;
case 0:break;
default:break;
}
}
void search()//查询
{
int t, button;
system("cls");
do
{
printf("\n按1 按工号查询\n按2 按姓名查询\n按3 回主菜单\n");
scanf("%d", &t);
if (t >= 1 && t <= 3)
{
button = 1;
break;
}
else
{
button = 0;
printf("输入错误");
}
} while (button == 1);
switch (t)//选择查询方式
{
case 1:printf("按工号查询\n"); search_num(); break;
case 2:printf("按姓名查询\n"); search_name(); break;
case 3:break;
default:break;
}
}
void search_num()//按职员号查询
{
int a;
int i, t;
int m = load();
printf("请输入要查找的职员号:\n");
scanf("%d", &a);
for (i = 0; i < m; i++)
if (a == em[i].num)
{
printf("职员号 姓名 基本工资 职务工资 津贴 医疗保险 公积金 总工资 \n");
printf("\n %-6d%-6s %-8d %-8d %-8d %-8d %-8d %-8d ", em[i].num, em[i].name, em[i].jbgz, em[i].zwgz, em[i].jt, em[i].yb, em[i].gjj, em[i].total);
break;
}
if (i == m)
printf("\n对不起,查无此人\n");
printf("\n");
printf("返回查询函数请按1,继续查询职员号请按2\n");
scanf("%d", &t);
switch (t)
{
case 1:search(); break;
case 2:search_num(); break;
default:break;
}
}
void search_name()//按姓名查询
{
char name[30];
int i, t;
int m = load();
printf("请输入姓名:\n");
scanf("%s", name);
for (i = 0; i < m; i++)
if (strcmp(em[i].name, name) == 0)
{
printf("\n已找到,其记录为:\n");
printf("职员号 姓名 基本工资 职务工资 津贴 医疗保险 公积金 总工资 \n");
printf("\n %-6d%-6s %-8d %-8d %-8d %-8d %-8d %-8d ", em[i].num, em[i].name, em[i].jbgz, em[i].zwgz, em[i].jt, em[i].yb, em[i].gjj, em[i].total);
}
if (i == m)
printf("\n\n");
printf("\n");
printf("返回查询菜单请按1,继续查询姓名请按2\n");
scanf("%d", &t);
switch (t)
{
case 1:search(); break;
case 2:search_name(); break;
default:break;
}
}
void modify() //修改
{
int num;
char name[20];
int jbgz;
int zwgz;
int jt;
int yb;
int gjj;
int b, c, i, n, t, button;
int m = load();
system("cls");
printf("\n 原来的职员信息:\n");
display();
printf("\n");
printf("请输入要修改的职员的姓名:\n");
scanf("%s", name);
for (button = 1, i = 0; button && i < m; i++)
{
if (strcmp(em[i].name, name) == 0)
{
printf("\n此人原始记录为:\n");
printf("职员号 姓名 基本工资 职务工资 津贴 医疗保险 公积金 总工资 \n");
printf("\n %-6d%-6s %-8d %-8d %-8d %-8d %-8d %-8d ", em[i].num, em[i].name, em[i].jbgz, em[i].zwgz, em[i].jt, em[i].yb, em[i].gjj, em[i].total);
printf("\n确定 按1 ; 不修改请按0\n");
scanf("%d", &n);
if (n == 1)
{
printf("\n需要进行修改的选项\n 1.职员号 2.姓名 3.基本工资 4.职务工资 5.津贴 6.医疗保险 7.公积金 8.返回上层\n");
printf("请选择序号1-8:\n");
scanf("%d", &c);
if (c > 8 || c < 1)
printf("\n选择错误,请重新选择!\n");
}
button = 0;
}
}
if (button == 1)
printf("\n查无此人\n");
do
{
switch (c) //因为当找到第i个职员时,for语句后i自加了1,所以下面的应该把改后的信息赋值给第i-1个人
{
case 1:printf("职员号改为: ");
scanf("%d", &num);
em[i - 1].num = num;
break;
case 2:printf("姓名改为: ");
scanf("%s", name);
strcpy(em[i - 1].name, name);
break;
case 3:printf("基本工资改为: ");
getchar();
scanf("%d", &jbgz);
em[i - 1].jbgz = jbgz;
em[i - 1].total = (em[i - 1].jbgz + em[i - 1].zwgz + em[i - 1].jt - em[i - 1].yb - em[i - 1].gjj);
break;
case 4:printf("职务工资改为: ");
scanf("%d", &zwgz);
em[i - 1].zwgz = zwgz;
em[i - 1].total = (em[i - 1].jbgz + em[i - 1].zwgz + em[i - 1].jt - em[i - 1].yb - em[i - 1].gjj);
break;
case 5:printf("津贴改为: ");
scanf("%d", &jt);
em[i - 1].jt = jt;
em[i - 1].total = (em[i - 1].jbgz + em[i - 1].zwgz + em[i - 1].jt - em[i - 1].yb - em[i - 1].gjj);
break;
case 6:printf("医疗保险改为: ");
scanf("%d", &yb);
em[i - 1].yb = yb;
em[i - 1].total = (em[i - 1].jbgz + em[i - 1].zwgz + em[i - 1].jt - em[i - 1].yb - em[i - 1].gjj);
break;
case 7:printf("公积金改为: ");
scanf("%d", &gjj);
em[i - 1].gjj = gjj;
em[i - 1].total = (em[i - 1].jbgz + em[i - 1].zwgz + em[i - 1].jt - em[i - 1].yb - em[i - 1].gjj);
break;
case 8:modify();
break;
}
printf("\n");
printf("\n\n 确定修改 请按1 ; 重新修改 请按2: \n");
scanf("%d", &b);
} while (b == 2);
printf("\n修改后的所有职员信息:\n");
printf("\n");
save(m);
display();
printf("\n按1 继续修改 ,不再修改请按0\n");
scanf("%d", &t);
switch (t)
{
case 1:modify(); break;
case 0:break;
default:break;
}
}
void sta()//统计
{
int i;
int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0;
int a = 0, b = 0, c = 0;
int m = load();
system("cls");
for (i = 0; i < m; i++) //为输入部分的职员人数
{
sum0 += em[i].jbgz;
sum1 += em[i].zwgz;
sum2 += em[i].jt;
sum3 += em[i].yb;
sum4 += em[i].gjj;
sum5 += em[i].total;
if ((em[i].total) <= 2000 && em[i].total >= 1000)
{
a++;
}
if (em[i].total > 2000 && em[i].total <= 3000)
{
b++;
}
if (em[i].total > 3000)
{
c++;
}
}
printf("\n\n工资总额为:%d\n", sum5);
printf("平均工资为:%d\n%d\n%d\n%d\n%d\n%d\n", sum0 / m, sum1 / m, sum2 / m, sum3 / m, sum4 / m, sum5 / m);
printf("\n基本工资、职务工资、津贴之和\n");
printf("在1000-2000圆的员工占总员工的%d%%\n", a * 100 / m);
printf("在2000-3000圆的员工占总员工的%d%%\n", b * 100 / m);
printf("在3000圆以上的员工占总员工的%d%%\n", c * 100 / m);
printf("\n\n按Enter键继续");
getchar();
menu();
}