1 #include
2 #include//malloc
3 #include
4 #include
5 #include
6 #define SIZE 12 //姓名字符串大小为12个字符,包含空字符
7 #define SEX 6 //性别字符串大小为6个字符,包含空字符
8 typedef structitem{9 char name[SIZE]; //创建一个储存姓名的成员
10 char sex[SEX]; //创建一个储存性别的成员
11 int age; //创建一个储存年龄的成员
12 struct item * next; //指向自身的结构的指针用以指向下一个item结构
13 }Item; //利用typdef定义一个Item类型,其结构为item
14 typedef structnode{15 Item item; //创建一个Item结构的成员
16 struct node * next; //创建一个指向下一个节点的节点指针
17 }Node; //利用typdef定义一个Node类型,其结构为node
18 typedef Node * List; //定义List为一个指向Node节点的指针类型
19 void InitializeList(List * p){ //接受一个(指向Node节点的指针)的指针
20 *p=NULL; //将指向Node节点的指针设为空(*号解引用指向Node节点的指针的指针得到Node节点的指针)
21 }22 bool IsListEmpty(List *p){ //接受一个(指向Node节点的指针)的指针
23 return *p==NULL?true:false; //如果Node节点为空返回真否则返回假
24 }25 void CopyToNode(Item item,Node *p){ //接受一个Item结构参数和一个指向Node节点的指针
26 p->item=item; //Node节点的item成员获得传来的item信息
27 }28 bool AddItem(Item item,List *p){ //接受一个Item结构参数和一个指(向Node节点的指针)的指针
29 Node * pnew; //声明一个指向Node节点类型的指针pnew
30 Node * scan=*p; //声明一个指向Node节点类型的指针scan,该指针获得传来的节点的指针地址
31 pnew=(Node *)malloc(sizeof(Node)); //为pnew分配空间
32 if(pnew==NULL) //如果分配失败
33 return false; //返回假
34 CopyToNode(item,pnew); //将item结构信息和已分配好空间的pnew作为参数传送以将item作为pnew节点的一部分
35 pnew->next=NULL; //将pnew的下一个节点设为空
36 if(scan==NULL) //如果传来的Node节点为空(代表尚无信息录入))
37 *p=pnew; //则该Node节点获得pnew这个已获取信息的Node节点的地址
38 else{ //如果传来的Node节点不为空
39 while(scan->next!=NULL) //当传来的Node节点的next指针指向不为空时
40 scan=scan->next; //该节点等于下一个节点41 //循环结束得到一个节点的下一个节点为空
42 scan->next=pnew; //节点的下一个节点获得pnew这个节点的地址以形成链接
43 }44 return true; //返回真
45 }46 void ShowItems(Item item){ //接受一个Item结构类型
47 printf("姓名:%s 性别:%s 年龄:%d\n",item.name,item.sex,item.age); //打印该结构的成员信息
48 }49 void whi1e(const List *pt,void (*p) (Item item)){ //接受一个(指向Node节点的指针)的指针和一个函数指针(该函数指针,接受一个Item结构参数,其返回值为空)
50 Node * look=*pt; //创建一个指向Node节点的指针,该指针获得解析的来的指向(Node结构的指针的指针)的地址,即节点的指针
51 while(look!=NULL){ //当Node节点指针不为空时
52 p(look->item); //调用传来的函数即ShowItems,将当前Node节点的item成员作为参数传送过去以打印
53 look=look->next; //节点指向下一个节点以打印下一个节点的信息
54 }55 }56 void DeList(List *p){ //接受一个指向(Node节点的指针)的指针以删除储存节点信息的列表
57 List * replace=p; //创建一个指向(Node节点的指针)的指针repalce来获得传来的指针p
58 while(replace!=NULL){ //如果该指向(Node节点的指针)的指针不为空
59 free(*replace); //释放该指针指向的节点空间
60 (*p)=(*p)->next; //传来的指针p指向的节点等于下一个节点
61 *replace=*p; //replace指向的节点等于p指针指向的节点
62 }63 }64 unsigned int ListCounter(const List *p){ //接受一个只读类型的(指向Node节点的指针)的指针
65 Node * example = *p; //创建一个指向Node节点的指针来获取传来的p指针指向的节点
66 unsigned int counter=0; //计数器置0
67 while(example!=NULL){ //当这个节点不为空
68 counter++; //计数器+1
69 example=example->next; //该节点等于下一个节点
70 }71 return counter; //返回结果
72 }73 bool DeNode(List *p,char *pt){ //接受一个(指向Node节点的指针)的指针p和一个字符串pt以删除指定姓名的信息
74 Node * front=NULL; //创建一个指向Node节点结构类型的指针front,初始化为空,该指针用以指向rear这个节点的上一个节点来进行删除节点后的连接工作
75 Node * rear=*p; //创建一个指向Node节点结构类型的指针rear并获得传来的节点
76 while(rear!=NULL){ //当节点不为空时进行循环
77 if(strcmp(rear->item.name,pt)==0){ //如果找到姓名相同的
78 if(front==NULL){ //如果这个节点是第一个节点时
79 free(rear); //释放该节点
80 *p=(*p)->next; //该指针指向的节点等于下一个节点
81 return true; //返回真
82 }83 else{ //当找到的不是第一个节点时
84 front->next=rear->next; //上一个节点的next指向已找到的当前节点的下一个节点
85 free(rear); //释放当前节点
86 return true; //返回真
87 }88 }89 else //没找到时
90 front=rear; //front等于当前节点
91 rear=rear->next; //rear等于当前节点的下一个节点
92 }93 return false; //返回假
94 }95 void menu(void){ //打印菜单
96 printf("a:添加信息\n");97 printf("d:删除信息\n");98 printf("p:打印信息\n");99 printf("q:退出并清空列表\n");100 }101 voidmain(){102 Item item; //创建一个item结构以获取输入并作为数据传送
103 List info; //创建一个指向Node类型的指针,Node类型包含一个item结构成员和一个指向下一个节点的指针
104 char ch=‘y‘; //初始化ch
105 char name[SIZE]; //获取要删除的姓名
106 InitializeList(&info); //将指向Node的指针的地址作为参数传送(因该函数要求接受一个指向Node的指针的指针,而info为一个指向Node节点的指针,该函数的指针通过*号解引用便获得了该指针指向的Node节点)
107 menu(); //打印菜单
108 while(ch!=‘q‘){109 switch (tolower(ch)) { //将字母小写
110 case ‘a‘:{111 printf("请输入你的姓名:");112 scanf("%s",item.name); //获取信息以存储到item结构的成员中
113 printf("请输入你的性别:");114 scanf("%s",item.sex); //获取信息以存储到item结构的成员中
115 printf("请输入你的年龄:");116 scanf("%d",&item.age); //获取信息以存储到item结构的成员中
117 AddItem(item,&info); //将item和指向节点的指针的地址作为参数传送以形成连接
118 menu(); //打印菜单
119 break;120 }121 case ‘d‘:{122 printf("你想删除哪个人的信息(键入此人姓名):");123 scanf("%s",name);124 printf("%s",DeNode(&info,name)?"删除成功\n":"删除失败\n"); //如果返回为真则删除成功,否则失败
125 menu(); //打印菜单
126 break;127 }128 case ‘p‘:{129 printf("共有%d条信息\n",ListCounter(&info)); //将指向节点的指针的地址作为参数传送,该函数接受一个(指向Node节点的指针)的指针,该指针指向节点的指针的地址,通过*号解引用获得对应的节点信息
130 whi1e(&info,ShowItems); //将指向节点的指针的地址作为参数传送,同时将一个函数作为参数传送
131 menu(); //打印菜单
132 break;133 }134 }135 setbuf(stdin,NULL); //将标准输入的文件指针指向的缓冲区设为空
136 ch=getchar();137 setbuf(stdin,NULL); //将标准输入的文件指针指向的缓冲区设为空
138 }139 DeList(&info); //删除列表
140 printf("再见!\n");141 }