本文继上一篇:STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID
本文介绍在运用RC522模块时,运用链表结构存储数据的操作
Let's go!
(一)顺序表是最常用且最简单的一种数据结构。简而言之,一个线性表是n个数据元素的有限序列,至于每个数据元素的具体含义,在不同的情况下各不相同,它可以是一个数或一个符号,也可以是一页书,甚至其他更复杂的信息。在稍复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表称为文件。
(二)线性结构分类:连续存储【数组】、离散存储【链表】
(三)线性表的链式存储结构的特点是用一组任意的存储单眼存储线性表的元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的存储位置)。这两部分信息组成数据元素ai的存储映像,称为结点(node)。它包括两个域,其中存储数据元素的信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链。n个节点链结成一个链表,即为线性表的链式存储结构。又由于此链表的每一个结点中只包含一个指针域,故又称线性链表或单链表。
(四) 简单的说:n个结点离散分配,彼此用指针相连,每个结点有且只有一个前驱结点有且只有一个后继结点,尾结点没有后继结点。每个结点可以访问下一个结点,无法访问上一个点。
(五)关于链表的相关术语:
首结点:第一个有效结点
尾结点:最后一个有效结点
头结点:第一个结点,首结点前的那个结点。头结点不存放有效数据,它存在的目的是为了方便对链表的操作
头指针:指向头结点的指针链表
尾指针:指向尾指针的指针变量
(6)总而言之,链表比数组存储更灵活,所以用链表
//==============================================================================
//读取卡的类型
//读取卡的ID号
//==============================================================================
void ReaderCard(void)
{
int temp_value=0;
if(PcdRequest(PICC_REQALL,Temp)==MI_OK) //选卡
{
if(Temp[0]==0x04&&Temp[1]==0x00)
printf("\r\n卡类型:MFOne-S50\r\n");
else if(Temp[0]==0x02&&Temp[1]==0x00)
printf("MFOne-S70");
else if(Temp[0]==0x44&&Temp[1]==0x00)
printf("MF-UltraLight");
else if(Temp[0]==0x08&&Temp[1]==0x00)
printf("MF-Pro");
else if(Temp[0]==0x44&&Temp[1]==0x03)
printf("MF Desire");
else
printf("Unknown");
if(PcdAnticoll(UID)==MI_OK) //防冲撞
{
// printf("Card Id is:");
// /* 获取卡值 */
// printf("%d%d%d%d\r\n",UID[0],UID[1],UID[2],UID[3]);
temp_value = ((UID[0]>>4)*10+(UID[0]&0x0f));//原卡ID太长,取原卡ID的高几位作为新卡ID
if(Car_D==1&&Car_R==1) //正常读取模式
{
if(1==Read_Car(pHead,temp_value))
printf("欢迎光临ID:%d\r\n",temp_value);
else printf("当前卡ID未录入,通行失败!\r\n");
}
if(Car_D==1&&Car_R==0) //录入模式
{
Insert_Car(pHead,temp_value);
Output_Car(pHead) ;
}
if(Car_D==0&&Car_R==1) //删除模式
{
Delete_Car(pHead,temp_value);
}
}
}
}
#ifndef __CHAIN_H
#define __CHAIN_H
struct My_Car //结构体,目前只存放卡ID,更多数据类型可自行添加
{
int Car_ID;//卡ID
// char Name[10];
};
typedef struct Node//结点
{
struct My_Car st;//数据域
struct Node *pNext;//指针域
}NODE, *PNODE;
/*
NODE等价于struct My_Car st
PNODE等价于struct Node *pNext
*/
PNODE First_Car(void); //创建头结点
void Output_Car(PNODE pHead); //打印全部已录入的卡ID
void Insert_Car(PNODE pHead,int temp_value);//录入一个卡ID(传入参数temp_value为读出的卡ID)
int Read_Car(PNODE pHead,int temp_value); //读取链表是否存在此卡ID(传入参数temp_value为读出的卡ID)
int Search_Car(PNODE pHead,int temp_value );//定位某个卡ID在链表的位置(传入参数temp_value为读出的卡ID)
void Delete_Car(PNODE pHead,int temp_value);//删除掉此卡ID(传入参数temp_value为读出的卡ID)
#endif
#include "Chain.h"
#include "stdlib.h"
#include "stdio.h"
//这个函数用来创建头结点,头结点不存放有效数据,仅供后续使用链表方便
PNODE First_Car(void)
{
NODE stu;//定义一个结构体
//定义一个头结点并且为头结点分配内存
PNODE pHead = (PNODE)malloc(sizeof(NODE));
//判断内存是否为空
if(NULL == pHead) return 0;
//定义一个指向头结点的指针
PNODE pTail = pHead;
pTail->pNext = NULL;//清空指针域
stu.st.Car_ID=0;
//为新节点分配内存
PNODE pNew = (PNODE)malloc(sizeof(NODE));
//判断内存是否为空
if(NULL == pNew) return 0;
//初始化结点的数据域
pNew->st = stu.st;
//将新结点挂到老结点后
pTail->pNext = pNew;
//清空新结点的指针域
pNew->pNext = NULL;
//将pTail移到新结点上
pTail = pNew;
return pHead;
}
//录入卡ID
void Insert_Car(PNODE pHead,int temp_value)
{
if( 1==Read_Car(pHead,temp_value) )
printf("卡ID已存在,请勿重复录入!\r\n");
else
{
PNODE p = pHead; //定义一个指向头结点的指针
NODE stu; //定义一个结构体
p = p->pNext;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
printf("动态内存分配失败,程序终止!\r\n");
else
{ stu.st.Car_ID=temp_value;
pNew->st = stu.st;
pNew->pNext = p->pNext;
p->pNext = pNew;
}
printf("卡ID:%d 录入成功!\r\n",temp_value);
}
}
//读取卡号存储数据
int Read_Car(PNODE pHead,int temp_value )
{
PNODE p = pHead->pNext; //定义一个指向头结点后一个结点的指针
while(NULL != p)
{
if(p->st.Car_ID==temp_value)
{
break;
}
p = p->pNext;
}
if(NULL == p) return 0;
else return 1;
}
//定位卡ID在链表的位置
int Search_Car(PNODE pHead,int temp_value )
{
PNODE p = pHead->pNext;//定义一个指向头结点后一个结点的指针
int i=0;
while(NULL != p)
{
i++;
if(p->st.Car_ID==temp_value) break;
p = p->pNext;
}
return i;
}
//删除卡ID
void Delete_Car(PNODE pHead,int temp_value)
{
if( 0==Read_Car(pHead,temp_value) )
printf("卡ID不存在,删除失败!\r\n");
else
{
PNODE p = pHead;//定义一个指向头结点的指针
int i = 0;
int pos;
pos=Search_Car(pHead,temp_value );//获取要删除的卡ID在链表位置
while(NULL != p->pNext && ipNext;
i++;
}
if(NULL == p->pNext || i>pos-1)
{
printf("没找到需要删除的卡ID编号!\r\n");
}
PNODE q = p->pNext;
p->pNext = q->pNext;
free(q);
q = NULL;
printf("你已经成功删除卡ID:%d !\r\n",temp_value);
}
}
//打印输出全部卡号
void Output_Car(PNODE pHead)
{
PNODE p = pHead->pNext->pNext;//p指向头结点的后一个结点
printf("当前录入卡号有:");
while(NULL != p)
{
printf("%d、", p->st.Car_ID);
p = p->pNext;
}
printf("\r\n");
}