单向链表(数据防止误操作)

本文介绍了一种防止用户直接修改链表数据的方法,通过使用`void*`类型并配合回调函数,实现了对链表的读取操作,确保了数据安全。讲解了如何初始化链表、插入、遍历、删除及清空链表,同时展示了如何在`main.c`中应用这些操作。
摘要由CSDN通过智能技术生成

C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂 

防止用户能在主程序对链表内数据进行修改:用void* 修饰数据,回调函数来遍历数据。

代码如下:

LinkList.h

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//节点结构体
struct LinkNode {
	//数据域
	void* data;
	//指针域
	struct LinkNode* next;
};

//链表结构体
struct LList {
	//头结点
	struct LinkNode *pHeader;
	//链表长度
	int m_size;
};

typedef  void*  LinkList;

//初始化链表
LinkList init_LinkList();

//插入链表 按位置插
LinkList insert_LinkList(LinkList List  , int pos, void * data);

//遍历链表
void foreach_LinkList(LinkList List , void (*MyPrint)(void*));

//删除链表 按位置删除
void DeleteByPos_LinkList(LinkList List, int pos);

//删除链表 按值删除
void DeleteByVal_LinkList(LinkList List, void * data , int (*Mycompare)(void* , void*));

//清空链表
void clean_LinkList(LinkList List);

//返回链表长度
int  size_LinkList(LinkList list);

//销毁链表
void destroy_Linklist(LinkList list);

LinkList.c

#include "LinkList.h"

//初始化链表
LinkList init_LinkList()
{
	struct LList * MyList = (struct LList *)malloc(sizeof(struct LList));
	if (MyList == NULL)
	{
		return NULL;
	}
	//初始化头结点
	MyList->pHeader = (struct LinkNode *)malloc(sizeof(struct LinkNode));
	MyList->pHeader->data = NULL;
	MyList->pHeader->next = NULL;
	//初始化链表长度
	MyList->m_size = 0;

	return MyList;
}

//插入链表 按位置插
LinkList insert_LinkList(LinkList List , int pos, void * data)
{
	if (List == NULL)
	{
		return ;
	}
	if (data == NULL)
	{
		return ;
	}
	//将List 还原成 struct LList 数据类型
	struct LList * MyList = List;

	//无效位置 尾插
	if (pos < 0 || pos > MyList->m_size)
	{
		pos = MyList->m_size;
	}

	//插入结点的前驱结点
	struct LinkNode * pCurrebt = MyList->pHeader;

	//找到插入结点的前驱结点
	for (int i = 0; i < pos; i++)
	{
		pCurrebt = pCurrebt->next;
	}

	//创建新节点
	struct LinkNode * NewLinkNode = (struct LinkNode *)malloc(sizeof(struct LinkNode));
	NewLinkNode->data = data;

	//建立关系
	NewLinkNode->next = pCurrebt->next;
	pCurrebt->next = NewLinkNode;

	//更新链表长度
	MyList->m_size++;
}

//遍历链表
void foreach_LinkList(LinkList List, void (*MyPrint)(void*))
{
	if (List == NULL)
	{
		return;
	}

	//将List 还原成 struct LList 数据类型
	struct LList * MyList = List;
	
	struct LinkNode * pCurrebt = MyList->pHeader->next;

	for(int i = 0; i < MyList->m_size ; i++)
	{
		MyPrint(pCurrebt->data);
		pCurrebt = pCurrebt->next;
	}
}

//删除链表 按位置删除
void DeleteByPos_LinkList(LinkList List, int pos)
{
	if (List == NULL)
	{
		return;
	}

	//将List 还原成 struct LList 数据类型
	struct LList * MyList = List;

	//无效删除位置
	if (pos < 0 || pos > MyList->m_size - 1)
	{
		return;
	}

	//删除结点的前驱结点
	struct LinkNode * pCurrebt = MyList->pHeader;

	//找到删除结点的前驱结点
	for (int i = 0; i < pos; i++)
	{
		pCurrebt = pCurrebt->next;
	}

	//待删除节点
	struct LinkNode * DeleteLinkNode = pCurrebt->next;
	//删除结点
	pCurrebt->next = DeleteLinkNode->next;

	free(DeleteLinkNode);
	DeleteLinkNode = NULL;

	//更新链表长度
	MyList->m_size--;
}

