本文继上一篇:STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID

本文介绍在运用RC522模块时,运用链表结构存储数据的操作

Let's go!


前言

(一)顺序表是最常用且最简单的一种数据结构。简而言之,一个线性表是n个数据元素的有限序列,至于每个数据元素的具体含义,在不同的情况下各不相同,它可以是一个数或一个符号,也可以是一页书,甚至其他更复杂的信息。在稍复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表称为文件。

(二)线性结构分类:连续存储【数组】、离散存储【链表】

(三)线性表的链式存储结构的特点是用一组任意的存储单眼存储线性表的元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的存储位置)。这两部分信息组成数据元素ai的存储映像,称为结点(node)。它包括两个域,其中存储数据元素的信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链。n个节点链结成一个链表,即为线性表的链式存储结构。又由于此链表的每一个结点中只包含一个指针域,故又称线性链表或单链表。

(四) 简单的说:n个结点离散分配,彼此用指针相连,每个结点有且只有一个前驱结点有且只有一个后继结点,尾结点没有后继结点。每个结点可以访问下一个结点,无法访问上一个点。

(五)关于链表的相关术语:

首结点:第一个有效结点
尾结点:最后一个有效结点

头结点:第一个结点,首结点前的那个结点。头结点不存放有效数据,它存在的目的是为了方便对链表的操作
头指针:指向头结点的指针链表
尾指针:指向尾指针的指针变量

(6)总而言之,链表比数组存储更灵活,所以用链表


1.较上一篇需改动的地方

2.代码实现思路

3.部分代码

(1)RC522读卡部分

//==============================================================================
//读取卡的类型
//读取卡的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");elseprintf("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的高几位作为新卡IDif(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);                      }}}
}

(2)链表操作函数.h文件代码

#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

(3)链表操作函数.c文件代码

#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 && i<pos-1)  //使指针p指向要删除结点的前一个结点{p = p->pNext;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");
}

4.实现效果

本例程源码下载:点击跳转

STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID(二)相关推荐

  1. STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件准备 (1)MFRC-522模块 (2)F1的板子,本例使用经典F103C8T6 (3)ST-li ...

  2. STM32系列(HAL库)——F103C8T6通过NRF24L01(2.4G)无线模块进行双机通信

    本文参考:STM32L051C8T6 HAL库 + nRF24L01 收发案例(硬件SPI通讯) 1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件 ...

  3. STM32系列(HAL库)——F103C8T6 通过GY906/MLX90614红外测温模块实现温度测量

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件准备 (1)GY-906-BCC红外测温模块 (2)F1的板子,本例使用经典F103C8T6 (3 ...

  4. STM32系列(HAL库)——F103C8T6通过SPI方式读写W25Q64—(Flash存储模块)

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件准备 (1)W25Q64模块 (2)F1的板子,本例使用经典F103C8T6 (3)ST-link ...

  5. STM32系列(HAL库)——F103C8T6点亮1.44寸TFT-LCD彩屏

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)中景园屏幕资料链接:点击跳转        提取码:8888 2.硬件准备 (1)1.44寸TFT彩屏 (2)F1的板子,本例使用经 ...

  6. STM32系列(HAL库)——F103C8T6使用SPI方式点亮OLED

    目录 1.软件准备 2.硬件准备 3.CubeMX配置 (1)芯片选择 (2)配置RCC.SYS.时钟树 (3)配置SPI (4)配置GPIO (5)生成代码工程 4.代码移植 (1)复制文件 (2) ...

  7. STM32系列(HAL库)——F103C8T6硬件SPI点亮带字库OLED屏

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)程序:点击下载 2.硬件准备 (1)1.3寸带字库OLED 注意,成品模块无RES引脚,模块正常工作时RES置于高电平,成品模块是硬 ...

  8. STM32CubeMX | STM32 F1系列HAL库低功耗STOP和STANDBY模式唤醒(RTC时钟唤醒+外部中断唤醒示例)

    STM32CubeMX | STM32 F1系列HAL库低功耗STOP和STANDBY模式唤醒(RTC时钟唤醒+外部中断唤醒示例) 目录 STM32CubeMX | STM32 F1系列HAL库低功耗 ...

  9. 【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(二)

    前言: 本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 上一讲我们说了CubeMX配置SDRAM的一些基本配置,还有FMC跟SDRAM的讲解,这一讲我们 ...

最新文章

  1. PyTorch中的MIT ADE20K数据集的语义分割
  2. SQL语句中 LIMIT与OFFSET
  3. php常用插件,关于PHP网站编程中常用插件的使用——w3cdream|前端学习-开发
  4. visio思维导图模板_如何下载思维导图模板?在线教你找精美漂亮的思维导图
  5. ARM 编译选项的默认关系 001
  6. 怎样利用商业智能软件实现业务目标
  7. cad计算机功能键,【答疑】Auto CAD2014计算器快捷键是什么呢?? - 视频教程线上学...
  8. MATLAB带通滤波器开始端和结尾端数据异常(解决的小技巧)
  9. linux如何禁用独立显卡驱动,Ubuntu中独立显卡不好用如何关闭独立显卡
  10. 隐马尔可夫模型(HMM:Hidden Markov Models)
  11. 孙鑫视频VC++深入详解学习笔记
  12. 20190527-陈静初-文件操作-笔记
  13. android jmf,基于JMF与Android的无线视频监控系统的设计与实现
  14. win10如何激活电脑系统
  15. 算法练习:Sequence II
  16. 鼠标变成方块而不是竖线
  17. Vue element怎么获取table表格当前行数据和索引值
  18. 视频禁止快进的解决方法
  19. 【荐书】C程序设计语言(第二版)
  20. ScriptManager的简单用法

热门文章

  1. 记一次线上启动war包 StackOverflowError
  2. 柯桥小学教师资格证考试:班级突发情况处理
  3. 正则表达式的介绍及应用
  4. 如何测试数字硅麦软件,硅麦克风技术规格及测试方法
  5. 基层管理之正负向激励
  6. MultiCD: 构建多重引导 CD 映像
  7. 《Learning Scrapy》(中文版)第10章 理解Scrapy的性能
  8. android 刷机原理,分区。
  9. 整合Mybatis、Servlet、Mysql、Axios、Filter、Session写一个入门级项目:非常适合初接触JavaWeb的小白白来进阶
  10. 监控POE供电交换机最大传输距离有多远?