初学链表,单向链表运用

该文描述了一个C语言实现的链表数据结构,用于存储学生姓名、学号和成绩。链表通过结构体定义,包括成员变量和指针。文章详细介绍了链表的初始化、动态内存分配、创建新条目、删除指定条目以及通过串口发送数据的函数。此外,还讨论了释放内存时的注意事项,确保释放后的安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果有错误和不恰当的地方,还请大神指出,谢谢~~~

功能实现:创建成绩表(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文件代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值