简单的链表存储和搜索例子(完整的增删查改)

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

//链表结点
typedef struct Item ListItem;
struct Item
{
	char *epc,
		 *name;
	ListItem *next;
};

ListItem* creatList();
ListItem* createItem(char* epc, char* name);
int insert(ListItem *listHead, ListItem *newItem);
void removeAll(ListItem *listHead); 
int removeItem(ListItem *listHead, ListItem *item);
int search(ListItem *list, char tools[], void (*callback)(ListItem *list, ListItem *item));
void readList(ListItem *list);

//搜索到之后的回调事件实现:
void callbackForSearch(ListItem *list, ListItem *item)
{
	printf("找到了epc为%s的name:%s\n", item->epc, item->name);
}

//搜索到对应条目就干掉的回调实现 
void callbackForDel(ListItem *list, ListItem *item)
{
	removeItem(list, item);
}

//搜索并修改的回调实现 
void callbackForModify(ListItem *list, ListItem *item)
{
	printf("找到了epc为%s的name:%s,需要修改为:\n", item->epc, item->name);		
	{
		int choice = 0;
		printf("1为修改该条目的epc,0为修改该条目的name:");
		scanf("%d", &choice);
		if(choice == 1)
		{
			printf("请输入对应该name的新epc:");
			free(item->epc);
			scanf("%s",item->epc); 
			printf("修改完毕\n");
		}else if(choice == 0)
		{
			printf("请输入对应该epc的新name:");
			free(item->name);
			scanf("%s",item->name); 
			printf("修改完毕\n");		
		}else
		{
			printf("功能选择错误\n");
		}
	} 
}

int main()
{	
	int i;
	//创建链表
	ListItem *list = creatList();
	//创造一些例子数据,你按着步骤加结点就可以了
	for(i=0; i<9; i++)
	{
		//这里只是用来方便我做循环,你可以直接对字符指针赋值的
		char *epc = (char*)malloc(sizeof(char) * 3);  
		char *name = (char*)malloc(sizeof(char) * 3);
		epc[0] = '0' + i;
		epc[1] = '1' + i;
		epc[2] = '\0';
		name[0] = 't';
		name[1] = 'o';
		name[2] = '0' + i;
		name[3] = '1' + i;
		name[4] = '\0';
		insert(list, createItem(epc, name));
	}
	printf("\n全部读取一次:\n"); 
	readList(list);
	printf("\n修改条目\n");
	search(list, "56", callbackForModify);
	printf("\n全部再读取一次:\n"); 
	readList(list);
	printf("\n读取对应条目:\n"); 
	search(list, "2301568710100101", callbackForSearch);
	printf("\n删除对应条目:\n"); 
	search(list, "2301568710100101", callbackForDel);
	printf("\n全部再读取一次:\n"); 
	readList(list);
	printf("\n删除全部:\n"); 
	removeAll(list);
	return 0;
}

//建表函数
//返回 表头地址
ListItem* creatList()
{
	ListItem *head;
	head = (ListItem*)malloc(sizeof(ListItem));
	head->epc = NULL;
	head->name = NULL;
	head->next = NULL;
	return head;
}

//创建内存空间存放条目的函数
//返回 条目在内存里面的地址
ListItem* createItem(char* epc, char* name)
{
	ListItem* item = (ListItem*)malloc(sizeof(ListItem));
	//记得创建完结点之后要设置next为空,否则影响insert函数算法的运作
	item->epc = epc;
	item->name = name;
	item->next = NULL;
	return item;
}

//插入条目到指定表中函数
int insert(ListItem *listHead, ListItem *newItem)
{
	//利用static int做第一次读表判断
	static int firstIn = 1;	
	ListItem *temp = listHead;
	if(temp == NULL)
		return -1;
	while(temp->next != NULL)
		temp = temp->next;
	//如果表被清空了就重新设置为第一次进入 
	if(temp->epc == NULL && temp->name == NULL && temp->next == NULL && temp == listHead)
		firstIn = 1;
	//如果是表头而且第一次读,就直接读结点赋值
	if(temp == listHead && firstIn)
	{
		//赋值newItem的内容地址进已经有内存空间但没内容的表头结点,免得浪费该结点
		temp->epc = newItem->epc;
		temp->name = newItem->name;
		//对firstIn取反,下一次就不会进入这个分支(static变量声明周期和程序周期相同,要记得函数执行完毕firstIn值还保留的)
		firstIn = !firstIn;
		//newItem利用完了,销毁掉
		free(newItem);
	}
	//不是表头就添加进表未的下一个的位置
	else
		temp->next = newItem;
	//师弟你要记住这里不能继续free掉newItem。因为上面的那个分支是结点已经保存好了newItem结构体地址里面的内容的地址
	//但这里是newItem的地址赋值给temp的下一个指针,你一旦free掉,那么想读这个内存地址的数据的时候,数据杰不存在了
	//会产生非法访问内存错误,所以这里不能free也没必要free
} 

//遍历并读出整个表的函数
void readList(ListItem *list)
{
	if(list == NULL) return ;
	printf("结点数据epc: %s,name:%s\n", list->epc, list->name);	
	readList(list->next);
}

//清空整个表,包括表头,请重新使用createList来得到一个新表,使用原表头指针保存的内存地址将引发内存访问权限错误 
void removeAll(ListItem *listHead)
{
	if(listHead == NULL) return;
	ListItem *next = listHead->next;
	printf("预备删除节点的内存地址: address:%d\n", listHead);
	free(listHead->epc);
	free(listHead->name);
	//memset(listHead, NULL, sizeof(ListItem)); //将这块内存填0 
	free(listHead);
	removeAll(next);
}

//按内存地址删除某一个条目 
int removeItem(ListItem *listHead, ListItem *item)
{
	ListItem *before = listHead, *cursor = listHead; 
	printf("将要删除的结点数据epc: %s,name:%s\n", item->epc, item->name);
	//如果是头结点
	if(listHead == item)
	{
		//复制第二个节点的数据到第一个节点,并且free掉第二个结点,一三节点相连 
		ListItem *copySecNext = item->next->next;
		free(item->epc);
		free(item->name);
		item->epc = item->next->epc;
		item->name = item->next->name; 
		free(item->next);
		item->next = copySecNext;
		return ;
	} 
	//其他结点: 
	while(cursor != NULL)
	{
		if(cursor == item)
		{
			before->next = item->next;
			free(item);
			break;		
		}
		before = cursor;
		cursor = cursor->next;	
	}
}

//搜索对应epc的条目 
int search(ListItem *list, char tools[], void (*callback)(ListItem *list, ListItem *item))
{
	ListItem *temp = list;
	int i, j, toolsLength = strlen(tools);
	printf("\n你想搜索的epc组合为(两个字节为一个搜索项):%s\ntools数组长度%d\n", tools, toolsLength);
	while(temp->next != NULL)
	{
		for(i=0,j=1; i < toolsLength,j < toolsLength; i+=2,j+=2)
		{
			if(temp->epc[0] == tools[i] && temp->epc[1] == tools[j])
			{
				callback(list, temp);
			}
		}
		temp = temp->next;
	}
	return 0;
}





猜你喜欢

转载自blog.csdn.net/cjzjolly/article/details/78617849