LinuxC语言——通讯录

通讯录是许多手机等电子产品必带功能之一,在有了数据结构中链表的相关知识后,便可以自己制作一个简单的通讯录了。

制作通讯录的一些基础知识

  1. 结构体
  • 结构体是什么?说白了结构体是一种类型,它可以是一些其他类型的集合体;打个比方,数组是它元素类型的集合体,int a[10]是int类型的集合体;同理,结构体是它自身一些元素类型的集合体;为什么说是一些呢?这就涉及到了数组与结构体的区别了;数组中元素的类型是确定,一致的,而在结构体中,其元素可以是不同类型的。
  • 本文用到的结构体
//个人信息
struct people
{
    
    
	char name[20];
	int number;
};
  1. 链表
  • 链表是一系列的存储数据元素的单元通过指针串接起来形成的,因此每个单元至少有两个域,一个域用于数据元素的存储,另一个或两个域是指向其他单元的指针。这里具有一个数据域和多个指针域的存储单元通常称为节点(node)。

  • 链表的第一个节点和最后一个节点,分别称为链表的头节点和尾节点。尾节点的特征是其 next 引用为空(null)。链表中每个节点的 next 引用都相当于一个指针,指向另一个节点,借助这些 next 引用,我们可以从链表的头节点移动到尾节点

  • 本文用到的链表节点

//双向链表节点设计
struct double_list
{
    
    
	struct double_list *prev;    //用于存放上一个(前缀)节点地址指针变量
	struct people data;          //数据  数据域
	struct double_list *next;    //用于存放下一个(后缀)节点地址指针变量
};

功能

  • 使用链表实现增加(在增加人员的过程中有一个自动排序功能,比如按姓名排序)、删除、修改、查找(比如:工号查找、电话查找)的功能;
  • 添加用户信息
  • 列出好友信息
  • 查找好友信息(按姓名、号码查找)
  • 删除好友
  • 修改号码
  • 退出

代码

链表节点创建

//(2)节点初始化(在堆空间生成节点)
struct double_list *new_node(void)
{
    
    
	struct double_list *p = NULL;  //指针变量p
	
	//在堆空间开辟内存,大小为:sizeof(struct double_list)
	p = (struct double_list *)malloc(sizeof(struct double_list));
	
	if(p == NULL)
	{
    
    
		printf("开辟空间失败!\n");
		return 0;
	}
	
	p->data.number=0;//结构体成员初始化
 
	//两个指针成员存放自己的地址,即单个节点也是循环链表
	p->next = p;
	p->prev = p;
	
	return p;
}

节点插入 增加节点到链表头

void insert_node(struct double_list *p, struct double_list *new)
{
    
    
	if(p == NULL || new == NULL)
	{
    
    
		return;
	}
	
	new->next		= p->next; 	
	p->next->prev	= new;		
	new->prev 		= p;		
	p->next 		= new;		
}

节点插入 增加节点到链表尾部

void insert_node_tail(struct double_list *p, struct double_list *new)
{
    
    
	if(p == NULL || new == NULL)
	{
    
    
		return;
	}
	p->prev->next = new;	
	new->prev = p->prev;	
	p->prev = new;      	
	new->next = p;	    	
}

节点查找(姓名、号码)

struct double_list *find_node(struct double_list *head, struct people s)
{
    
    
	struct double_list *p;
	int ret;
	
	p = head->next;  //指针第一个数据节点

	while(p != head)  //有数据节点
	{
    
    
		ret = strcmp(p->data.name,s.name);
		
		if(ret == 0)
		{
    
    
			return p;    //返回节点地址 结束循环
		}
		p = p->next;     //移动到下一个节点
	}
	
	//遍历完成整个链表,无法查找与数据相等的节点,返回NULL
	return NULL;
	
}
struct double_list *find_node1(struct double_list *head, struct people s)
{
    
    
	struct double_list *p;
	int ret;
	
	p = head->next;  //指针第一个数据节点

	while(p != head)  //有数据节点
	{
    
    
		if(p->data.number == s.number);
		
		if(ret == 0)
		{
    
    
			
			return p;    //返回节点地址 结束循环
		}
		p = p->next;     //移动到下一个节点
	}
	
	//遍历完成整个链表,无法查找与数据相等的节点,返回NULL
	return NULL;
	
}

节点删除

void del_node(struct double_list *del)
{
    
    
	del->prev->next = del->next;  
	del->next->prev = del->prev;   
	del->prev = del;              
	del->next = del;               
}

因为我删除之前进行查找操作,此处代码操作将数据节点解下来,所以我再主函数进行释放节点。

显示节点

//节点显示
void display_node(struct double_list *head)
{
    
    
	struct double_list *p;
	
	p = head->next;  //指针第一个数据节点
	
	while(p != head)  //有数据节点
	{
    
    
		printf("名字:%s\t", p->data.name);
		printf("电话号码:%d", p->data.number);
		printf("\n");
		p = p->next;
	}
	
	printf("\n");
}

主函数逻辑

printf("\033[1;31;46m=========================通讯录============================ \033[0m\n");
		printf("*******************     添加联系人     :1******************\n");
		printf("*******************     查看所有       :2******************\n");
		printf("*******************     查找联系人(名) :3******************\n");
		printf("*******************     查找联系人(号) :4******************\n");
		printf("*******************     删除联系人     :5******************\n");
		printf("*******************     修改联系方式   :6******************\n");
		printf("*******************     退出通讯录     :q******************\n");
		printf("\033[1;31;46m=========================================================== \033[0m\n");

此处printf("\033");是更改显示的颜色,不需要可以去除。

运行效果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46026429/article/details/108484048