欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言|小型工资管理系统/学生管理系统

程序员文章站 2024-03-13 12:40:21
...

C语言结课作业:编写一个小型工资管理系统,用来管理职工的个人基本信息及工资薪酬等数据。在技术要求方面仅仅是要求了使用结构体数据类型,但基于我们的学习进度,考察的应该是用数组来储存。

作业要求

  1. 每个职工的数据应包括:工号、姓名、性别、部门、基本工资、绩效工资、奖金、应发工资(应发工资=基本工资+绩效工资+奖金)。职工数据要求采用结构体数据类型。

  2. **菜单显示:**显示系统的一级功能菜单(数据输入、数据修改、数据处理、数据输出、退出)。

  3. 数据输入:至少输入10个职工的各项数据(应发工资由系统自动计算,不需要输入)。**录入的第一条记录用自已的真实姓名,部门为自己的真实班级。**并将有自己真实姓名、班级的输出结果截屏保存到大作业总结报告中。

  4. 数据修改:输入工号,修改指定工号的各项数据。输出修改完成后的全部职工数据。

  5. 数据处理:处理方式包括:排序、查询。可提供子菜单让用户选择。其中:

    1)排序:按工号排序,显示所有职工的全部数据。

    2)查询:按工号查询,显示指定工号的全部数据。

  6. 数据输出:输出全部职工的各项数据。

  7. 退出:退出整个工资管理系统。

整体框架

1.数据存储

我使用的是结构体数组来自建一个数据库,放在全局环境下,将数据库设为一个全局变量

//自建数据库
 struct staff {
 	
	int  id;
 	char name[20];
 	char sex[20];
 	char belong[20];
 	int  basic_pay;
	int  add_pay;
	int  reward_pay;
	int  all_pay;

 }data[999] = {
 	
	{44, "张三", "男", "技术部", 5000, 1000, 200, 6200 },
	
	{14, "李四", "男", "运维部", 4000, 1000, 200, 5200 },
	
	{56, "小红", "女", "网安部", 3000, 1000, 200, 4200 },
 		
 }; 

另外还需要定义一个全局的数据库长度

int lenth = 3;

之所以直接定义为一个常量,而不是用sizeof这种方式来计算数组长度,因为我发现结构体数组用这种方式来计算数组长度会是一个大坑!所以还不如手动添加常量

2.函数功能结构

(1)函数声明

//函数声明
int create();    //增
int del();  	//删
int edit();    //改

int process();     //处理 
int req();     //查
int line();     //排 

int showall(); //查询全部

(2)函数定义

//菜单系统 
int main(void){

	int order;

	while(1){
        
		printf("****************************\n");
		printf("主菜单:\n");
		printf("1.输入员工信息\n");
		printf("2.删除员工信息\n");
		printf("3.修改员工信息\n");
		printf("4.处理员工信息\n");
		printf("5.显示所有员工信息\n"); 
		printf("6.退出\n");
		printf("****************************\n");
		printf("---请输入菜单项:---\n");

		
		scanf("%d",&order); 
		
		if(order==6){		
			
			system("cls");
			return 0;		
		}
		
		switch(order){
				
			case 1: 	create();break;
			case 2: 	del();break;	
			case 3: 	edit();break;	
			case 4: 	process();break;	
			case 5: 	showall(); break;
			default:    printf("\n404 NOT FOUND!"); getchar(); getchar(); system("cls");	
			
			}	
}


}


//增添信息
int create() {}

//删除信息 
int del(){}

//修改信息
int edit(){}

//处理信息
int process(){}

//员工信息排序输出 
int line(){}

//查询员工信息 
int req(){}

//查询全部数据 
int showall(){}

函数结构如下

C语言|小型工资管理系统/学生管理系统

这些函数都会对全局中的数据库进行操作。

菜单系统

main函数这里,就构建整体的函数调用框架,即本管理系统的菜单系统

