程序设计综合实习(C语言):考勤管理系统_c语言创建一个职工考勤管理系统-程序员宅基地

技术标签: 算法  c语言  程序设计综合实习  链表  

一、目的

1.调动创新能力的培养

二、实习环境

Visual Studio 2022

三、实习内容与步骤

问题描述:

每个员工信息包括工号、姓名、年龄、性别、部门等;

功能要求:

(1)能够增加、删除、修改员工信息。

(2)提示开始考勤后,以录入一个员工号后敲回车表明该员工考勤一次;

(3)输出功能:能够输出员工信息;

(4)查找功能:能够查询员工信息和考勤信息;

(5)统计功能:能够对考勤进行统计。

(6)要求能通过文件保存信息,程序支持信息导入和保存 

四、程序流程图、算法及运行结果

流程图

算法描述

1.定义员工信息的结构体,包括工号、姓名、年龄、性别、部门、考勤次数和出勤次数。同时定义链表的头指针和尾指针。
2.实现菜单功能,包括增加员工信息、删除员工信息、修改员工信息、开始考勤、输出员工信息、查找员工信息和考勤信息、统计员工出勤率和退出系统。
3.实现增加员工信息的功能,包括输入员工的工号、姓名、年龄、性别、部门等信息,并将其插入到链表的尾部。同时需要保存新增的员工信息到文件中。
4.实现删除员工信息的功能,先输入需要删除的员工工号,然后遍历链表,找到对应的员工信息并删除。同时需要保存删除后的员工信息到文件中。
5.实现修改员工信息的功能,先输入需要修改的员工工号,然后选择需要修改的信息,最后将修改后的信息保存。同时需要保存修改后的员工信息到文件中。
6.实现输出员工信息的功能,遍历链表,将所有员工信息输出。
7.实现查找员工信息和考勤信息的功能,可以根据员工的工号或姓名进行查找。找到对应的员工信息后,将其输出。
8.实现开始考勤的功能,输入员工工号和考勤状态,对应员工的考勤次数加1,出勤次数加1或不变。输入0停止考勤,同时需要保存考勤后的员工信息到文件中。
9.实现统计员工出勤率的功能,遍历链表,计算每个员工的出勤率,并输出。
10.实现导入和保存员工信息的功能,通过文件操作实现。在程序启动时,从文件中读取员工信息并存入链表中;在程序结束时,将链表中的员工信息保存到文件中。

