进击的小白Day007——通讯录(一)

今天来diy一个通讯录,功能需求是从网上找的,然后这些功能恰好需要用到结构体、指针、链表这些功能,恰好可以练练手。

通讯录可以用来存储1000个人的信息,每个人的信息包括:
姓名、性别、年龄、电话、住址
实现功能:

  1. 添加联系人信息
  2. 删除指定联系人信息
  3. 修改指定联系人信息
  4. 查找指定联系人信息
  5. 显示所有联系人信息
  6. 清空所有联系人
  7. 以名字排序所有联系人

今天只实现了1和5的功能,其他的明天继续,贴代码:

#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 reCreatList(pNode);
	void TraverseList(pNode);
	
	while (1)
	{ 
		printf("请输入要进行的操作:\n");
		printf("1.添加联系人信息\n2.删除指定联系人信息\n3.修改指定联系人信息\n4.查找指定联系人信息\n5.显示所有联系人信息\n6.清空所有联系人\n7.以名字排序所有联系人\n");
		scanf_s("%d", &flag);


		while (getchar() != '\n')
		{
			ch = getchar();
		}

		switch (flag)
		{
			case 1:
			{
				/*首次录入联系人*/
				if (pHead == NULL)
				{
					pHead = CreatList();
				}
				/*重复录入联系人*/
				else
				{
					pHead = reCreatList(pHead);
				}
				printf("\n");
				break;
			}
			case 2:
			{
				printf("2\n");
				break;
			}
			case 3:
			{
				printf("3\n");
				break;
			}
			case 4:
			{
				printf("4\n");
				break;
			}
			case 5:
			{
				TraverseList(pHead);
				printf("\n");
				break;
			}
			case 6:
			{
				printf("6\n");
				break;
			}
			case 7:
			{
				printf("7\n");
				break;
			}
		}
	}
	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 reCreatList(pNode p)
{
	/*定义新链表的头节点、尾节点、新节点*/
	pNode pHead, pTail, pNew;
	pHead = p;  /*将原有的链表赋给pHead*/

	/*寻找原有链表的最后一个节点*/
	pNode pVal = NULL;  /*定义一个pVal来临时保存最后一个节点的数据*/
	while (p != NULL)
	{
		pVal = p;  /*pVal始终为p的前一个节点,当遍历结束时,p为空,pVal即为最后一个节点*/
		p = p->pNext;
	}
	pTail = pVal;  /*令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);

	/*新节点接入链表*/
	pTail->pNext = pNew;  /*令原来的尾节点指向新节点*/
	pNew->pNext = NULL;  /*新节点指向空值*/
	pTail = pNew;  /*新节点成为新的尾节点,原来的尾节点成为中间节点*/

	/*录入联系人+1*/
	num++;

	return pHead;
}

/*遍历输出所有联系人*/
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;
}

刚刚也说了,这部分内容主要训练链表方面的知识,但又与其他的链表建立不太一样,因为通讯录的录入联系人并不是一次性把多有的联系人都录入,中间会有间断,因此通讯录的链表不是一次建成的,而是需要后续数据不断接到原有链表之上。这就在后续录入的时候,需要知道之前录入过多少次,以便统计总人数,不超过1000。因此这边是定义了一个全局变量num,在每次子函数对成员操作的时候都会有num的加加减减。

收获:

  1. 链表到底是个什么样的结构,链表该怎么建立,主要步骤都在代码的注释中有所体现;
  2. p = pHead表示把头指针赋值给p,p = pHead->pNext表示把头指针之后的链表第一个节点赋值给p,详见代码132和173行。

今天就到这儿了,明天不一定有时间继续看这个,Socket那个程序还需要继续完善,从最初网上下的100多行写到300,再到500,再到现在的700,估计这次完善之后有可能破千了,或许真应该庆幸自己对这个比较感兴趣,或者终于在学习这条路上找到了自己感兴趣的点了。

猜你喜欢

转载自blog.csdn.net/u011232393/article/details/83865207
今日推荐