如果有错误和不恰当的地方,还请大神指出,谢谢~~~
功能实现:创建成绩表(add,姓名,成绩,学号), 删除对应成绩单(del,姓名) ,
每次创建一条成绩信息,创建完成之后,通过串口将整体的成绩单发送出来,
1.创建所需结构体:里面包含姓名,成绩,学号等字段,还需要一个指向下一层结构体指针,此结构体指针将把所有任务串成一个链表
typedef struct list
{
char name[6]; /*此处字符串储存必须要用数组,如果用指针,将无法给他赋值*/
char student_number[9];
char score[2];
struct list *next;
}linked_list_body;
2.初始化:创建结构体变量,和结构体指针,
void init_linked_list(void)
{
linked_list_ptr = &linked_list_head; /*让结构体指针指向具体的地址,不让其成为野指针*/
linked_list_ptr->next = NULL;
}
3.申请空间:
申请空间用malloc()函数;rtos系统里面也有一个申请空间的函数pvPortMalloc()
static linked_list_body * Request_space(void)
{
linked_list_body * p;
p = (linked_list_body *)malloc(sizeof(linked_list_body)); /*申请一个空间,p指向这个空间的首地址*/
if(p == NULL) /*p为NULL,说明申请空间失败*/
{
usart1_send_string("Request space fail\r\n");
return NULL;
}
memset(p->name,0,sizeof(p->name)); /*将数据清空,*/
memset(p->name,0,sizeof(p->score));
memset(p->name,0,sizeof(p->student_number));
p->next = NULL; /*指向下一个的结构体指针为空,为了便于链表指向下一个任务使用*/
return p; /*返回p的首地址*/
}
4.创建链表任务:
接收数据格式:add,xiao1,10004896,91
bool create_list(uint8_t *dat) /* *dat指向串口接收数据buff首地址 */
{
linked_list_body * p;
linked_list_body * curr;
curr = linked_list_ptr;
p = Request_space(); /*将新建指针指向申请的空间的首地址*/
if(p == NULL)
{
printf((char *)"create fail\r\n");
return false;
}
memcpy(p->name,&dat[4],5); /*将名字复制到p空间里面的name数组里*/
memcpy(p->score,&dat[19],2); /*将成绩复制到p空间里面的name数组里*/
memcpy(p->student_number,&dat[10],8); /*将学号复制到p空间里面的name数组里*/
while(curr->next != NULL) /*寻找链表尾端,*/
{
curr = curr->next;
}
p->next = NULL; /*将p->next指向Null,便于下次寻找链表尾端*/
curr->next = p; /*将链表尾端指向新创建的任务首地址,添加任务成功*/
return true;
}
5.删除任务;释放空间用free()函数; rtos系统里面也有一个释放空间的函数pvPortMalloc()
void delect_list(uint8_t *dat)
{
linked_list_body * p;
linked_list_body * delect = NULL;
p = linked_list_ptr; /*指向链表首地址*/
while(p != NULL)
{
if(memcmp(&p->next->name[0],&dat[0],5) == 0) /*表头不进行任务创建,所以从表头的next开始进行判断*/
{
delect = p->next; /*获取需要删除任务的首地址*/
p->next = p->next->next; /*将指向需要删除节点的指针指向下一个节点*/
delect->next = NULL; /*将此节点完全从链表中移除*/
free(delect); /*释放此节点*/
delect = NULL; /*将释放空间的指针指向空地址*/
break;
}
p = p->next;
}
}
6.free()函数运用: free()函数释放空间,不会把结构体指针里面的指针指向的空间释放,只会将这个结构体指针指向的空间释放;释放空间并不是把指针指向的空间真的释放了,而是将这个空间变成野空间,当下次分配空间时,可能会把这个空间分配给其他指针,但此指针依然时指向这个空间,并且可以对这个空间进行操作,所以释放空间之后需要将此结构体指针置空,防止这块空间分配给别的指针使用时,此结构体指针改变此空间的内容
7.实际效果
新增:
删除
具体代码:
hal_linked_list.c文件代码
/* Includes ------------------------------------------------------------------*/
#include "hal_linked_list.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "hal_usart.h"
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef struct list
{
char name[6];
char student_number[9];
char score[2];
struct list *next;
}linked_list_body;
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static linked_list_body * linked_list_ptr = NULL;
static linked_list_body linked_list_variate = {0};
/* Private function prototypes -----------------------------------------------*/
/* Private user code ---------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/**
* @brief 链表初始化
* @param d 指针
* @param deci 小数位
* @retval null
*/
void init_linked_list(void)
{
linked_list_ptr = &linked_list_variate;
linked_list_ptr->next = NULL;
}
/**
* @brief 创建链表 显示闪烁
* @param dat 指针
* @retval null
*/
static linked_list_body * Request_space(void)
{
linked_list_body * p;
p = (linked_list_body *)malloc(sizeof(linked_list_body));
if(p == NULL)
{
usart1_send_string("Request space fail\r\n");
return NULL;
}
memset(p->name,0,sizeof(p->name));
memset(p->name,0,sizeof(p->score));
memset(p->name,0,sizeof(p->student_number));
p->next = NULL;
return p;
}
/**
* @brief 创建链表 显示闪烁
* @param dat 指针
* @retval null
*/
bool create_list(uint8_t *dat)
{
linked_list_body * p;
linked_list_body * curr;
curr = linked_list_ptr;
p = Request_space();
if(p == NULL)
{
printf((char *)"create fail\r\n");
return false;
}
memcpy(p->name,&dat[4],5);
memcpy(p->score,&dat[19],2);
memcpy(p->student_number,&dat[10],8);
while(curr->next != NULL)
{
curr = curr->next;
}
p->next = NULL;
curr->next = p;
return true;
}
/*
* @brief delect_list 删除链表信息
* @param dat 指针
* @retval null
*/
void delect_list(uint8_t *dat)
{
linked_list_body * p;
linked_list_body * delect = NULL;
p = linked_list_ptr;
while(p != NULL)
{
if(memcmp(&p->next->name[0],&dat[0],5) == 0)
{
delect = p->next;
p->next = p->next->next;
delect->next = NULL;
free(delect);
delect = NULL;
break;
}
p = p->next;
}
}
/**
* @brief HAL_UART_TxCpltCallback 串口发送完成中断函数
* @param huart 指针
* @retval null
*/
void send_list_data(void)
{
linked_list_body *p;
p = linked_list_ptr;
while(p->next != NULL)
{
p = p->next ;
usart1_send_string(" ");
usart1_send_string(p->name);
usart1_send_string(" ");
usart1_send_string(p->student_number);
usart1_send_string(" ");
usart1_send_string(p->score);
usart1_send_string("\r\n");
}
}
app_main.c文件代码
/* Includes ------------------------------------------------------------------*/
#include "app_main.h"
#include "string.h"
#include "hal_usart.h"
#include "hal_linked_list.h"
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADD_DATA 0
#define DEL_DATA 1
#define ANALYSIS_FALSE 2
#define ADD_SUCCEED 0
#define DEL_SUCCEED 1
#define UNKNOWN_ERROR 2
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private user code ---------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/*add,姓名(5字节),成绩(2个字节),学号(8个字节)
del,
*/
/**
* @brief get_type获取链表类型(添加\删除)
* @param
* @retval HAL_OK 确认输入
*/
static uint8_t get_type(uint8_t *rxbuff)
{
if(memcmp(rxbuff,"add,",4) == 0 )
{
return ADD_DATA;
}
else if(memcmp(rxbuff,"del,",4) == 0 )
{
return DEL_DATA;
}
else
{
return ANALYSIS_FALSE;
}
}
/**
* @brief send_linked_list_result 发送执行链表任务结果
* @param
* @retval HAL_OK 确认输入
*/
static void send_linked_list_result(uint8_t result)
{
if(result == ADD_SUCCEED)
{
usart1_send_string("Successfully added:\r\n");
}
else if(result == DEL_SUCCEED)
{
usart1_send_string("Successfully delete:\r\n");
}
if(result == UNKNOWN_ERROR)
{
usart1_send_string("Unknown error occurred. Please send again\r\n");
return ;
}
usart1_send_string(" name student_number score\r\n");
send_list_data();
usart1_send_string("\r\n\r\n");
}
/**
* @brief list_task 显示闪烁
* @param null
* @retval null
*/
static void list_task(uint8_t *rxbuf)
{
uint8_t type = 0;
uint8_t result;
type = get_type(rxbuf);
if(type == ADD_DATA)
{
create_list(rxbuf);
result = ADD_SUCCEED;
}
else if(type == DEL_DATA)
{
delect_list(&rxbuf[4]);
result = DEL_SUCCEED;
}
else
{
result = UNKNOWN_ERROR;
}
hal_clear_usart1();
send_linked_list_result(result);
}
/**
* @brief total_task 总任务
* @param null
* @retval null
*/
void total_task(void)
{
uint8_t *rxbuff_p = NULL;
uint32_t rx_lenght = 0;
get_usart1_data(&rxbuff_p,&rx_lenght); /*获取串口接收数据和和接收数据长度*/
if(rx_lenght >= 21)
{
list_task(rxbuff_p);
}
}
main.c文件代码