C语言的指针和链表举例分析
本篇内容主要讲解"C语言的指针和链表举例分析",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C语言的指针和链表举例分析"吧!
关于指针和链表这两个的应用和上次的管理系统有着直接的关系,没有添加链表和指针的管理系统无法做到精确的查找。数据存储方面也显得不方便。所以指针和链表的作用能够直接指向你所需要的数据地址,使程序更加完善。这次我就利用指针的应用制作了一个管理员工工资等信息的程序。
首先还是最重要的定义和基本函数:
#include
#include
#include
#include
typedef struct Node Node;
//定义工资信息节点
//分别为基本工资、任务工资、支出和实得工资;
struct Score
{
int ji,ren,zhi,sum;
};
//定义员工信息节点
//分别为姓名、工作号、年龄、工资和指向下一个节点的指针
//定义了4个全局变量,头节点,和临时节点变量;
struct Node
{
char name[20],num[20],age[20];
struct Score score;
struct Node* next;
}*head,*u,*p,*q;
//定义多个员工的员工个数及各项工资高水平和平均水平;
int n,C,M,E,Cj,Cy,Mj,My,Ej,Ey;
char num[20];
记住,一定要先定义出所需要的节点,并做出指向下一节点的指针这样指针的作用才能够发挥出来。
这次我先做了程序的开始菜单防止后来忘记:
void Welcome()
{
printf("\t\t # # # # # # # # # # # # # # # # #\n");
printf("\t\t # 欢迎您使用员工工资管理系统 #\n");
printf("\t\t # #\n");
printf("\t\t # 1.读取文件 #\n");
printf("\t\t # #\n");
printf("\t\t # 2.保存文件 #\n");
printf("\t\t # #\n");
printf("\t\t # 3.添加员工工资 #\n");
printf("\t\t # #\n");
printf("\t\t # 4.修改员工工资 #\n");
printf("\t\t # #\n");
printf("\t\t # 5.删除员工工资 #\n");
printf("\t\t # #\n");
printf("\t\t # 6.查询个人工资 #\n");
printf("\t\t # #\n");
printf("\t\t # 7.查询本科工资 #\n");
printf("\t\t # #\n");
printf("\t\t # 8.查询公司工资 #\n");
printf("\t\t # #\n");
printf("\t\t # 9.退出管理系统 #\n");
printf("\t\t # #\n");
printf("\t\t # # # # # # # # # # # # # # # # #\n\n");
printf("\t\t 请输入指令:(1-9) ");
}
接下来便是制造出一个节点信息,并制作输入员工信息的程序,最主要的不要忘记再次做出指向下一节点的函数:
Node* new_node(Node* uu)
{
uu = (Node*)malloc(sizeof(Node));
uu->next = NULL;
return uu;
}
//添加员工信息
void Add()
{
//新建一个节点;
u = new_node(u);
printf("\n请输入您要加入的员工的信息:\n");
printf("\n姓名: ");
scanf("%s",u->name);
printf("\n工作号: ");
scanf("%s",u->num);
printf("\n年龄: ");
scanf("%s",u->age);
printf("\n基本工资、任务工资、支出: ");
scanf("%d%d%d",&u->score.ji,&u->score.ren,&u->score.zhi);
//计算实得工资;
u->score.sum = u->score.ji + u->score.ren - u->score.zhi;
//采用头插法将新节点的尾指针指向第二个节点
u->next = head->next;
//将新节点放在头节点后面;
head->next = u;
printf("\n--->添加成功!\n");
}
这一步做完我们整个的程序的地基就算是打好了,接下来就是慢慢的制作出我们所需要的一些实用指令程序比如:修改和删除。
void Mod()
{
n = 0;
printf("\n请输入您要修改的工作号: ");
scanf("%s",num);
for(u = head; u != NULL;u = u->next)
{
if(strcmp(u->num,num) == 0)
{
n = 1;
printf("\n请输入新的基本工资、任务工资、支出: ");
scanf("%d%d%d",&u->score.ji,&u->score.ren,&u->score.zhi);
u->score.sum = u->score.ji + u->score.ren - u->score.zhi;
printf("\n--->修改成功!\n");
break;
}
}
if(!n)
printf("\n--->没有这个员工的信息!\n");
}
做这个的理论想法是:让程序一个一个节点的寻找,如果找到自己所需的节点就在这产生可以更新的函数程序。
void Del()
{
n = 0;
printf("\n请输入您要删除的员工的学号: ");
scanf("%s",num);
for(u = head; u != NULL;u = u->next)
{
if(strcmp(u->num,num) == 0)
{
n = 1;
p->next = u->next;
free(u);
printf("\n--->删除成功!\n");
break;
}
p = u;
}
if(!n)
printf("\n--->没有这个员工的信息!\n");
}
删除的原理与更改相似,就是当找到所需节点时将其删除即可。并没有什么新的操作。
添加、删除、修改做完以后我们由于是工资管理所以就需要信息的整合,并按照我们所需以工作号排序,所以接下来的程序就是为了解决这个问题:
n = 0;
for(u = head->next; u != NULL;u = u->next)
n++;
for(i=1;i<=n;i++)
{
u = head;
for(j=0;j { p = u->next; q = p->next; if(strcmp(p->num,q->num) > 0 || strcmp(p->num,q->num) == 0 && p->score.sum < q->score.sum) { u->next = q; p->next = q->next; q->next = p; } u = u->next; } } } 这样程序进行循环比较就可以按照工作号进行升序排列并且能将工资信息列举出来。 全部列举之后就是为了能让员工们自己利用程序快速的查找到自己的信息而做出的个人信息的查找程序: //按工作号查找某一员工成绩; void Que_One() { //标志变量,记录是否查找成功; n = 0; printf("\n请输入您要查询的员工的工作号: "); scanf("%s",num); //从第二个节点开始遍历,直到最后一个节点为止; for(u = head->next; u != NULL;u = u->next) { //如果当前节点工作号与要查找工作号一致这输出此员工信息; if(strcmp(u->num,num) == 0) { n = 1; printf("\n"); puts("年龄 姓名 基本工资 任务工资 支出 实得工资"); printf("%-11s%-15s",u->age,u->name); printf("%-6d%-6d%-6d%-6d\n",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); break; } } if(!n) printf("\n--->没有这个员工的信息!\n"); } 再次利用循环让程序挑出想要查找的程序并显现出来有关员工的所有信息,十分的方便。 在这之后就是整个公司的总结,员工们不同的工作会使工资有所不同,从中计算出较高工资和较低工资的员工占比例为多少从而决定公司未来的发展。 void Analyze_Sco(Node *uu) { //对查找到的节点进行求各项平均工资 //求高工资率和较低工资率; C += uu->score.ji; M += uu->score.ren; E += uu->score.zhi; if(uu->score.ji >= 1000) Cj++; if(uu->score.ji >= 5000) Cy++; if(uu->score.ren >= 500) Mj++; if(uu->score.ren >= 1000) My++; } //打印各项平均工资高工资率和低工资率 void Print_Sco() { printf("基本平均工资: %-6.2f, 较低工资率: %%%-6.2f , 高工资率: %%%-6.2f.\n\n",(float)C/n,(float)100*Cj/n,(float)100*Cy/n); printf("任务平均工资: %-6.2f, 较低工资率: %%%-6.2f , 高工资率: %%%-6.2f.\n\n",(float)M/n,(float)100*Mj/n,(float)100*My/n); } 为了确认公司中新员工和老员工数量来判断接下来公司可能的发展进行年龄阶段信息的排列也是必要的: void Que_Cla() { //对链表节点排序; Sort(); n = C = M = E = Cj = Cy = Mj = My = 0; printf("\n请输入您要查询的年龄: "); scanf("%s",num); printf("\n"); for(u = head->next; u != NULL;u = u->next) { //不是该年龄的员工则跳过; if(strcmp(u->age,num)) continue; //如果是第一个员工则打印头信息 if(!n) puts("年龄 姓名 基本工资 任务工资 支出 实得工资"); n++; printf("%-11s%-15s",u->age,u->name); printf("%-6d%-6d%-6d%-d\n",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); Analyze_Sco(u); } if(!n) { printf("没有这个年龄的员工信息!\n"); return ; } //打印该年龄员工的各项工资的特征值; printf("\n该年龄段共有员工 %d 人.\n\n",n); Print_Sco(); } 在制作这些程序是为了方便也可以做出打印的辅助程序,有助于去实施。 最后便是对自己输入或修改的资料进行保存和再读取: void Save() { char c; printf("\n确认保存?(Y/N): "); scanf("%*c%c",&c); if(c == 'N') return ; FILE *fp; if((fp=fopen("C:\\data.txt","w"))==NULL) { printf("\n--->无法打开文件\n"); return ; } //写入数据表头信息; fputs("年龄 工作号 姓名 基本工资 任务工资 支出 实得工资",fp); if(head->next != NULL) fputs("\n",fp); //从头节点开始依次写入文件; for(u = head->next; u != NULL;u = u->next) { fprintf(fp,"%-11s%-11s%-15s",u->age,u->num,u->name); fprintf(fp,"%-6d%-6d%-6d%-d",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); if(u->next != NULL) fprintf(fp,"\n"); } fclose(fp); printf("\n--->成绩成功存入C:\\\\data.txt中\n"); } //读取文件; void Open() { printf("\n请把数据放到目录C:\\\\data.txt中,按任意键确认.\n"); getch(); FILE *fp; //从c盘根目录下读取文件; if((fp=fopen("C:\\data.txt","r"))==NULL) { printf("\n--->没有找到文件!\n"); return ; } char tmp[100]; //读取65个菜单头字符存入tem字符数组中; fgets(tmp,66,fp); //读到文件结尾处跳出循环; while(!feof(fp)) { u = new_node(u); fscanf(fp,"%s%s%s",u->age,u->num,u->name); fscanf(fp,"%d%d%d%d",&u->score.ji,&u->score.ren,&u->score.zhi,&u->score.sum); //头插法建立链表; u->next = head->next; head->next = u; } printf("\n--->成绩读入成功!\n"); fclose(fp); } //退出程序 void Exi() { char c; printf("\n确定退出?(Y/N): "); scanf("%*c%c",&c); if(c == 'N') return ; //打印结束语; system("cls"); printf("\n\n"); printf("\t\t\t %c %c %c %c %c %c %c %c %c\n",4,4,4,4,4,4,4,4,4); printf("\t\t\t %c 谢谢使用 %c\n",4,4); printf("\t\t\t %c %c %c %c %c %c %c %c %c\n",4,4,4,4,4,4,4,4,4); printf("\t\t\t Thank you!\n\n\n"); exit(0); } int main() { //存储指令的变量 int orz; //设置系统文本颜色 system("color 0B"); //新建一个员工信息头节点; head = new_node(head); while(1) { //显示菜单、 Welcome(); //接收用户命令、 scanf("%d",&orz); //调用系统函数清屏; system("cls"); switch(orz) { //根据指令进入相应菜单选项 case 1:Open();break; case 2:Save();break; case 3:Add();break; case 4:Mod();break; case 5:Del();break; case 6:Que_One();break; case 7:Que_Cla();break; case 8:Que_All();break; case 9:Exi();break; default :printf("\n--->无效的指令!\n"); } printf("\n"); //执行系统函数 system("pause"); system("cls"); } return 0; } 这样这个程序就完整的完成了。在这次的程序设计中我们要注意,不要忘记让指针指向下一节点,并且注意。指针的指向是否与你设置的方向一致。要细心尽量不要出现错误,否则更改起来会异常的麻烦。随着C语言程序设计这门课的结束,我对于C语言的了解变得更加的深入,并且也对他产生了浓厚的兴趣。在最后附上这次所做的完整程序代码: #include #include #include #include typedef struct Node Node; //定义工资信息节点 //分别为基本工资、任务工资、支出和实得工资; struct Score { int ji,ren,zhi,sum; }; //定义员工信息节点 //分别为姓名、工作号、年龄、工资和指向下一个节点的指针 //定义了4个全局变量,头节点,和临时节点变量; struct Node { char name[20],num[20],age[20]; struct Score score; struct Node* next; }*head,*u,*p,*q; //定义多个员工的员工个数及各项工资高水平和平均水平; int n,C,M,E,Cj,Cy,Mj,My,Ej,Ey; char num[20]; //进入菜单函数 void Welcome() { printf("\t\t # # # # # # # # # # # # # # # # #\n"); printf("\t\t # 欢迎您使用员工工资管理系统 #\n"); printf("\t\t # #\n"); printf("\t\t # 1.读取文件 #\n"); printf("\t\t # #\n"); printf("\t\t # 2.保存文件 #\n"); printf("\t\t # #\n"); printf("\t\t # 3.添加员工工资 #\n"); printf("\t\t # #\n"); printf("\t\t # 4.修改员工工资 #\n"); printf("\t\t # #\n"); printf("\t\t # 5.删除员工工资 #\n"); printf("\t\t # #\n"); printf("\t\t # 6.查询个人工资 #\n"); printf("\t\t # #\n"); printf("\t\t # 7.查询本科工资 #\n"); printf("\t\t # #\n"); printf("\t\t # 8.查询公司工资 #\n"); printf("\t\t # #\n"); printf("\t\t # 9.退出管理系统 #\n"); printf("\t\t # #\n"); printf("\t\t # # # # # # # # # # # # # # # # #\n\n"); printf("\t\t 请输入指令:(1-9) "); } //构造节点函数 Node* new_node(Node* uu) { uu = (Node*)malloc(sizeof(Node)); uu->next = NULL; return uu; } //添加员工信息 void Add() { //新建一个节点; u = new_node(u); printf("\n请输入您要加入的员工的信息:\n"); printf("\n姓名: "); scanf("%s",u->name); printf("\n工作号: "); scanf("%s",u->num); printf("\n年龄: "); scanf("%s",u->age); printf("\n基本工资、任务工资、支出: "); scanf("%d%d%d",&u->score.ji,&u->score.ren,&u->score.zhi); //计算实得工资; u->score.sum = u->score.ji + u->score.ren - u->score.zhi; //采用头插法将新节点的尾指针指向第二个节点(掰开) u->next = head->next; //将新节点放在头节点后面; head->next = u; printf("\n--->添加成功!\n"); } //根据工作号修改信息 //和查找函数一样,依次从第二个节点开始遍历,如果找到这更新 void Mod() { n = 0; printf("\n请输入您要修改的工作号: "); scanf("%s",num); for(u = head; u != NULL;u = u->next) { if(strcmp(u->num,num) == 0) { n = 1; printf("\n请输入新的基本工资、任务工资、支出: "); scanf("%d%d%d",&u->score.ji,&u->score.ren,&u->score.zhi); u->score.sum = u->score.ji + u->score.ren - u->score.zhi; printf("\n--->修改成功!\n"); break; } } if(!n) printf("\n--->没有这个员工的信息!\n"); } //根据工作号删除员工信息, //从头节点开始遍历,如果找到这删除此节点; void Del() { n = 0; printf("\n请输入您要删除的员工的学号: "); scanf("%s",num); for(u = head; u != NULL;u = u->next) { if(strcmp(u->num,num) == 0) { n = 1; p->next = u->next; free(u); printf("\n--->删除成功!\n"); break; } p = u; } if(!n) printf("\n--->没有这个员工的信息!\n"); } void Sort() { int i,j; //记录员工总数; n = 0; for(u = head->next; u != NULL;u = u->next) n++; //采用冒泡法对各个节点按工作号升序和实得工资降序排列 for(i=1;i<=n;i++) { u = head; for(j=0;j { p = u->next; q = p->next; if(strcmp(p->num,q->num) > 0 || strcmp(p->num,q->num) == 0 && p->score.sum < q->score.sum) { u->next = q; p->next = q->next; q->next = p; } u = u->next; } } } //按工作号查找某一员工成绩; void Que_One() { //标志变量,记录是否查找成功; n = 0; printf("\n请输入您要查询的员工的工作号: "); scanf("%s",num); //从第二个节点开始遍历,直到最后一个节点为止; for(u = head->next; u != NULL;u = u->next) { //如果当前节点工作号与要查找工作号一致这输出此员工信息; if(strcmp(u->num,num) == 0) { n = 1; printf("\n"); puts("年龄 姓名 基本工资 任务工资 支出 实得工资"); printf("%-11s%-15s",u->age,u->name); printf("%-6d%-6d%-6d%-6d\n",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); break; } } if(!n) printf("\n--->没有这个员工的信息!\n"); } void Analyze_Sco(Node *uu) { //对查找到的节点进行求各项平均工资 //求高工资率和较低工资率; C += uu->score.ji; M += uu->score.ren; E += uu->score.zhi; if(uu->score.ji >= 1000) Cj++; if(uu->score.ji >= 5000) Cy++; if(uu->score.ren >= 500) Mj++; if(uu->score.ren >= 1000) My++; } //打印各项平均工资高工资率和低工资率 void Print_Sco() { printf("基本平均工资: %-6.2f, 较低工资率: %%%-6.2f , 高工资率: %%%-6.2f.\n\n",(float)C/n,(float)100*Cj/n,(float)100*Cy/n); printf("任务平均工资: %-6.2f, 较低工资率: %%%-6.2f , 高工资率: %%%-6.2f.\n\n",(float)M/n,(float)100*Mj/n,(float)100*My/n); } //查找某一年龄所有员工的信息; void Que_Cla() { //对链表节点排序; Sort(); n = C = M = E = Cj = Cy = Mj = My = 0; printf("\n请输入您要查询的年龄: "); scanf("%s",num); printf("\n"); for(u = head->next; u != NULL;u = u->next) { //不是该年龄的员工则跳过; if(strcmp(u->age,num)) continue; //如果是第一个员工则打印头信息 if(!n) puts("年龄 姓名 基本工资 任务工资 支出 实得工资"); n++; printf("%-11s%-15s",u->age,u->name); printf("%-6d%-6d%-6d%-d\n",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); Analyze_Sco(u); } if(!n) { printf("没有这个年龄的员工信息!\n"); return ; } //打印该年龄员工的各项工资的特征值; printf("\n该年龄段共有员工 %d 人.\n\n",n); Print_Sco(); } //打印公司所有员工的信息 //具体情况同打印年龄段员工信息; void Que_All() { Sort(); n = C = M = E = Cj = Cy = Mj = My = Ej = Ey = 0; printf("\n"); if(head->next == NULL) { printf("--->没有员工信息!\n"); return ; } puts("年龄 工作号 姓名 基本工资 任务工资 支出 实得工资"); for(u = head->next; u != NULL;u = u->next) { n++; printf("%-12s%-12s%-15s",u->age,u->num,u->name); printf("%-6d%-6d%-6d%-d\n",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); Analyze_Sco(u); } printf("\n全公司共有员工 %d 人.\n\n",n); Print_Sco(); } //保存文件; void Save() { char c; printf("\n确认保存?(Y/N): "); scanf("%*c%c",&c); if(c == 'N') return ; FILE *fp; if((fp=fopen("C:\\data.txt","w"))==NULL) { printf("\n--->无法打开文件\n"); return ; } //写入数据表头信息; fputs("年龄 工作号 姓名 基本工资 任务工资 支出 实得工资",fp); if(head->next != NULL) fputs("\n",fp); //从头节点开始依次写入文件; for(u = head->next; u != NULL;u = u->next) { fprintf(fp,"%-11s%-11s%-15s",u->age,u->num,u->name); fprintf(fp,"%-6d%-6d%-6d%-d",u->score.ji,u->score.ren,u->score.zhi,u->score.sum); if(u->next != NULL) fprintf(fp,"\n"); } fclose(fp); printf("\n--->成绩成功存入C:\\\\data.txt中\n"); } //读取文件; void Open() { printf("\n请把数据放到目录C:\\\\data.txt中,按任意键确认.\n"); getch(); FILE *fp; //从c盘根目录下读取文件; if((fp=fopen("C:\\data.txt","r"))==NULL) { printf("\n--->没有找到文件!\n"); return ; } char tmp[100]; //读取65个菜单头字符存入tem字符数组中; fgets(tmp,66,fp); //读到文件结尾处跳出循环; while(!feof(fp)) { u = new_node(u); fscanf(fp,"%s%s%s",u->age,u->num,u->name); fscanf(fp,"%d%d%d%d",&u->score.ji,&u->score.ren,&u->score.zhi,&u->score.sum); //头插法建立链表; u->next = head->next; head->next = u; } printf("\n--->成绩读入成功!\n"); fclose(fp); } //退出程序 void Exi() { char c; printf("\n确定退出?(Y/N): "); scanf("%*c%c",&c); if(c == 'N') return ; //打印结束语; system("cls"); printf("\n\n"); printf("\t\t\t %c %c %c %c %c %c %c %c %c\n",4,4,4,4,4,4,4,4,4); printf("\t\t\t %c 谢谢使用 %c\n",4,4); printf("\t\t\t %c %c %c %c %c %c %c %c %c\n",4,4,4,4,4,4,4,4,4); printf("\t\t\t Thank you!\n\n\n"); exit(0); } int main() { //存储指令的变量 int orz; //设置系统文本颜色 system("color 0B"); //新建一个员工信息头节点; head = new_node(head); while(1) { //显示菜单、 Welcome(); //接收用户命令、 scanf("%d",&orz); //调用系统函数清屏; system("cls"); switch(orz) { //根据指令进入相应菜单选项 case 1:Open();break; case 2:Save();break; case 3:Add();break; case 4:Mod();break; case 5:Del();break; case 6:Que_One();break; case 7:Que_Cla();break; case 8:Que_All();break; case 9:Exi();break; default :printf("\n--->无效的指令!\n"); } printf("\n"); //执行系统函数 system("pause"); system("cls"); } return 0; } 到此,相信大家对"C语言的指针和链表举例分析"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!