今天初步完成了通讯录的添加、删除、查找、显示4个功能。
贴代码:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define MAX 100
/*建立结构体链表,固定结构,背下来*/
typedef struct people
{
char name[MAX];
char sex[MAX];
int age;
long long int tel;
char addr[MAX];
struct people *pNext;
}Node, *pNode; /*Node为结构体变量,pNode为结构体指针变量,也可以只写Node,在定义指针的时候写成(Node *p)*/
/*定义全局变量,记录最后录入的联系人的节点数*/
int num = 0;
int main(void)
{
int flag;
char ch;
pNode pHead = NULL; /*首次定义头指针需要置零*/
pNode CreatList(void);
pNode CreatMember(pNode);
void FindMember(pNode);
void DeleteMember(pNode);
void DeleteList(pNode);
void TraverseList(pNode);
while (1)
{
printf("1.添加联系人信息\n2.删除指定联系人信息\n3.查找指定联系人信息\n4.修改指定联系人信息\n5.显示所有联系人信息\n6.清空所有联系人\n7.以名字排序所有联系人\n");
printf("请输入要进行的操作:");
scanf_s("%d", &flag);
printf("\n");
while (getchar() != '\n')
{
ch = getchar();
}
switch (flag)
{
case 1:
{
/*首次录入联系人*/
if (num == 0)
{
pHead = CreatList();
}
/*重复录入联系人*/
else
{
pHead = CreatMember(pHead);
}
printf("\n");
break;
}
case 2:
{
/*剩余联系人超过1人时,令链表为空表*/
if (num == 1)
{
DeleteList(pHead);
}
/*正常删除*/
else
{
DeleteMember(pHead);
}
printf("\n");
break;
}
case 3:
{
FindMember(pHead);
printf("\n");
break;
}
case 4:
{
printf("4\n");
break;
}
case 5:
{
/*链表中有联系人时,正常遍历*/
if (num > 0)
{
TraverseList(pHead);
}
/*空链表*/
else
{
printf("无联系人。");
}
printf("\n");
break;
}
case 6:
{
printf("6\n");
break;
}
case 7:
{
printf("7\n");
break;
}
}
printf("现有%d个联系人。\n\n\n", num);
}
return 0;
}
/*首次录入联系人,建立一个新的链表*/
pNode CreatList(void)
{
/*定义头节点、尾节点、新节点*/
pNode pHead, pTail, pNew;
pHead = (pNode)malloc(sizeof(Node)); /*为头指针开辟一块内存*/
pTail = pHead; /*空链表的头节点就是尾节点*/
pTail->pNext = NULL; /*尾节点指向空值*/
/*输入数据给新节点*/
pNew = (pNode)malloc(sizeof(Node)); /*为新节点开辟内存*/
printf("请输入联系人姓名:");
scanf_s("%s", &pNew->name, MAX);
printf("请输入联系人性别:");
scanf_s("%s", &pNew->sex, MAX);
printf("请输入联系人年龄:");
scanf_s("%d", &pNew->age);
printf("请输入联系人电话:");
scanf_s("%lld", &pNew->tel);
printf("请输入联系人地址:");
scanf_s("%s", &pNew->addr, MAX);
/*新节点接入链表*/
pTail->pNext = pNew; /*令原来的尾节点指向新节点*/
pNew->pNext = NULL; /*新节点指向空值*/
pTail = pNew; /*新节点成为新的尾节点,原来的尾节点成为中间节点*/
/*录入联系人+1*/
num++;
return pHead;
}
/*重复录入联系人,将新的联系人接到原有的链表中*/
pNode CreatMember(pNode p)
{
/*定义新链表的头节点、尾节点、新节点、临时节点*/
pNode pHead, pTail, pNew, pSwap, pRepeat;
char a[MAX];
pHead = p; /*将原有的链表赋给pHead*/
pRepeat = p->pNext;
/*寻找原有链表的最后一个节点*/
pSwap = NULL; /*定义一个pVal来临时保存最后一个节点的数据*/
while (p != NULL)
{
pSwap = p; /*pVal始终为p的前一个节点,当遍历结束时,p为空,pVal即为最后一个节点*/
p = p->pNext;
}
pTail = pSwap; /*令pTail成为链表最后一个节点*/
pTail->pNext = NULL; /*尾节点指向空值*/
/*输入数据给新节点*/
pNew = (pNode)malloc(sizeof(Node));
printf("请输入联系人姓名:");
scanf_s("%s", &pNew->name, MAX);
printf("请输入联系人性别:");
scanf_s("%s", &pNew->sex, MAX);
printf("请输入联系人年龄:");
scanf_s("%d", &pNew->age);
printf("请输入联系人电话:");
scanf_s("%lld", &pNew->tel);
printf("请输入联系人地址:");
scanf_s("%s", &pNew->addr, MAX);
/*判断新录入的联系人是否已存在*/
while (pRepeat != NULL)
{
if (strcmp(pNew->name, pRepeat->name) == 0)
{
printf("联系人已存在!\n");
return pHead;
}
pRepeat = pRepeat->pNext;
}
/*新节点接入链表*/
pTail->pNext = pNew; /*令原来的尾节点指向新节点*/
pNew->pNext = NULL; /*新节点指向空值*/
pTail = pNew; /*新节点成为新的尾节点,原来的尾节点成为中间节点*/
/*录入联系人+1*/
num++;
return pHead;
}
/*查找联系人*/
void FindMember(pNode p)
{
/*定义临时节点*/
pNode pSwap;
char a[MAX];
printf("请输入要查找的联系人姓名:");
scanf_s("%s", a, MAX);
pSwap = p->pNext; /*将联系人链表头节点赋值给临时节点*/
/*遍历*/
while (pSwap != NULL)
{
if (strcmp(pSwap->name, a) == 0) /*检查姓名是否*/
{
printf("%s ", pSwap->name);
printf("%s ", pSwap->sex);
printf("%d ", pSwap->age);
printf("%lld ", pSwap->tel);
printf("%s\n", pSwap->addr);
break;
}
pSwap = pSwap->pNext;
}
if (pSwap == NULL)
{
printf("未找到联系人!\n");
}
return 0;
}
/*删除第一个联系人,令链表为空*/
void DeleteList(pNode p)
{
/*定义临时节点*/
pNode pSwap;
char a[MAX];
printf("请输入要删除的联系人姓名:");
pSwap = p; /*将联系人链表头节点赋值给临时节点*/
scanf_s("%s", a, MAX);
if (strcmp(pSwap->pNext->name, a) == 0) /*检查姓名是否匹配*/
{
pSwap = NULL;
/*删除联系人-1*/
num--;
}
else
{
printf("联系人不存在!");
}
return 0;
}
/*删除指定联系人*/
void DeleteMember(pNode p)
{
/*定义临时节点*/
pNode pSwap, pVal;
char a[MAX];
printf("请输入要删除的联系人姓名:");
pSwap = p; /*将联系人链表头节点赋值给临时节点*/
pVal = p;
scanf_s("%s", a, MAX);
/*遍历*/
while (pSwap != NULL)
{
if (strcmp(pSwap->name, a) == 0) /*检查姓名是否匹配*/
{
pVal->pNext = pVal->pNext->pNext;
break;
}
pVal = pSwap; /*保存要删除的节点的前一节点*/
pSwap = pSwap->pNext;
}
if (pSwap == NULL)
{
printf("未找到联系人!\n");
}
/*删除联系人-1*/
num--;
return 0;
}
/*遍历输出所有联系人*/
void TraverseList(pNode pHead)
{
/*定义临时节点*/
pNode p;
p = pHead->pNext; /*把pHead->pNext而不是pHead赋给p,是因为pHead的数据域本身没有意义,因此只需要赋值pHead->pNext,即将第一个节点的数据域和指针域赋给p*/
/*执行遍历*/
while (p != NULL)
{
printf("%s ", p->name);
printf("%s ", p->sex);
printf("%d ", p->age);
printf("%lld ", p->tel);
printf("%s\n", p->addr);
p = p->pNext;
}
return 0;
}
收获:
- 指针让函数通过自己的局部变量改变其他函数中变量的值,不管指针经过了多少次赋值,只要地址还在,都会影响对应地址上的变量值
疑问:
- 一个变量可以被两个指针控制吗?向下面这段代码,m和u都可以空值x的值
#include <stdio.h>
void exe(int *u, int *v)
{
int m = u;
printf("请输入x的值,m=");
scanf_s("%d", m);
printf("请输入x的值,u=");
scanf_s("%d", u);
printf("请输入y的值,y=");
scanf_s("%d", v);
}
int main(void)
{
int x, y;
exe(&x, &y);
printf("x=%d,y=%d\n", x, y);
return 0;
}
- 什么是野指针?指针用完之后怎么取消掉