//菜单系统 
int main(void){
   	
   int order;

	while(1){

		
		printf("****************************\n");
		printf("主菜单:\n");
		printf("1.输入员工信息\n");
		printf("2.删除员工信息\n");
		printf("3.修改员工信息\n");
		printf("4.处理员工信息\n");
		printf("5.显示所有员工信息\n"); 
		printf("6.退出\n");
		printf("****************************\n");
		printf("---请输入菜单项:---\n");

		
		scanf("%d",&order); 
		
		if(order==6){		
			
			system("cls");
			return 0;		
		}
		
		switch(order){
				
			case 1: 	create();break;
			case 2: 	del();break;	
			case 3: 	edit();break;	
			case 4: 	process();break;	
			case 5: 	showall(); break;
			default:    printf("\n404 NOT FOUND!"); getchar(); getchar(); system("cls");	
			
			}	
}

}

菜单系统常用switch语句来调用各个函数,另外为了整个管理系统的输出整洁一点,我还用了

“stdlib.h”库中的清屏函数system(“cls”)

增添员工信息

增添员工信息的基本设计思路:将新的信息填入到下一个数组空的位置。

int create() {
	
	int i;
	i = lenth;
	
	printf("\n");
	
	printf("新增员工工号:");
	scanf("%d", &data[i].id); 
	printf("\n");
	
	printf("新增员工姓名:");
	scanf("%s", &data[i].name); 
	printf("\n");

	printf("新增员工性别:");
	scanf("%s", &data[i].sex); 
	printf("\n");	
	
	printf("新增员工所属部门:");
	scanf("%s", &data[i].belong);
	printf("\n");	 
	
	printf("新增员工基本工资:");
	scanf("%d", &data[i].basic_pay); 
	printf("\n");	
	
	printf("新增员工绩效工资:");
	scanf("%d", &data[i].add_pay); 
	printf("\n");		
	
	printf("新增员工奖金:");
	scanf("%d", &data[i].reward_pay); 
	printf("\n");
	
	data[i].all_pay = data[i].basic_pay + data[i].add_pay + data[i].reward_pay;
	
	printf("创建成功!\n");	
	lenth++;
	getchar();
	getchar();
	system("cls");	
		
} 

用在全局定义的lenth(突然发现自己记错了长度的英语单词2333)来确定新数据的填写地址,创建成功后要注意用lenth++,拓展数据的长度。

删除员工信息

删除员工信息的基本设计思路是:通过遍历所有的数据查询到指定的员工工号,然后将后面的数据依次向上填补被“删除”的空白

//删除信息 
int del(){
	
	int i = lenth;
	int num;
	
	printf("\n请输入删除员工工号:");
	scanf("%d", &num);  
	
	for(int j=0; j<=i+1; j++){
		
		if(num==data[j].id){
			for( ;j<=i-j; j++){
				
				data[j] = data[j+1];
			}
			
			lenth--;
			printf("\n删除成功!\n"); 
			break;
		}
		
		if(j==i+1){
			
			printf("\n查无此人!\n");
			break;
		}
		
		
		
	}
	
	getchar();
	getchar();
	system("cls");
	
}

在遍历中用到了两个if语句,if(num==data[j].id)来寻找符合条件的员工号,而if(j==i+1)则是遍历所有的数据后未找到匹配条件。

说是删除实践上只是删除的数组元素的地位(下标)和财产(数据)被下一个数组元素给继承了,而下一个的数据元素的下标和数据又被下下个数据元素继承,以此类推。这里同样要注意用lenth--缩短数据长度。

修改员工信息

修改员工信息的思路和删除员工信息的思路相差无几:都需要查询定位对应的员工信息,不同的是定位后,这个还要修改员工的信息

