进击的小白Day008——通讯录(二)

今天初步完成了通讯录的添加、删除、查找、显示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;
}

收获:

  1. 指针让函数通过自己的局部变量改变其他函数中变量的值,不管指针经过了多少次赋值,只要地址还在,都会影响对应地址上的变量值

疑问:

  1. 一个变量可以被两个指针控制吗?向下面这段代码,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;
}
  1. 什么是野指针?指针用完之后怎么取消掉

猜你喜欢

转载自blog.csdn.net/u011232393/article/details/83899514