//删除链表 按值删除
void DeleteByVal_LinkList(LinkList List, void * data, int(*Mycompare)(void*, void*))
{
	if (List == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}
	//将List 还原成 struct LList 数据类型
	struct LList * MyList = List;

	//待删除的结点
	struct LinkNode* pCurrent = MyList->pHeader->next;

	/* //方法1
	for(int i = 0; i < MyList->m_size ; i++)
	{
		if(Mycompare(pCurrent->data, data))
		{
			DeleteByPos_LinkList(List, i);
			break;
		}
		pCurrent = pCurrent->next;
	}
	*/

	//方法2
	//删除结点的前驱结点
	struct LinkNode* pPrev = MyList->pHeader;
	for (int i = 0; i < MyList->m_size; i++)
	{
		if (Mycompare(pCurrent->data, data))
		{
			//建立关系
			pPrev->next = pCurrent->next;

			free(pCurrent);
			pPrev = NULL;

			//更新链表长度
			MyList->m_size--;
			break;
		}
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
}

//清空链表
void clean_LinkList(LinkList List)
{
	if (List == NULL)
	{
		return;
	}
	//将List 还原成 struct LList 数据类型
	struct LList * MyList = List;

	//待删除的结点
	struct LinkNode* pCurrent = MyList->pHeader->next;
	//删除结点的后继结点
	struct LinkNode* pNext = pCurrent;

	for (int i = 0; i < MyList->m_size ; i++)
	{
		pNext = pCurrent->next;

		free(pCurrent);

		pCurrent = pNext;
		
	}
	MyList->pHeader->next = NULL;
	MyList->m_size = 0;
}

//返回链表长度
int  size_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return -1;
	}

	struct LList * Mylist = list;

	return Mylist->m_size;
}

//销毁链表
void destroy_Linklist(LinkList list)
{
	if (list == NULL)
	{
		return;
	}

	//清空链表
	clean_LinkList(list);

	free(list);
	list = NULL;
}

main.c

#include "LinkList.h"

//测试
struct Person {
	char name[128];
	int age;
};

void myPrintPerson(void * data)
{
	struct Person * p = data;
	printf("name:  %s \t, age: %d\n" , p->name , p->age);
}

int Mycompare(void* data1, void* data2)
{
	struct Person * p1 = data1;
	struct Person * p2 = data2;
	return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

int main(void)
{
	//准备数据
	struct Person p1 = { "亚瑟", 18 };
	struct Person p2 = { "妲己", 20 };
	struct Person p3 = { "安琪拉", 19 };
	struct Person p4 = { "凯", 21 };
	struct Person p5 = { "孙悟空", 999 };
	struct Person p6 = { "李白", 999 };

	//初始化链表
	LinkList MyList = init_LinkList();
	
	//插入数据
	insert_LinkList(MyList, 0, &p1);
	insert_LinkList(MyList, 0, &p2);
	insert_LinkList(MyList, -1, &p3);
	insert_LinkList(MyList, 0, &p4);
	insert_LinkList(MyList, 1, &p5);
	insert_LinkList(MyList, 0, &p6);
	//遍历
	foreach_LinkList(MyList, myPrintPerson);
	printf("链表长度为:%d\n", size_LinkList(MyList));
	printf("------------------------------\n");
	// 李白 凯 孙悟空 妲己 亚瑟 安琪拉

	//删除链表 按位置删除
	DeleteByPos_LinkList(MyList, 1);
	//遍历
	foreach_LinkList(MyList, myPrintPerson);
	printf("链表长度为:%d\n", size_LinkList(MyList));
	printf("------------------------------\n");
	// 李白 孙悟空 妲己 亚瑟 安琪拉

	//删除链表 按位置删除
	struct Person pD = { "亚瑟", 18 };
	DeleteByVal_LinkList(MyList, &pD, Mycompare );
	//遍历
	foreach_LinkList(MyList, myPrintPerson);
	printf("链表长度为:%d\n", size_LinkList(MyList));
	printf("------------------------------\n");
	// 李白 孙悟空 妲己  安琪拉
	
	//测试清空
	clean_LinkList(MyList);

	//返回链表长度
	printf("链表长度为:%d\n", size_LinkList(MyList));

	//销毁
	destroy_Linklist(MyList);

	system("pause");
	return EXIT_SUCCESS;
}

输出效果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值