//修改信息
int edit(){
	
	int i = lenth;
	int num;
	
	printf("\n请输入需要修改的员工工号:");
	scanf("%d", &num);  
	printf("\n");
	
	for(int j=0; j<=i+1; j++){
		
		if(num==data[j].id){
					
			printf("修改姓名:");
			scanf("%s", &data[j].name); 
			printf("\n");
		
			printf("修改性别:");
			scanf("%s", &data[j].sex); 
			printf("\n");	
			
			printf("修改所属部门:");
			scanf("%s", &data[j].belong);
			printf("\n");	 
			
			printf("修改基本工资:");
			scanf("%d", &data[j].basic_pay); 
			printf("\n");	
			
			printf("修改绩效工资:");
			scanf("%d", &data[j].add_pay); 
			printf("\n");		
			
			printf("修改奖金:");
			scanf("%d", &data[j].reward_pay); 
			printf("\n");
			
			data[j].all_pay = data[j].basic_pay + data[j].add_pay + data[j].reward_pay;
			
			printf("修改成功!\n");				
			showall(); 
			break;

		}
		
		if(j==i+1){
			
			printf("\n查无此人!\n");
			break;
		}
				
		
	}
	
	getchar();
	getchar();
	system("cls");
	
}

所谓修改,无非是重新赋值罢了。

处理信息

处理信息分成了排序信息和查询信息两部分,所有采用菜单系统同样的方式来设计

//处理信息
int process(){
	
	
	int order;
	printf("---------------------------------------------\n");
	printf("1.员工信息排序     2.员工信息查询\n"); 
	printf("---------------------------------------------\n");
	printf("请选择处理方式:");
	scanf("%d",&order); 
	printf("\n");
	
	switch(order){
		
		case 1: line(); break;
		case 2: req();  break;
		
	}	
	
} 
1.信息排序

说实话这个函数的设计是该项目唯一卡到我的地方,因为我一直把它理解成了“排序处理”,但我了解实际上的需求应该是“排序输出”,那问题就简单很多了,我的设计思路如下

将每个数组元素的地址看作是它们的住址,而员工工号信息就是它们的门牌号,把它们的门牌号记录下来,然后排列大小顺序,按顺序去拜访它们,期间它们的住处时是没有发生改变的。

//员工信息排序输出 
int line(){
	
	int i;
	int id_data[100];
	i = lenth;
	char* str[8] = {"工号", "姓名", "性别", "部门", "基本工资", "绩效工资", "奖金", "应发工资"}; 
	
		for(int j = 0; j<i; j++){
		
		id_data[j] = data[j].id;
		
	}
	
	
	qsort(id_data, i, sizeof(id_data[0]) , cmp);



	printf("\n排序成功!\n\n") ;


//数据表的字段输出	
	
	for(int n=0; n<8; n++){
		
		printf("%-12s" , str[n]);
		
	}
	
	
	printf("\n\n");


//数据排序输出	
	
	for(int n1 = 0; n1<i; n1++){
		
		for(int n2 = 0; n2<i; n2++ ){
			
			if(id_data[n1] == data[n2].id){
				
				printf(" %-10d",    data[n2].id); 
		
				printf(" %-10s",    data[n2].name); 
			
				printf("   %-10s",  data[n2].sex); 
				
				printf("%-10s",     data[n2].belong); 
				
				printf("    %-10d", data[n2].basic_pay); 
				
				printf("  %-10d",   data[n2].add_pay); 	
				
				printf("  %-10d",   data[n2].reward_pay); 
				
				printf("  %-10d",   data[n2].all_pay ); 
				
				printf("\n\n");
				
			}
						
			
		}
		
		
	} 
	
 	getchar();
 	getchar();
	system("cls");	
	
	
}

依据代码,我的思路对应关系如下

  • 住址 ==> 数组元素下标,即data数组的下标
  • 门牌号 ==> data[j].id
  • 记录门牌号 ==> 用了另一个数组:id_data[j] 来储存
  • 排列门牌号大小 ==> 将id_data[j] 存储的门牌号排序,这里使用了C语言内置的排序函数:qsort()
  • 依次拜访 ==> 两层循环,外层循环:for(int n1 = 0; n1<i; n1++)循环名单上排列好的门牌号,内层循环:for(int n2 = 0; n2<i; n2++ ),一个个去找符合名单上第一位的门牌号,然后输出。