程序代码: 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct worker {
	int num;//工号
	char name[100];//姓名
	int age;//年龄
	char sex[100];//性别
	char department[100];//部门
	struct worker* next;
	int attendence;//考勤次数
	int chuqin;//出勤次数
};
int num;//工号
char name[100];//姓名
int age;//年龄
char sex[100];//性别
char department[100];//部门
int cnt;
int op;
int flag;
int st;
int attendence;//考勤次数
int chuqin;//出勤次数
FILE* fp;
struct worker* p, * q, * head = NULL, * tail = NULL;
void menu();//菜单
void add();//增加信息
void delete1();//删除信息
void modify();//修改信息
void output();//输出信息
void search();//查找员工信息和考勤信息
void attendstart();//开始考勤
void attendstatistics();//统计考勤
void read_in_information();//导入信息
void save_information();//保存信息
int main()
{
	read_in_information();//导入信息
	st = 1;
	while (1) {
		menu();//菜单
		scanf("%d", &op);
		if (op >= 1 && op <= 8) {
			switch (op) {
			case 1:add(); break;
			case 2:delete1(); break;
			case 3:modify(); break;
			case 4:attendstart(); break;
			case 5:output(); break;
			case 6:search(); break;
			case 7:attendstatistics(); break;
			case 8:st = 0; break;
			}
		}
		else printf("输入无效\n");
		if (st == 0) break;
	}
	return 0;
}
//菜单
void menu() {
	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("***********************************************************************************************************************\n");
	printf("请输入代码选择(1-8):");
}
//增加员工信息
void add() {
	printf("请输入需要增加的员工信息(工号,姓名,年龄,性别,部门):\n");
	scanf("%d%s%d%s%s", &num, name, &age, sex, department);
		p = (struct worker*)malloc(sizeof(struct worker));
		if (p != NULL) {
			p->num = num;
			strcpy(p->name, name);
			p->age = age;
			strcpy(p->sex, sex);
			strcpy(p->department, department);
			p->attendence = 0;
			p->chuqin = 0;
			p->next = NULL;
		}
		if (head == NULL) {
			head = p;
			tail = p;
		}
		else {
			tail->next = p;
			tail = p;
		}
	save_information();
}
//删除员工信息
void delete1() {
	printf("请输入需要删除的员工的工号:\n");
	scanf("%d", &num);
	p = head;
	q = head;
	cnt = 0;
	while (p != NULL) {
		if (p->num == num) break;
		q = p;
		cnt++;
		p = p->next;
	}
	if (p != NULL) {
        printf("删除成功!!!\n");
		if (cnt == 0) head = p->next;
		else q->next = p->next;
	}
	else printf("没有查到该员工工号!!!\n");
	save_information();
}
//修改员工信息
void modify() {
	p = head;
	printf("请输入需要修改的员工的工号:\n");
	scanf("%d", &num);
	while (p != NULL) {
		if (p->num == num) break;
		p = p->next;
	}
	printf("请输入需要修改的信息:\n");
	printf("按1:修改工号 "); printf("按2:修改姓名 "); printf("按3:修改年龄 ");
	printf("按4:修改性别 "); printf("按5:修改部门 "); printf("按6:停止修改 ");
	printf("\n请按键:");
	scanf("%d", &op);
	flag = 1;
	while (1) {
		if (op >= 1 && op <= 6) {
			switch (op)
			{
			case 1:printf("请输入工号:"); scanf("%d", &num); p->num = num; break;
			case 2:printf("请输入姓名:"); scanf("%s", name); strcpy(p->name, name); break;
			case 3:printf("请输入年龄:"); scanf("%d", &age); p->age = age; break;
			case 4:printf("请输入性别:"); scanf("%s", sex); strcpy(p->sex, sex); break;
			case 5:printf("请输入部门:"); scanf("%s", department); strcpy(p->department, department); break;
			case 6:flag = 0; break;
			}
		}
		else printf("按键无效,请重新输入:\n");
		if (flag == 0) break;
		printf("请输入需要修改的信息:\n");
		printf("按1:修改工号 "); printf("按2:修改姓名 "); printf("按3:修改年龄 ");
		printf("按4:修改性别 "); printf("按5:修改部门 "); printf("按6:停止修改 ");
		printf("\n请按键:");
		scanf("%d", &op);
	}
	save_information();
}
//输出员工信息
void output() {
	printf("输出所有员工信息:\n");
	printf("工号 姓名 年龄  性别     部门  考勤次数  出勤次数\n");
	p = head;
	while (p != NULL) {
		printf("%d%4s%5d   %-10s%2s%7d%9d\n", p->num, p->name, p->age, p->sex, p->department, p->attendence,p->chuqin);
		p = p->next;
	}
save_information();
}
//查找员工信息和考勤信息
void search() {
	flag = 1;
	while (1)
	{
		printf("请输入需要查找的员工工号或姓名\n按键1选择输入工号,按键2选择输入姓名,按键0选择停止输入:");
		scanf("%d", &op);
		if (op == 1 || op == 2 || op == 0) {
			switch (op)
			{
			case 0:flag = 0; break;
			case 1:
			{printf("请输入要查找的工号:");
			scanf("%d", &num);
			p = head;
			while (p != NULL) {
				if (p->num == num) break;
				p = p->next;
			}
			printf("该员工信息如下:\n");
			printf("工号 姓名 年龄  性别     部门  考勤次数  出勤次数\n");
			printf("%d%4s%5d   %-10s%2s%7d%9d\n", p->num, p->name, p->age, p->sex, p->department, p->attendence,p->chuqin);
			}
			break;
			case 2:
			{
				printf("请输入要查找的姓名:");
				scanf("%s", name);
				p = head;
				while (p != NULL) {
					if (strcmp(p->name, name) == 0) break;
					p = p->next;
				}
			}
			printf("该员工信息如下:\n");
			printf("工号 姓名 年龄  性别     部门  考勤次数  出勤次数\n");
			printf("%d%4s%5d   %-10s%2s%7d%9d\n", p->num, p->name, p->age, p->sex, p->department, p->attendence,p->chuqin);
			break;
			}
		}
		else {
			printf("输入无效,请重新输入\n");
			continue;
		}
		if (flag == 0) break;
	}
}
//开始考勤
void attendstart() {
	printf("开始考勤!!!\n");
	printf("请输入工号(输入0停止考勤),考勤状态(0表示缺勤,1表示出勤):");
	scanf("%d%d", &num,&chuqin);
	while (1) {
		if (num == 0) return;
		p = head;
		while (p != NULL) {
			if (p->num == num) break;
			p = p->next;
		}
		if (p == NULL) printf("没有找到该员工!!!\n");
		else {
			printf("%s考勤成功\n", p->name);
			p->attendence++;
		}
		if (chuqin == 1) p->chuqin++;
		printf("请输入工号(输入0停止考勤),考勤状态(0表示缺勤,1表示出勤):");
		scanf("%d%d", &num, &chuqin);
	}
	save_information();
}
//统计员工出勤率
void attendstatistics() {
	p = head;
	while (p != NULL) {
		if(p->attendence!=0) printf("工号:%d 姓名:%s 出勤率:%.0f%%\n",p->num,p->name,(double)(p->chuqin)/p->attendence*100);
		else printf("工号:%d 姓名:%s 出勤率:0%%\n", p->num, p->name);
		p = p->next;
	}
}
//导入信息
void read_in_information() {
	if ((fp = fopen("D:\\data.txt", "r")) == NULL) {
		printf("file open error!\n");
		exit(0);
	}
	while (!feof(fp)) {
		p = (struct worker*)malloc(sizeof(struct worker));
		if (p != NULL) {
			fscanf(fp, "%d%s%d%s%s%d%d", &p->num, p->name, &p->age, p->sex, p->department, &p->attendence,&p->chuqin);
			p->next = NULL;
		}
		if (head == NULL) {
			head = p;
			tail= p;
		}
		else {
			tail->next = p;
			tail = p;
		}
	}
	if (fclose(fp)) {
		printf("can not close the file!\n");
		exit(0);
	}
}
//保存信息
void save_information() {
	if ((fp = fopen("D:\\data.txt", "w")) == NULL) {
		printf("file open error!\n");
		exit(0);
	}
	p = head;
	while (p != NULL) {
		if (p->next != NULL) fprintf(fp, "%d %s %d %s %s %d %d\n", p->num, p->name, p->age, p->sex, p->department, p->attendence, p->chuqin);
		else fprintf(fp, "%d %s %d %s %s %d %d", p->num, p->name, p->age, p->sex, p->department, p->attendence, p->chuqin);
		p = p->next;
	}
	if (fclose(fp)) {
		printf("can not close the file!\n");
		exit(0);
	}
}

