内核链表 例题 C语言实现

news2025/1/8 11:50:13

问题:

将下面的数据节点信息转换为链表结构,并遍历输出。要求根据type的值来决定val的类型。

type为1代表bool类型,2代表整形,3代表浮点型。无需解析文本,直接赋值形成节点即可。


代码:

list.c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include "list.h"

/*定义Value共用体*/
typedef union{
    bool bool_val;
    int int_val;
    float float_val;
} Value;

/*定义Data结构体*/
typedef struct Data{
    int key;
    int type;
    Value val;
    struct list_head list;
}Data;
/*初始化结点*/
Data create_node(int key,int type,char* val_str){
    Data node;

    node.key = key;
    node.type = type;
    
    /*根据类型存数据*/
    switch(type){
    case 1:
        node.val.bool_val = atoi(val_str) != 0;
        break;
    case 2:
        node.val.int_val = atoi(val_str);
        break;
    case 3:
        node.val.float_val = atof(val_str);
        break;
    default:
        printf("error\n");
        exit(1);
    }
    node.list.next = NULL;
    node.list.prev = NULL;
    return node;
}
/*输出结点*/
void print_node(Data *tmp){
    switch(tmp->type){
        case 1:
            printf("key = %d,val = %s\n",tmp->key,(tmp->val.bool_val == 0 ? "false":"true"));;
            break;
        case 2:
            printf("key = %d,val = %d\n",tmp->key,tmp->val.int_val);
            break;
        case 3:
            printf("key = %d,val = %.2f\n",tmp->key,tmp->val.float_val);
            break;
        default:
            printf("print error\n");
            exit(1);
        }
}

int main(){
    struct list_head head;
    INIT_LIST_HEAD(&head);

    Data data1,data2,data3;
    /*初始化结点*/
    data1 = create_node(1,2,"10");
    data2 = create_node(2,1,"0");
    data3 = create_node(3,3,"22.5");

    /*把结点加入链表*/
    list_add(&data1.list, &head);
    list_add(&data2.list, &head);
    list_add(&data3.list, &head);

    struct list_head *pos;
    Data *tmp;

    printf("init list\n");

    /*遍历链表*/
    list_for_each(pos, &head){
        tmp = list_entry(pos, Data, list); // 获取当前结点
        print_node(tmp); // 输出结点
    }
    printf("\n");

    puts("del last\n");
    pos = get_last(&head);
    list_del(pos); // 删除末尾结点

    printf("after del:\n");

    /*遍历链表*/
    list_for_each(pos, &head){
        tmp = list_entry(pos, Data, list); // 获取当前结点
        print_node(tmp); // 输出结点
    }
    printf("\n");
}
list.h
/***********************************************************************************
Copy right:	Coffee Tech.
Author:			wanghan
Version:		V1.0
Date:			2025-1
Description:	从linux内核抽出来链表,可以做通用链表使用,可保留
***********************************************************************************/

#ifndef _LIST_H
#define _LIST_H

//定义核心链表结构
struct list_head
{
	struct list_head *next, *prev;
};

//链表初始化
static inline void INIT_LIST_HEAD(struct list_head *list)
{
	list->next = list;
	list->prev = list;
}

//插入结点
static inline void __list_add(struct list_head *new_list,
							  struct list_head *prev, struct list_head *next)
{
	next->prev = new_list;
	new_list->next = next;
	new_list->prev = prev;
	prev->next = new_list;
}

//在链表头部插入
static inline void list_add(struct list_head *new_list, struct list_head *head)
{
	__list_add(new_list, head, head->next);
}

//尾部插入结点
static inline void list_add_tail(struct list_head *new_list, struct list_head *head)
{
	__list_add(new_list, head->prev, head);
}

static inline void __list_del(struct list_head *prev, struct list_head *next)
{
	next->prev = prev;
	prev->next = next;
}

//删除任意结点
static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
}

//是否为空
static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}

//得到第一个结点
static inline struct list_head *get_first(const struct list_head *head)
{
	return head->next;
}

