一、目的
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;
} 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语言编程的基础知识,并学习了一些新的编程技能,对我的编程能力提高起到了积极的作用。