#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;
}

文章图片
【简单的链表存储和搜索例子(完整的增删查改)】

文章图片
推荐阅读
- C语言学习|第十一届蓝桥杯省赛 大学B组 C/C++ 第一场
- 【C】题目|【C语言】题集 of ⑥
- 单片机|自学单片机好找工作吗(会单片机能找什么工作?)
- 单片机|keil把源代码生成lib的方法
- c语言|一文搞懂栈(stack)、堆(heap)、单片机裸机内存管理malloc
- c语言|C语言初期学习遇到的特殊点 【三子棋详解】【初学者福音,详细总结,复习能手】
- 笔记|C语言数据结构——二叉树的顺序存储和二叉树的遍历
- 个人理解|【C语言基础之类型转换】
- c语言|【C语言】自定义类型 结构体 枚举 联合
- 学习分享|【C语言函数基础】