另外注意,作为一个大学生的作业,使用内置的qsort()排序函数应该是非法的(狗头),应该使用冒泡排序或选择排序!

qsort()函数使用参考文章:点击查看

好,我摊牌啦,我就是想偷一下懒……

2.查询员工信息

查询的思路和删除信息,修改信息相似,没什么特别的地方

//查询员工信息 
int req(){
	
	int i = lenth;
	int num;
	char* str[8] = {"工号", "姓名", "性别", "部门", "基本工资", "绩效工资", "奖金", "应发工资"}; 
	
	printf("\n请输入需要查询员工工号:");
	scanf("%d", &num);  
	printf("\n\n");
	
	for(int n=0; n<8; n++){
		
		printf("%-12s" , str[n]);
		
	}
	
	printf("\n\n");
	
	for(int j=0; j<=i+1; j++){
		
		if(num==data[j].id){
	
			printf(" %-10d",    data[j].id); 
		
			printf(" %-10s",    data[j].name); 
			
			printf("   %-10s",  data[j].sex); 
				
			printf("%-10s",     data[j].belong); 
				
			printf("    %-10d", data[j].basic_pay); 
				
			printf("  %-10d",   data[j].add_pay); 	
				
			printf("  %-10d",   data[j].reward_pay); 
				
			printf("  %-10d",   data[j].all_pay ); 
				
			printf("\n\n");
			
			printf("\n查询成功!\n\n");
			break;

		}
		
		if(j==i+1){
			
			printf(" 无\n");
			printf("\n查无此人!\n");
			
			break;
		}
		
	
	
} 


	getchar();
	getchar();
	system("cls");	

}

这里输出数据表的表头,用了数组来存储字符串,要注意加*号: char* str[8]

查询全部数据

无脑遍历输出即可,就是输出格式上要有调整,一般可以用printf("%-9d")占9个空格,左对齐的方式来调整输出格式,输出那里我也是为了美观才一个个去加空格调整格式,就不要吐槽我代码格式不整洁了。

//查询全部数据 
int showall(){
	
	int i;
    char* str[8] = {"工号", "姓名", "性别", "部门", "基本工资", "绩效工资", "奖金", "应发工资"}; 
	i = lenth - 1;
	 
	data[i].all_pay = 	data[i].basic_pay + data[i].add_pay + data[i].reward_pay;
	printf("\n");
	printf("查询成功!\n\n");

	
	for(int n=0; n<8; n++){
		
		printf("%-12s" , str[n]);
		
	}
	
	printf("\n\n");
	
	for(int j=0; j<=i; j++){
			
		printf(" %-10d",    data[j].id); 
		
		printf(" %-10s",    data[j].name); 
	
		printf("   %-10s",  data[j].sex); 
		
		printf("%-10s",     data[j].belong); 
		
		printf("    %-10d", data[j].basic_pay); 
		
		printf("  %-10d",   data[j].add_pay); 	
		
		printf("  %-10d",   data[j].reward_pay); 
		
		printf("  %-10d",   data[j].all_pay ); 
		
		printf("\n\n");
		
	}

 	getchar();
 	getchar();
	system("cls");	
	
}

实现效果:

C语言|小型工资管理系统/学生管理系统

看这整整齐齐的亚子,爱了爱了!

总结

整体来说,这个结课作业并不难,只用用课堂上的知识完全是可以完成了(我一个下午不到就写好)。

但事实上无论用哪门语言,增删改查的实现永远是入门重要的第一课,本项目和之前的python学生管理系统,都仅仅是在内部实现的数据增删改查,一旦退出程序,缓存就被清除了,无法保留。所以我们还应考虑——如何把这样的操作在文本中实现,如何连接mysql数据库实现同样增删改查的操作。

所以呀,流水的编程语言,铁打的管理系统,入门从管理系统开始!

相关标签: C语言 c语言