运行结果

 

 

  

五、知识点、难点及解决办法。

知识点

1.结构体:定义了一个名为worker的结构体,包含员工的基本信息(工号、姓名、年龄、性别、部门)、考勤次数和出勤次数。在增加、删除、修改、查询、统计 等功能中,都用到了worker结构体。
2.文件操作:通过read_in_information函数从文件中读取已有的员工信息并导入到程序中,在save_information函数中将程序中的员工信息保存到文件中。文件路径为D\\:data.txt,
3.链表:通过定义指针p、q、head和tail以链表的形式存储和管理员工信息,每个节点即为一个worker结构体。在增加、删除和输出员工信息等操作中,需要遍历整 个链表。
4.菜单设计:通过menu函数设计了一个菜单,让用户选择需要进行的操作。
5.操作实现:实现了增加员工信息、删除员工信息、修改员工信息、开始考勤、输出员工信息、查找员工信息和考勤信息、统计员工出勤率等基本操作。其中开始考勤和统计员工出勤率是根据考勤次数和出勤次数来计算的。

难点及解决办法

该程序的难点在于需要涉及到链表的操作和文件的读写,需要处理好相关的指针、数据结构和文件流等内容。
对于链表的操作,在增加、删除和修改等功能中,需要注意指针的移动、重新连接等细节。同时,链表操作需要考虑多种情况,如空链表、只有一个节点的链表、需要删除头节点等情况。对于文件的读写,需要注意文件流的打开和关闭、读取和写入的格式、文件路径的设置等问题。在程序中,相关操作需要判断文件是否成功打开或关闭,并检查文件读写操作是否成功。
解决办法可以采用编写函数来处理错表操作和文件读写,将不同功能的代码块分离开来,方便处理。在实现时,可以先使用伪代码或流程图来规划程序结构,再逐步实现各个模块的功能,最后进行测试和调试,确保程序正确运行。

六、编程小结或体会。

该程序是一个考勤管理系统,实现了员工信息的增加、删除、修改、输出、查找和考勤统计等功能。其中员工信息以链表形式存储,考勤信息则直接在员工结构体中记录。程序还实现了数据的持久化,即将员工信息保存在文件中,并在程序启动时从文件中读取已有的员工信息。通过编写该程序,我学会了如何使用链表来存储和管理数据,以及如何进行文件的读写操作。同时,我也意识到了数据的特久化对于一些需要长期保存的应用程序非常重要,可以保证数据不因程序的退出而丢失。此外,在编写程序过程中,我也加强了对于函数的使用和调用的理解,通过将各种功能拆分成不同的函数实现,使得程序结构更加清晰,易于维护和扩展。总之,通过编写这个考勤管理系统,我进一步巩固了C语言编程的基础知识,并学习了一些新的编程技能,对我的编程能力提高起到了积极的作用。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_74087709/article/details/130997287

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签