成 都工业学院 通信工程系微电子技术专周报告 姓名: 蹇岚 班级: 1306161 学号: 11 导师: 王飞
一、 设计题目:职工工资管理小软件
二、 实习目的:
1、通过这次专题实习,可以巩固和加深对所学相关知识点的理解。
2、进一步熟悉基本的流程控制结构---实现分支的if ?else语句、switsh语句和实现循环的for、while?、do?while语句、break、continue等。
3、基本数据类型、数组、结构体、自定义类、函数的应用。
4、加强对模块化程序设计和面向对象程序设计的理解。
5、掌握C/C++语言程序设计的基本思想,了解简单的系统分析和设计方法。
三、 程序设计要求:
1、启动软件时,进行密码校验。若出错三次,则自动退出该系统。
2、实现简易的提示菜单界面(可以用中文或英文显示),刚运行时应显示版本信息(版本号、作者的班级、姓名、设计时间)。用所学的知识尽量实现良好的、美观的“人机界面”,便于软件的操作使用。(比如,在每次输入之前先输入“提示信息”;保存数据成功时输出相应提示;启动时输出“欢迎使用”;退出前输出“谢谢使用”,?..)
3、要求把所录入的数据以文件的形式,保存在硬盘中(文件中的数据应有一定的格式,以便于文件的读写访问)。
4、系统应包含以下基本功能:
(1) 登录功能:用户输入口令,如果与系统内保存的密码相一致,则登陆成功;否则重新输入口令,直至输入口令正确才可以登录系统。若出错三次,则自动退出该系统。
(2) 显示主菜单:用户登录成功,系统显示图形界面,显示系统功能的提示信息。
(3)职工信息输入:用户输入要添加的职工的职工号、姓名、年龄、性别、基本工资、岗位工资等信息,系统逐个保存职工信息。当用户输入学号为0时,输入结束。输入数据时,须验证数据的输入格式正确,保证职工号的唯一性。
(4)职工信息输出:将结构体数组中的职工信息输出到屏幕上。
(5)职工信息查询:
按职工号查询职工信息:用户输入要查询职工的职工号,系统查询该职工号在结构体数组中是否存在,存在则输出该职工的全部信息;否则,输出not found。
按职工姓名查询职工信息:用户输入要查询职工的职工姓名,系统查询该职工姓名在结构体数组中是否存在,存在则输出该职工的全部信息;否则,输出not found。
(6) 职工信息修改:修改职工的信息(职工号不能修改),并保存。
(7)工资排序:
对结构体数组中的所有职工按基本工资从高到低的顺序排序,用选择法来实现。(
对结构体数组中的所有职工按岗位工资从高到低的顺序排序,用冒泡法来实现。
对结构体数组中的所有职工按总工资从高到低的顺序排序,用插入法来实现。
(8)工资统计:分别统计总工资在2000以下,2000-3000 及3000以上的职工人数。
(9)导出数据:把结构体数组中的职工信息保存到磁盘文件里。
(10)导入数据:从外部文件中导出职工信息到结构体数组里。
(11)退出:结束程序运行。
四、 系统的实现方法:
1、 提示菜单的实现:最外层为一个“死循环”,先显示简易的提示菜单,等
待输入之后,通过一个switch开关语句进行菜单项的判别,再调用实现相应功能的函数。
(其中,应该有“退出系统”菜单项,用于退出“死循环”-)break;)。
2、录入的每一个职工的信息,可以通过一个职工结构体数组来存放.再存入到文件中。例如,可以定义结构体类型如下:
struct Employee
{
char Name[10];
unsigned int Id;
char Sex[3];
char Age;
float Basewage;
float Postwage;
float Totalwages;
};
struct Node
{
struct Employee data;
struct Node * pNext;
};
五、 实现步骤:
(1)总体分析设计(画出模块结构图和系统流程图,理清程序思路) (2)完成字符界面菜单 (3)结构体类型的定义 (4)主控函数main的编写 (5)新增记录、保存到文件 (6)从文件读出记录,显示到屏幕 (7)保存结果到文件 (8)查询记录
部分运行实例:
1、登陆界面:
2、欢迎页:
3、显示全部职工信息:
4、信息查询:
(姓名方式)
(职工号方式)
工资排序:(总工资降低)
岗位工资降低
。。。。。。。。。。。。。。。。等等;
实现的源代码是:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<string.h>
#include<malloc.h>
struct Employee
{
char Name[10];
unsigned int Id;
char Sex[3];
char Age;
float Basewage;
float Postwage;
float Totalwages;
};
struct Node
{
struct Employee data;
struct Node * pNext;
};
/*-----------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 函数声明
------------------------------------------------------------------------*/
void Login (void);
void menu (void);
void choose (char ch);
void Add_Info ();
void Op_Info ();
struct Node * create_list (void);
void traverse_list(struct Node *);
void Query_Info (void);
void Alter_Info ();
void save (struct Node *);
void Wage_Sorting ();
unsigned int length_list (struct Node * pHead);
void Wage_Statistics ();
void Writ_File ();
void Read_File ();
void Alter_Admin();
void Exit_System ();
int main (void)
{
char ch;
system ("color F3");
Login ();//登陆函数,要显示登陆成功,并清屏、(只有一个管理员,也只有一个密码,后续扩展可修改密码(在主菜单的10))
menu ();//如果登陆成功,打印主菜单
while (1)
{
scanf (" %d", &ch);
} } choose (ch);//选择函数 return 0;
/*----------------------------------登陆函数-----------------------------*/
void Login (void)
{
FILE * Logfp;//校验保存用户名和密码的文件(Login file.dat)指针变量 int i; int check; char user[20];//保存用户输入的用户名 char key[20];//保存用户输入的密码 char user1[20];//保存从校验文件(Login file.dat)中取出的用户名 char key1[20];//保存从校验文件(Login file.dat)中取出的密码 Logfp = fopen ("Login file.dat", "rb");//打开校验文件 if (Logfp == NULL)//如果文件打开失败的提示 { printf ("密码校验文件打开失败!强行退出\n"); exit(-1); } check = fread (user1, 20, 1, Logfp);//取出文件中的用户名给user1 if (check != 1)//如果取用户名值错误 { printf ("用户名校验出错!强行退出\n"); exit(-1); } check = fread (key1, 20, 1, Logfp);//取出文件中的密码给key1 fclose (Logfp); if (check != 1)//如果取用户名值错误 { printf ("密码校验出错!强行退出\n");
exit(-1); } for (i=0; i<3; i++) { printf("用户名:"); gets (user);//gets ();是以回车键结束读取的 putchar('\n'); printf("密码: "); gets (key); if (strcmp (user, user1) == 0 && strcmp (key, key1) == 0) { printf("登陆成功!请稍后");//完成后可以调用贪吃蛇的函数 Sleep (2000);//贪吃蛇本身可以作为延时,到时候取代这个 system ("cls");//清屏 return; } else
printf ("用户名或密码错误!你还有 %d 次机会,请重新输入\n", 2-i); }
printf ("密码已输入三次!登录失败,强行退出\n");
Sleep (500);//延时0.5秒
exit(-1);
}
/*-----------------------------打印主菜单----------------------------------*/
void menu (void)
{
printf (" 欢迎登陆职工信息管理系统\n");
printf ("【1】 输入职工信息 【2】全部职工信息\n"); printf ("【3】 查询职工信息 【4】修改职工信息\n"); printf ("【5】 工资排序信息 【6】工资统计信息\n"); printf ("【7】 导出职工信息 【8】导入职工信息\n"); printf ("【9】 管理员信息 【10】退出系统\n");
printf ("请输入以上数字,选择相应功能:");
}
/*-----------------------------功能选择函数-------------------------------*/
void choose (char ch)
{
switch (ch)
{
case 1 : Add_Info (); break;//添加职工成员的信息
case 2 : Op_Info (); break;//显示全部职工的信息
case 3 : Query_Info (); break;//查询职工的信息
case 4 : Alter_Info (); break;//修改职工的信息
case 5 : Wage_Sorting (); break;//按不同工资排序
case 6 : Wage_Statistics (); break;//不同工资阶段统计
case 7 : Writ_File (); break;//导出数据到磁盘文件
case 8 : Read_File (); break;//导入数据到结构体变量中
case 9 : Alter_Admin();break;//修改管理员的函数
case 10: Exit_System (); break;//退出登录函数
}
}
/*----------------------------信息添加函数--------------------------------*/
void Add_Info ()
{
char name[10];
unsigned int id;
char sex[3];
char age;
float basewage;
float postwage;//岗位工资
float totalwages;
long pAdress;
unsigned int len;
char check_read;
char check_write;
struct Employee val;
unsigned int i;
FILE * Infp;//员工信息文件(Iformation.dat)指针
Infp = fopen ("Information.dat", "rb");//读取其中的最大工号
if (Infp == NULL)//如果文件打开失败的提示
{
printf ("员工信息文件打开失败!强行退出\n");
exit(-1);
}
printf ("移动前指针的位置:%d\n", ftell(Infp));
fseek (Infp, -(long)(sizeof(struct Employee)), 2);//将文件指针移动到最后一个结构体数据的首字节//sizeof(struct Employee)的返回值是32
pAdress = ftell (Infp);//判断文件指针的位置
printf ("从最后向前移动一个结构体指针的位置:%ld\n", pAdress);
if (pAdress == -1L)//文件指针如果在负了表明没有数据
id = 0;
else
{
check_read = fread (&val, sizeof(struct Employee), 1, Infp);//读取一个结构体数据给 val
printf ("读取后文件指针的位置:%d\n", ftell (Infp));
if (check_read != 1)
{ } printf ("最后一位员工的ID获取失败!强行退出\n"); exit (-1); id = val.Id;//val中(即最后一个职工的信息)的工号提取出来 } fclose (Infp); printf ("请输入需要添加的员工人数:"); scanf ("%d", &len); Infp = fopen ("Information.dat", "ab"); for (i=0; i<len; i++) { printf ("请输入新增第%d个员工的信息:\n", i+1); getchar ();//吸收回车符号 printf ("姓名:"); gets (name); printf ("工号:%d\n", id+i+1); printf ("性别:"); gets (sex); printf ("年龄:"); scanf ("%d", &age); printf ("基本工资:"); scanf ("%f", &basewage); printf ("岗位工资:"); scanf ("%f", &postwage); totalwages = basewage + postwage; printf ("总工资:%0.1f\n", basewage+postwage); strcpy (val.Name, name); val.Id = id+i+1; strcpy(val.Sex, sex); val.Age = age; val.Basewage = basewage; val.Postwage = postwage; val.Totalwages = totalwages; check_write = fwrite (&val, sizeof(struct Employee), 1, Infp); printf("读取数量:%d", check_write); if (check_write == 1) printf ("这位员工的信息已保存\n"); else { printf ("这位员工的信息写入失败!强行退出\n"); exit (-1); } } fclose (Infp); printf ("所有新增员工的信息已保存!两秒后自动返回主菜单\n"); Sleep (2000);
system ("cls");
menu ();
}
void Op_Info (void)
{
struct Node * pHead = NULL;
pHead = create_list ();
traverse_list(pHead);
system ("pause");
system ("cls");
menu ();
}
/*------------------------------创建链表---------------------------------*/
struct Node * create_list (void)
{
int len;//保存文件中的结构体struct Employee的数量
int i;
struct Employee val;//保存文件中读取的该类型结构体的值
struct Node * pHead;//头指针//存放第一个结点的指针变量
pHead = (struct Node *)malloc(sizeof(struct Node));//动态分配一块能存放strcut Node 类型数据的空间,但这块空间不会存放数据,只会存放第一个节点的首地址,并把首地址保存在pHead指针变量
if(NULL == pHead)
{
printf ("链表头结点内存分配失败,程序终止!\n");
exit (-1);
}
struct Node * pTail;//尾节点指针变量
pTail = pHead;
pTail->pNext = NULL;
FILE * Infp = fopen ("Information.dat", "rb");
fseek (Infp, 0L, 2);//文件指针指向最后一字节
len = ftell (Infp)/sizeof (struct Employee);//统计出文件中的数据的个数
fseek (Infp, 0L, 0);//文件指针指向第一字节
//rewind ();
struct Node * pNew;
for (i=0; i<len; i++)//也可以通过是否在文件末尾判断是否继续循环,来继续生成新节点 {
pNew = (struct Node *)malloc(sizeof (struct Node));//新节点的空间申请,和其地址的返回
if (NULL == pNew)
{
printf ("链表创建节点时内存分配失败,终止程序!\n");
exit (-1);
}
fread (&val, sizeof(struct Employee), 1, Infp);//从文件指针位置开始 向后读取struct Employee类型大小的字节数的数据 给 val(保存这个结构体内的内容)
pNew->data = val;//将取出的数据赋给新节点的数据域
pTail->pNext = pNew;//现在新节点放在了尾节点的后面,所以之前尾节点的地址域要保存新节点的地址
pNew->pNext = NULL;//现在尾节点的地址必须为空,表示链表的结束
pTail = pNew;//新节点完全成为尾结点,之前的尾节点不再是最后的节点 }
fclose (Infp);
return pHead;
}
/*-----------------------按照链表顺序对员工信息的输出--------------------*/
void traverse_list(struct Node * pHead)
{
struct Node * p;
p = pHead->pNext;
printf ("姓名\t工号\t性别\t年龄\t基本工资\t岗位工资\t总工资\n");
while (NULL != p)
{
printf ("%s\t%d\t%s\t%d\t%f\t%f\t%f\n", (p->data).Name, (p->data).Id, (p->data).Sex, (p->data).Age, (p->data).Basewage, (p->data).Postwage, (p->data).Totalwages);
p = p->pNext;
}
}
/*----------------------------职工信息查询函数---------------------------*/
void Query_Info ()
{
char ch;
char name[10];//存取用户输入的姓名
char temp_name[10];//临时存取链表中所保存的结构体的Name成员的值
unsigned int id;//存取用户输入的工号
unsigned int temp_id;//临时存取链表中所保存的结构体的Name成员的值
char check_name;//存取比较函数的返回值
char c;//是否重复查询程序,用于人机交互的判断
struct Node * pHead;//保存struct Node 类型数据的地址
struct Node * p;
struct Employee temp_Employee;
pHead = create_list ();//pHead是指向头结点的,pHead叫头指针
p = pHead->pNext;//现在的p是指向头节点了 do { while (1) { printf ("请选择查询方式:1、根据姓名 2、根据职工号\n"); scanf ("%d", &ch); if (ch == 1) {
printf ("请输入职工的姓名:\t");
getchar ();
gets (name);
while(p != NULL)
{
temp_Employee = p->data;
strcpy(temp_name, temp_Employee.Name);
check_name = strcmp (name, temp_name);
if (check_name == 0)
break; //如果跳出了循环可能是找到这个职工,那么此时temp_Employee就保存了这个职工的信息,将他打印即可;也可能是找到最后没有找到
p = p->pNext;
}
break;
}
else if (ch == 2)
{
printf ("请输入职工号:\t"); scanf ("%d", &id); while(p != NULL) { temp_Employee = p->data; temp_id = temp_Employee.Id; if (temp_id == id) break; p = p->pNext; } break; } else { printf ("输入不合法,请重试!\n"); continue; }
}
if (p != NULL)
{
printf ("姓名\t工号\t性别\t年龄\t基本工资\t岗位工资\t总工资\n"); printf ("%s\t%d\t%s\t%d\t%f\t%f\t%f\n", temp_Employee.Name,
temp_Employee.Id, temp_Employee.Sex, temp_Employee.Age, temp_Employee.Basewage, temp_Employee.Postwage, temp_Employee.Totalwages);
}
else
} printf ("数据库没有你要查询的人,请检查后重试!\n"); printf ("是否要继续查询!继续请按Y,退出请按N"); scanf (" %c", &c); }while ('y' == c || 'Y' == c); system ("cls"); menu ();
/*------------------------------职工信息修改函数--------------------------*/
void Alter_Info ()
{
char ch;//用于查询方式选择、修改项选择
char c;//是否重复查询程序、是否修改另外职工信息;用于人机交互的判断
char New_name[10];
char New_sex[3];
char New_age;
float New_basewage;
float New_postwage;//岗位工资
float New_totalwages;
/*********************************************************查询部分***************************************************/
char name[10];//存取用户输入的姓名
char temp_name[10];//零时存取链表中所保存的结构体的Name成员的值 unsigned int id;//存取用户输入的工号
unsigned int temp_id;//零时存取链表中所保存的结构体的Name成员的值 char check_name;//存取比较函数的返回值
struct Node * pHead;//保存struct Node 类型数据的地址
struct Node * p;
struct Employee temp_Employee;
pHead = create_list ();//pHead是指向头结点的,pHead叫头指针
p = pHead->pNext;//现在的p是指向头节点了
do
{
do { while (1) { printf ("请选择查询方式:1、根据姓名 2、根据职工号\n"); scanf ("%d", &ch); if (ch == 1) { printf ("请输入职工的姓名:\t"); getchar (); gets (name); while(p->pNext != NULL) { temp_Employee = p->data; strcpy(temp_name, temp_Employee.Name); check_name = strcmp (name, temp_name); if (check_name == 0)
break; //如果跳出了循环可能是找到这个职工,那么此时temp_Employee就保存了这个职工的信息,将他打印即可;也可能是找到最后没有找到
p = p->pNext;
}
break;
}
else if (ch == 2)
{
printf ("请输入职工号:\t");
scanf ("%d", &id);
while(p->pNext != NULL)
{
temp_Employee = p->data;
temp_id = temp_Employee.Id;
if (temp_id == id)
break;
p = p->pNext;
}
break;
}
else
{
printf ("输入不合法,请重试!\n");
continue;
}
}
if (p->pNext != NULL)
{
printf ("姓名\t工号\t性别\t年龄\t基本工资\t岗位工资\t总工资\n"); printf ("%s\t%d\t%s\t%d\t%f\t%f\t%f\n", temp_Employee.Name,
temp_Employee.Id, temp_Employee.Sex, temp_Employee.Age, temp_Employee.Basewage, temp_Employee.Postwage, temp_Employee.Totalwages);
}
else
printf ("数据库没有你要查询的人,请检查后重试!\n"); printf ("是否要重新查询!重查请按Y,修改请按N:"); scanf (" %c", &c); }while ('y' == c || 'Y' == c);
/*******************************************************查询结束
***********************************************************/
/*------------------------------------------------------------------------------------------------------------------------*/ /*******************************************************修改部分
***********************************************************/
printf ("**********************修改*************************\n\n"); do { printf ("A、姓名\t B、性别\t C、年龄\t D、基本工资\t E、岗位工资\n"); printf ("请选择需要修改的项:\t"); scanf (" %c", &ch); switch (ch) { case 'A': case 'a': printf ("请输入新名字:"); gets (New_name); strcpy((p->data).Name, New_name); break; case 'B': case 'b': printf ("请输入新性别:"); gets (New_sex); strcpy((p->data).Sex, New_sex); break; case 'C': case 'c': printf ("请输入新年龄:"); scanf ("%d", &New_age); break; case 'D': case 'd': printf ("请输入新的基本工资:"); scanf ("%f", &New_basewage); (p->data).Basewage = New_basewage; break;
case 'E': case 'e': printf ("请输入新的岗位工资:"); scanf ("%f", &New_basewage); (p->data).Basewage = New_basewage; break;
default : printf ("无该选项!请确认后重试");
}
printf ("是否继续修改该职工的信息(Y/N):");
getchar ();
ch = getchar ();
}while (ch == 'Y' || ch == 'y');
save (pHead);//每次一旦更改了一个职工的数据就要对其保存(将链表中的各个节点的数据域中的数据重新替代原二进制文本信息),因为下一次进入时指针的位置就变了
printf ("是否需要修改其他职工的信息(Y/N):");
getchar ();
c = getchar ();
}while (c = 'Y' || c == 'y');
}
/**********************************************修改结束
*******************************************/
/*--------------------------------------整个链表中的数据保存到文件-------------------------------*/ void save (struct Node * pHead)
{
struct Node * p;
struct Employee val;
p = pHead->pNext;//p已经指向了头节点
FILE * Infp;
Infp = fopen ("Information.dat", "wb");
if (Infp == NULL)//如果文件打开失败的提示
{
printf ("员工信息文件打开失败!强行退出\n");
exit(-1);
}
while (p->pNext != NULL)
{
val = p->data;
fwrite (&val, sizeof (struct Employee), 1, Infp);
p = p->pNext;
}
fclose (Infp);
}
/*--------------------------------------------职工工资排序-------------------------------*/
void Wage_Sorting ()
{
char ch; struct Employee temp; struct Node * p_temp; struct Node * pCompare_Last_temp; struct Node * pHead; struct Node * pCompare;//与之比较的数的指针 struct Node * pCompare_Last; struct Node * p;//选择的数的指针 struct Node * p_Last; unsigned int len; unsigned int i; unsigned int j; pHead = create_list (); len = length_list (pHead); do { do { system ("cls"); printf ("请选择排序(从高到低)的工资类型:\n"); printf ("A、基本工资, B、岗位工资, C、总工资\n"); printf ("你的选择是:"); scanf ("%c", &ch);
}while (ch != 'A' && ch != 'B' && ch != 'C' && ch != 'a' && ch != 'b' && ch != 'c');//如果输入不合法就会需要重新选择
switch (ch)
{
//选择法排序基本工资
case 'a' :
case 'A' :
for (i=0,pCompare=pHead->pNext; i<len-1,pCompare->pNext!=NULL;
i++,pCompare=pCompare->pNext)//pHead、pCompare 和 p 都成了头结点的地址域的指针 {
for (j=i+1,p = pCompare->pNext; j<len,p!=NULL; j++,p=p->pNext)
{
if ((p->data).Basewage > (pCompare->data).Basewage)
{
temp = p->data;
p->data = pCompare->data;
pCompare->data = temp;
} } break; }
//冒泡法排序岗位工资
case 'b' :
case 'B' :
for (i=0,pCompare=pHead->pNext; i<len-1,pCompare->pNext!=NULL; i++,pCompare=pCompare->pNext)
{
for (j=0,p=pHead->pNext; j<len-i-1; j++,p=p->pNext)
{
if (((p->pNext)->data).Postwage > (p->data).Postwage) {
temp = p->data;
p->data = (p->pNext)->data;
(p->pNext)->data = temp;
}
}
}
break;
//插入法排序总工资
case 'c' :
case 'C' :
for (i=1,pCompare=(pHead->pNext)->pNext,pCompare_Last=pHead->pNext; i<len,pCompare!=NULL;
i++,pCompare=pCompare->pNext,pCompare_Last=pCompare_Last->pNext)
{
for (j=0,p=pHead->pNext,p_Last=pHead; j<i,p!=pCompare->pNext; j++,p=p->pNext,p_Last=p_Last->pNext)
{
if ((pCompare->data).Totalwages > (p->data).Totalwages) {
p_temp = pCompare_Last->pNext;
pCompare_Last->pNext = pCompare->pNext;
pCompare->pNext = p_Last->pNext;
p_Last->pNext = p_temp;
pCompare = pCompare_Last;
pCompare_Last_temp = pHead->pNext;
while (1)
{
pCompare_Last_temp = pCompare_Last_temp->pNext; if (pCompare_Last_temp->pNext == pCompare_Last) break; } pCompare_Last = pCompare_Last_temp;
break;//这令因为改变了指针的值,所以肯定在返回内部for循环后各个指针指向错误,所以必须直接跳出(这个对排序是没有影响的,因为只有一个只来插入,只需要找到插入点一次)
}
}
}
break;
}
traverse_list (pHead);
printf ("你是否要选择其他方式排序(Y/N),是按Y 选择其他排序方式,否 按任意键回主菜单\n");
scanf (" %c", &ch);
}while ('y' == ch || 'Y' == ch);
system ("cls");
menu ();
}
/*--------------------------------链表长度的计算-------------------------*/
unsigned int length_list (struct Node * pHead)//计算链表长度
{
struct Node * p;
unsigned int len = 0;
p = pHead->pNext;
while (NULL != p)
{
len ++;
p = p->pNext;
}
return len;
}
void Wage_Statistics ()
{
struct Node * pHead;
struct Node * p;
unsigned i;
unsigned len; unsigned int count; printf ("-----------------公司职工工资统计-----------------\n\n"); pHead = create_list (); len = length_list (pHead); printf ("\t\t\t\t姓名\t\t总工资\n"); //总工资一万元内 printf ("总工资一万元内的人:\n"); count = 0; for (i=0,p=pHead->pNext; i<len,p!=NULL; i++,p=p->pNext) if ((p->data).Totalwages <10000.0) { printf ("\t\t\t\t%s :\t%f\n",(p->data).Name, (p->data.Totalwages)); count++; }
printf ("\t\t共计人数:%d\n",count);
//总工资1万元到十万
printf ("总工资一万元到十万元的人:\n");
count = 0;
for (i=0,p=pHead->pNext; i<len,p!=NULL; i++,p=p->pNext)
if ((p->data).Totalwages >= 10000.0 && (p->data).Totalwages <100000.0) {
printf ("\t\t\t\t%s :\t%f\n",(p->data).Name, (p->data.Totalwages)); count++;
}
printf ("\t\t共计人数:%d\n",count);
//总工资十万以上
printf ("总工资一万元以上的人:\n");
count = 0;
for (i=0,p=pHead->pNext; i<len,p!=NULL; i++,p=p->pNext)
if ((p->data).Totalwages >= 100000.0)
{
printf ("\t\t\t\t%s :\t%f\n",(p->data).Name, (p->data.Totalwages)); count++;
}
printf ("\t\t共计人数:%d\n\n\n",count);
printf ("请按按任意键回主菜单!\n");
system ("pause");
system ("cls");
menu();
}
/*-------------------------------文件导出到磁盘--------------------------*/
void Writ_File ()
{
FILE * fp; struct Node * pHead; struct Employee val; char File_Name[20]; char ch; struct Employee temp; struct Node * p_temp; struct Node * pCompare_Last_temp; struct Node * pCompare;//与之比较的数的指针 struct Node * pCompare_Last; struct Node * p; struct Node * p_Last; unsigned int len; unsigned int i; unsigned int j; pHead = create_list (); len = length_list (pHead); do { do { system ("cls");
printf ("A、默认(工号递增)\tB、基本工资递减\tC、岗位工资递减\tD、总工资递减\n");
printf ("你需要用什么排序方式导出文件:");
scanf (" %c", &ch);
}while (ch != 'A' && ch != 'B' && ch != 'C' && ch != 'D' && ch != 'a' && ch != 'b' && ch != 'c'&& ch != 'd');
switch (ch)
{
//默认方式排序,不需要进行任何的排序
case 'a' :
case 'A' : break;
//选择法排序基本工资
case 'b' :
case 'B' :
for (i=0,pCompare=pHead->pNext; i<len-1,pCompare->pNext!=NULL;
i++,pCompare=pCompare->pNext)//pHead、pCompare 和 p 都成了头结点的地址域的指针 {
for (j=i+1,p = pCompare->pNext; j<len,p!=NULL; j++,p=p->pNext) { if ((p->data).Basewage > (pCompare->data).Basewage) { temp = p->data; p->data = pCompare->data; pCompare->data = temp; } } } break;
//冒泡法排序岗位工资
case 'c' :
case 'C' :
for (i=0,pCompare=pHead->pNext; i<len-1,pCompare->pNext!=NULL; i++,pCompare=pCompare->pNext)
{
for (j=0,p=pHead->pNext; j<len-i-1; j++,p=p->pNext)
{
if (((p->pNext)->data).Postwage > (p->data).Postwage) {
temp = p->data;
p->data = (p->pNext)->data;
(p->pNext)->data = temp;
}
}
}
break;
//插入法排序总工资
case 'd' :
case 'D' :
for (i=1,pCompare=(pHead->pNext)->pNext,pCompare_Last=pHead->pNext; i<len,pCompare!=NULL;
i++,pCompare=pCompare->pNext,pCompare_Last=pCompare_Last->pNext)
{
for (j=0,p=pHead->pNext,p_Last=pHead; j<i,p!=pCompare->pNext; j++,p=p->pNext,p_Last=p_Last->pNext)
{
if ((pCompare->data).Totalwages > (p->data).Totalwages) {
p_temp = pCompare_Last->pNext;
pCompare_Last->pNext = pCompare->pNext;
pCompare->pNext = p_Last->pNext;
p_Last->pNext = p_temp;
pCompare = pCompare_Last;
pCompare_Last_temp = pHead->pNext;
while (1)
{
pCompare_Last_temp = pCompare_Last_temp->pNext; if (pCompare_Last_temp->pNext == pCompare_Last) break;
}
pCompare_Last = pCompare_Last_temp;
break;//这令因为改变了指针的值,所以肯定在返回内部for循环后各个指针指向错误,所以必须直接跳出(这个对排序是没有影响的,因为只有一个只来插入,只需要找到插入点一次)
}
}
}
break;
}
p = pHead->pNext;//链表已经排好序,可以从中依次导出职工的信息 printf ("请输入导出文件的名称:"); getchar (); gets (File_Name); fp = fopen (File_Name, "w"); if (fp == NULL)//如果文件打开失败的提示 { printf ("密码校验文件打开失败!强行退出\n"); exit(-1); } while (NULL != p) { val = p->data; fwrite (&val, sizeof(struct Employee), 1, fp); p = p->pNext; } if (ferror(fp) == 0) printf ("文件导出成功!\n"); fclose (fp); printf ("是否需要再次导出文件?(Y/N):");
} scanf (" %c", &ch); }while ('Y' == ch || 'y' == ch); system ("cls"); menu ();
/*------------------------将外部文件到入内部数据文件--------------------*/
void Read_File ()
{
FILE * Infp;//添加数据的文件的指针(是指向被添加的文件) FILE * Oufp;//读取数据的文件的指针 struct Employee val; char File_Name[20]; printf ("请输入导入的文件的名称:"); getchar (); gets (File_Name); Infp = fopen ("Information.dat", "a"); if (Infp == NULL)//如果文件打开失败的提示 { printf ("添加信息的文件打开失败!强行退出\n"); exit(-1); } Oufp = fopen (File_Name, "r"); if (Oufp == NULL)//如果文件打开失败的提示 {
printf ("读取数据的文件打开失败!强行退出\n");
exit(-1);
}
fseek (Infp, 0L, 2);//文件指针指向末尾,文件数据从文件末尾开始添加
fseek (Oufp, 0L, 0);//文件指针指向头部,文件数据从文件头部开始读取
while (feof(Oufp) != 1)//非1表示假,既没有到文件末尾
{
fread (&val, sizeof(struct Employee), 1, Oufp);//从Oufp所指向读取一个职员的信息到val
fwrite (&val, sizeof(struct Employee), 1, Infp);//将val的值(一个职员信息)写到Infp所指向的文件
}
printf ("添加数据的操作已经完成!");
if (ferror (Infp) == 0)
{
printf ("添加数据文件的调用有错误!强制退出"); exit (-1); } if (ferror (Oufp) == 0) {
printf ("读取数据的文件调用有错误!强制退出"); exit (-1);
}
fclose (Infp);
fclose (Oufp);
}
/*---------------------------修改管理员用户名和密码------------------------*/ void Alter_Admin ()
{
FILE * fp;
char user[20];
char user1[20];
char key[20];
char key1[20];
char user_check;
char key_check;
char check;
do
{
fp = fopen ("Login file.dat", "rb");//登陆数据文就爱你的读取方式打开 printf ("请输入旧用户名:"); getchar (); gets (user);//接受时自然有一个回车符,再回车符之前的都要接受 printf ("请输入旧密码:"); gets (key); fread (&user1, 20, 1, fp); fread (&key1, 20, 1, fp); fclose (fp); user_check = strcmp (user1, user); key_check = strcmp (key1, key); if (user_check == 0 && key_check == 0) { printf ("密码验证通过!\n"); printf ("请输"); fp = fopen ("Login file.dat", "wb"); check = fwrite (user, 20, 1, fp); if (check != 1) printf ("写入user失败!");
else printf ("用户名更该成功!下次进入系统生效\n"); check = fwrite (key, 20, 1, fp); if (check != 1) printf ("写入key失败!"); else printf ("密码更改成功!下次登陆时生效\n"); fclose (fp); printf ("是否要再次修改!(Y/N):\n"); } else
printf ("用户名或密码错误!请重试\n");
scanf (" %c", &check);
}while ('y' == check || 'Y' == check);
system ("cls");
menu ();
}
/*------------------------------退出系统-------------------------------*/
void Exit_System (void)
{
printf ("感谢使用!系统正在注销,请稍后......\n");
exit (-1);
}
C语言课程设计心得
通过这次课程设计,增加了我们对软件技术的了解,虽然还不明确软件技术
包含的具体内容,但从学习C语言这门课程开始,已发现程序设计的好处,它对我们数学的学习也有很大的帮助。在学习C语言的过程中也学到和巩固了许多计算机应用基础知识,对计算机的机体也有了一个较为详细的了解。在具体操作中对这学期所学的C语言的理论知识得到巩固加强,达到实训的目的,也发现自己的不足之处,为我们以后的c语言学习奠定了基础,同时体会到C语言具有的语句简洁,使用灵活,执行效率高等特点。发现上机操作的重要作用,特别是对数组和循环有了深刻的理解。通过实际操作,学会 C语言程序编程的基本步骤、基本方法,开发了自己的逻辑思维能力,培养了分析问题、解决问题的能力。 由于本课题中的许多知识点都没有学过都要靠自己到课外的资料中去查找。
在用的时候难免出现这样那样的错误。如开始设计出来的菜单不是预想的那样,而是总个窗中出现混乱。解决的这个问题的办法是调整。一个系统的菜单和提示信息非常重要。如果没有这些用户根本不知道怎么用你设计的这个系统。在设计的调试过程中也无法顺利的完成调试工作。有了一个清晰简单的菜单和一些提示信息这后,调试过程完成的非常顺利。
回顾起此次课程设计,至今我们仍感慨颇多,的确,从拿到题目到完成整个编程,从理论到实践,在这些日子里,可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,
而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我们懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体??通过这次课程设计之后,一定把以前所学过的知识本次课程设计结束了,对于我们的影响很大。我们通过这次实践学到了许多知识。学到了设计一个简单的系统。要注意哪些方面。也使我们知道自己哪些方面做得还不够。 但我们总结出了一点点的经验如下:
① 要对系统的功能和要求做出详细的分析,并合理分解任务。
② 把分解出来的子任务,做给一个相对独立的模块。
③ 在设计一个模块之前,要简单构想一下总界面的显视情况。
④ 针对构想出来的界面进行程序的编写。