//得到最后一个结点
static inline struct list_head *get_last(const struct list_head *head)
{
	return head->prev;
}

static inline void __list_splice(const struct list_head *list,
								 struct list_head *prev,
								 struct list_head *next)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;

	first->prev = prev;
	prev->next = first;

	last->next = next;
	next->prev = last;
}

/**
 * list_splice - join two lists, this is designed for stacks
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(const struct list_head *list,
							   struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head, head->next);
}

/**
 * list_splice_tail - join two lists, each list being a queue
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice_tail(struct list_head *list,
									struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head->prev, head);
}

//后序(指针向后走)遍历链表
#define list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)

//前序(指针向前走)遍历链表
#define list_for_each_prev(pos, head) \
	for (pos = (head)->prev; pos != (head); pos = pos->prev)

#define offsetof_list(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)

#define list_entry(ptr, type, member) ({			\
    const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
    (type *)( (char *)__mptr - offsetof_list(type,member) ); })

#endif

输出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言结构体数组

上次我们讲解了结构体&#xff0c;这里还有高级应用就是结构体数组&#xff08;集合的集合&#xff09; &#xff08;这里提醒一句&#xff0c;想要在北京参加NCRE考试的朋友们今天开始报名了&#xff09; 定义 还是拿上回那个学生数据的结构体 typedef struct {int year;i…

深入了解 ES6 Map:用法与实践

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

在Vue3项目中使用svg-sprite-loader

1.普通的svg图片使用方式 1.1 路径引入 正常我们会把项目中的静态资源放在指定的一个目录&#xff0c;例如assets,使用起来就像 <img src"../assets/svgicons/about.svg" /> 1.2封装组件使用 显然上面的这种方法在项目开发中不太适用&#xff0c;每次都需…

谷歌SEO真的需要很长时间吗?

关键在于策略与执行力&#xff0c;很多人在刚开始做谷歌SEO时&#xff0c;都会产生一种挫败感&#xff0c;觉得排名变化太慢&#xff0c;看不到显著效果。这其实是因为SEO本身是一项需要时间的工作&#xff0c;特别是在竞争激烈的领域。但如果策略得当、执行力强&#xff0c;时…

耐高压26V输入5V升压充电8.4V芯片

HU6877作为一款集成了26V高耐压保护的5V升压至8.4V两节锂电池充电管理IC&#xff0c;凭借其高效升压、智能充电管理、多重安全保护及高耐压特性&#xff0c;在高端手电筒、便携式医疗设备、无人机等领域展现出了广泛的应用前景。本文将详细探讨HU6877的技术特点、工作原理、应用…

linuxCNC(六)配置LinuxCNC完成伺服控制

这里写目录标题 1、 cia402安装2、找伺服描述文件&#xff08;xml&#xff09;3、配置ethercat-config.xml3.1、打开hal-cia402/example/ethercat-conf.xml3.2、修改 ethercat-conf.xml文件中vid"0x000116c7" pid"0x003e0402"3.3、其他参数&#xff0c;根据…

【数据结构】链表(2):双向链表和双向循环链表

双向链表&#xff08;Doubly Linked List&#xff09; 定义&#xff1a; 每个节点包含三个部分&#xff1a; 数据域。前驱指针域&#xff08;指向前一个节点&#xff09;。后继指针域&#xff08;指向下一个节点&#xff09;。 支持从任意节点向前或向后遍历。 #define dat…

指针 const 的组合

1、首先来了解一下常量 const int num 5&#xff1b; 那么num的值是5&#xff0c; num的值不可修改 2、来了解一下指针 int value 5; int* p &value; 我喜欢吧指针和类型放一起&#xff0c;来强调p是一个指针类型&#xff0c; 而赋值的时候就得赋值一个int类型的地址…

Tableau数据可视化与仪表盘搭建-数据可视化原理

目录 内容 做个小实验 数据如何变成图表 1 2 维度和度量定义 3 度量映射图形&#xff0c;维度负责区分 1 可映射的数据类型 2 可视化字典 3 使用Tableau将数据变成图表(Tableau可视化原理) 1 2 拖拽 3 具体操作 4 总结 内容 点击左下角的工作表 tableau可以自动…

【WRF数据准备】气象驱动数据-ERA5是否需要单层位势数据?

目录 气象驱动数据-ERA5是否需要单层位势(Geopotential)数据?位势(Geopotential)输入的重要性Vtable的管理参考气象驱动数据-ERA5是否需要单层位势(Geopotential)数据? 本博客参考WRF论坛中讨论内容-How to use ERA5 Data From Copernicus Database,总结位势(Geopot…

用ResNet50+Qwen2-VL-2B-Instruct+LoRA模仿Diffusion-VLA的论文思路,在3090显卡上训练和测试成功

想一步步的实现Diffusion VLA论文的思路&#xff0c;不过论文的图像的输入用DINOv2进行特征提取的&#xff0c;我先把这个部分换成ResNet50。 老铁们&#xff0c;直接上代码&#xff1a; from PIL import Image import torch import torchvision.models as models from torch…

常见中间件漏洞(tomcat,weblogic,jboss,apache)

先准备好今天要使用的木马文件 使用哥斯拉生成木马 压缩成zip文件 改名为war后缀 一&#xff1a;Tomcat 1.1CVE-2017-12615 环境搭建 cd vulhub-master/tomcat/CVE-2017-12615 docker-compose up -d 1.首页抓包&#xff0c;修改为 PUT 方式提交 发送shell.jsp 和木马内容 …

嵌入式科普(26)为什么heap通常8字节对齐

目录 一、概述 二、newlibc heap 2.1 stm32cubeide .ld heap 2.2 e2studio .ld heap 三、glibc源码 3.1 Ubuntu c heap 四、总结 一、概述 结论&#xff1a;在嵌入式c语言中&#xff0c;heap通常8字节对齐 本文主要分析这个问题的分析过程 二、newlibc heap newlibc…

大数据-240 离线数仓 - 广告业务 测试 ADS层数据加载 DataX数据导出到 MySQL

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

CTF杂项——[NSSRound#4 SWPU]Pixel_Signin

得到一个像素点 提取像素点 脚本 from PIL import Image result open(1.txt,w) img Image.open("Pixel_Signin.png") img img.convert(RGB) for i in range(31):for j in range(31):r,g,b img.getpixel((j,i))print(r,g,b,end ,fileresult) 运行之后得到 把它…

Harmony开发【笔记1】报错解决(字段名写错了。。)

在利用axios从网络接收请求时&#xff0c;发现返回obj的code为“-1”&#xff0c;非常不解&#xff0c;利用console.log测试&#xff0c;更加不解&#xff0c;可知抛出错误是 “ E 其他错误: userName required”。但是我在测试时&#xff0c;它并没有体现为空&#xff0c;…

springCloudGateWay使用总结

1、什么是网关 功能: ①身份认证、权限验证 ②服务器路由、负载均衡 ③请求限流 2、gateway搭建 2.1、创建一个空项目 2.2、引入依赖 2.3、加配置 3、断言工厂 4、过滤工厂 5、全局过滤器 6、跨域问题

韩国机场WebGIS可视化集合Google遥感影像分析

目录 前言 一、相关基础数据介绍 1、韩国的机场信息 2、空间数据准备 二、Leaflet叠加Google地图 1、叠加google地图 2、空间点的标记及展示 3、韩国机场空间分布 三、相关成果展示 1、务安国际机场 2、有同类问题的机场 四、总结 前言 12月29日8时57分左右务安国际机…

电子电气架构 --- 设计车载充电机的关键考虑因素

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

python进阶06:MySQL

课后大总结 Day1 一、数据库命令总结 1.连接数据库 连接数据库进入mysql安装目录打开bin文件夹&#xff0c;输入cmd(此命令后无分号)mysql.exe -u root -ppassword命令后输入密码:root 设置密码set passwordpassword("root123"); 查看所有数据库show databases; …