内核链表、JSON的序列化与反序列化

news2024/11/24 2:56:31

     1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

     2) 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

     3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节{trailing padding}。

 

 1

 内核链表:

链表:增删改查

单向链表 双向链表。。。

线性数据结构:

数组、链表、堆、栈

数组:连续(物理空间),随机存取,插入删除慢,复杂,会整体偏移

链表:连续(逻辑),无法随机存取,插入和删除方便

堆:malloc()  free()

栈:先进后出

队列:先进先出

非线性:

树、图

树:文件系统(开发)

图:路径规划(百度地铁、高德、路由器(路由算法))

 

 插入的代码是重点!!!!

 

#include <stdio.h>
#include <string.h>
#include "list.h"

struct student
{
    int age;
    char name[64];
    struct list_head list;
};

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

    struct student stu1;
    strcpy(stu1.name, "zhangsan");
    stu1.age = 1;

    struct student stu2;
    strcpy(stu2.name, "lisi");
    stu2.age = 2;

    struct student stu3;
    strcpy(stu3.name, "wangwu");
    stu3.age = 3;


    list_add(&stu1.list, &head);  //插入
    list_add(&stu2.list, &head);
    list_add(&stu3.list, &head);

    struct list_head *pos;
    struct student *tmp;

    printf("init list\n");
    list_for_each(pos, &head)   //遍历
    {
        tmp = list_entry(pos, struct student, list);  
        //list 为 struct list_head 的名字  struct list_head list
        printf("name = %s, age = %d\n", tmp->name, tmp->age);
    }
    printf("\n");

    pos = get_first(&head);
    tmp = list_entry(pos, struct student, list);
    printf("first is %s\n\n", tmp->name);

    pos = get_last(&head);
    tmp = list_entry(pos, struct student, list);
    printf("last is %s\n\n", tmp->name);

    puts("del last");
    list_del(pos);

    printf("after del:");
    list_for_each(pos, &head)
    {
        tmp = list_entry(pos, struct student, list);
        printf("%d ", tmp->age);
    }
	puts("\n");
}
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "list.h"
typedef int BOOL;
union val
    { 
    BOOL b_val; 
    int i_val;   
    float f_val;  
    };
struct data
{  
   
    int key;
    int type;
    union val val_t;
    struct list_head list;
};

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

    struct data data1;
    data1.key = 1;
    data1.type = 2;
    data1.val_t.b_val = 10;

    struct data data2;
    data2.key = 2;
    data2.type = 1;
    data2.val_t.i_val = 0;

    struct data data3;
    data3.key = 3;
    data3.type = 3;
    data3.val_t.f_val = 22.5;


    list_add(&data1.list, &head);
    list_add(&data2.list, &head);
    list_add(&data3.list, &head);

    struct list_head *pos;
    struct data *tmp;

    printf("init list\n");
    list_for_each(pos, &head)
    {
        tmp = list_entry(pos, struct data, list);
        if(1==tmp->type)
        {
            printf("%d %d %d\n",tmp->key,tmp->type,tmp->val_t.b_val);
        }
        else if(2==tmp->type)
        {
            printf("%d %d %d\n",tmp->key,tmp->type,tmp->val_t.i_val);
        }
       else if(3==tmp->type)
        {
            printf("%d %d %.2f\n",tmp->key,tmp->type,tmp->val_t.f_val);
        }
    }
	puts("\n");
}

JSON

是一种数据交换格式

在JSON之前用XML来传递数据,XML很复杂,雅虎的高级架构师道格拉斯发明JSON,是JavaScript的一个子集。

json数据类型

  • number:和JavaScript的number完全一致;相当于C中的int类型(数字型)
  • boolean:就是JavaScript的true或false;相当于c++中的bool类型
  • string:就是JavaScript的string;相当于c++的string类型(字符串)
  • null:就是JavaScript的null;相当于C的NULL类型
  • array:就是JavaScript的Array表示方式——[];相当于C的数组
  • object:就是JavaScript的{ ... }表示方式。相当于C++的类或者C的结构体(对象)

注意:json的数据类型在源码实现中和具体的编程语言有关,比如boolean在C中并没有相应的类型,C相关的实现库可能会用0和1表示。

格式规范


●json以大括号起始和结尾
●内容都是以键值对的形式存在
●所有的键都是字符串
●值的类型不一定,属于JavaScript 的基本数据类型
●每个键值对以,分割
●最后一个键值对不加逗号

{
  "name": "小明",   //键值  "name"键都是字符串
  "age": 14,       //number
  "gender": true,   //boolean
  "height": 1.65,   
  "grade": null,    //null
  "middle-school": "\"W3C\" Middle School",
  "skills": [     //array
    "JavaScript",
    "Java",
    "Python",
    "Lisp"
  ]
}

序列化与反序列化

 序列化:生成JSON字符串,多为发送端-----可以理解为利用程序生成Json字符串的过程。

反序列化:解析JSON字符串,拿到数据,多为接收端---可以理解为利用程序将已有的Json字符串解析出我们需要的值的过程。

使用cjson

cjson是个库

{
	"ver": "1.0",
	"login": {
		"user": "zhangsan",
		"pwd": "123456"
	},
	"data": [{
      "key": 1,
      "type": 2,
      "val": "10"
    },
    {
      "key": 2,
      "type": 1,
      "val": "0"
    },
    {
      "key": 3,
      "type": 3,
      "val": "22.5"
    }
	]
}

反序列化:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h"
#include "list.h"

typedef int BOOL;
union val
    { 
    BOOL b_val; 
    int i_val;   
    float f_val;  
    };
struct data
{  
   
    int key;
    int type;
    union val val_t;
    struct list_head list;
};

int main(void)
{
    char buf[800]="";
    FILE *fp = fopen("./test.json","r");
    if(fp == NULL){
        perror("fopen err\n");
        return -1;
    }
    printf("fopen success\n");

    fread(buf,800,1,fp); 

    //1.取出对象json
    cJSON *json = cJSON_Parse(buf);
    
    //2.取出json下的ver和login
    cJSON *node = NULL;
    node = cJSON_GetObjectItem(json,"ver");
    if(node == NULL){
        printf("ver node == NULL\n");
    }
    else{
        printf("found ver node\n");
    }
    printf("ver: %s\n",node->valuestring);
    cJSON *node2 = NULL;
    node2 = cJSON_GetObjectItem(json,"login");
    if(node2 == NULL){
        printf("login node == NULL\n");
    }
    else{
        printf("found login node\n");
    }

    //3.从login节点取出user和key子节点
    node = cJSON_GetObjectItem(node2,"user");
    printf("user: %s\n",node->valuestring);
    node = cJSON_GetObjectItem(node2,"pwd");
    printf("pwd: %s\n",node->valuestring);
    
    //4.取出json下节点data
    node = cJSON_GetObjectItem(json, "data");

    //5.链表初始化
    struct list_head head;
    INIT_LIST_HEAD(&head);

    //6.遍历出数组加到链表
    cJSON *value = NULL;
    cJSON *value1k = NULL;
    cJSON *value2t = NULL;
    cJSON *value3v = NULL;
    int size = cJSON_GetArraySize(node);
    int i;
    for(i=0;i<size;i++)
    {
        //取出i个节点
        value = cJSON_GetArrayItem(node,i);
        //从i个节点取出key和type
        value1k = cJSON_GetObjectItem(value,"key");
        value2t = cJSON_GetObjectItem(value,"type");
        
        //malloc指针node
        struct data *node = (struct data *)malloc(sizeof(struct data));

        //用指针赋值
        node->key = value1k->valueint;
        node->type = value2t->valueint;

        value3v = cJSON_GetObjectItem(value,"val");
        switch (value1k->valueint){
            case 1:
            node->val_t.i_val = atoi(value3v->valuestring);
            break;
            case 2:
            node->val_t.b_val = atoi(value3v->valuestring);
            break;
            case 3:
            node->val_t.f_val = atof(value3v->valuestring);
            break;
        }

        //7.加到链表存储
        list_add(&node->list,&head);
    }

    //8.遍历输出
    struct list_head *pos;
    struct data *tmp;
    printf("init list\n");
    list_for_each(pos, &head)
    {
        tmp = list_entry(pos, struct data, list);
        if(1==tmp->key)
        {
            printf("key:%d type:%d val:%d\n",tmp->key,tmp->type,tmp->val_t.i_val);
        }
        else if(2==tmp->key)
        {
            printf("key:%d type:%d val:%d\n",tmp->key,tmp->type,tmp->val_t.b_val);
        }
       else if(3==tmp->key)
        {
            printf("key:%d type:%d val:%.1f\n",tmp->key,tmp->type,tmp->val_t.f_val);
        }
    }


    return 0;
}


 

 序列化:

 
	
    // 1.构造根节点root
    cJSON * root =  cJSON_CreateObject();
 
    // 2.给 root 添加 ver 的子节点,子节点类型是 string
    cJSON_AddItemToObject(root, "ver", cJSON_CreateString("1.0"));
 
    // 3.给 root 添加 login 的子节点,子节点类型是 object
	cJSON * object1 =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "login", object1);
 
    // 4.给 login 节点添加 user 和 key 节点
    cJSON_AddItemToObject(object1, "user", cJSON_CreateString("zhangsan"));
    cJSON_AddItemToObject(object1, "key", cJSON_CreateString("123456"));
 
 
    // 5.创建数组节点
    cJSON *array  = cJSON_CreateArray();
    
	// 6.将数组data加入根节点中
    cJSON_AddItemToObject(root, "data", array);
 
    // 7.往data数组节点遍历增加项
    list_for_each(p, &head)
    {
        tmp = list_entry(p, struct data, list);
 
        // 7.1 创建数组data的子节点(此时还没放进数组data中)
        cJSON *tmp_son = cJSON_CreateObject();
        
        // 7.2 往数组data字节点中增加key和type
        cJSON_AddItemToObject(tmp_son, "key", cJSON_CreateNumber(tmp->key));
        cJSON_AddItemToObject(tmp_son, "type", cJSON_CreateNumber(tmp->type));
 
        // 7.3 往数组data字节点中增加val
        // 7.3.1 处理val
        char buf_tmp[32] = "";
        switch (tmp->type)
        {
        case 1:
            sprintf(buf_tmp, "%d", tmp->val.b);
            break;
        case 2:
            sprintf(buf_tmp, "%d", tmp->val.i);
            break;
        case 3:
            sprintf(buf_tmp, "%0.2f", tmp->val.f);
            break;
        }
        // 7.3.2 将处理好的val即string基本类型添加到数组data的字节点中
        cJSON_AddItemToObject(tmp_son, "val", cJSON_CreateString(buf_tmp));
 
        // 7.3.3 将字节点tmp_son增加到数组data中
        cJSON_AddItemToArray(array, tmp_son);
    }
 
    // 8.打印cJSON验证
    printf("\n打印Json字符串验证:\n");
    printf("%s\n", cJSON_Print(root));

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

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

相关文章

计算机组成原理(考研408)练习题#3

用于复习408或计算机组成原理期末考试。如有错误请在评论区指出。 So lets start studying with questions! それでは、問題の勉強を始めましょう&#xff01; 1. 定点整数原码编码[x]原1110100B 的真值为_________。 首先&#xff0c;1110100B是一个8位二进制数&#xff0c…

Spring Cloud Sleuth使用简介

Spring-Cloud Spring Cloud为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性Token、全局锁、决策竞选、分布式会话和集群状态)操作的开发工具。使用SpringCloud开发者可以快速实现上述这些模式。 SpringCloud Sleuth Distribu…

【0基础教程】Javascript 正则表达式里的分组捕捉 Capturing Groups 使用方法及原理

一、从最简单开始 现有一个字符串&#xff1a; “1-apple” 需要解析出 1 和 apple 来&#xff0c;对应的正则表达式很简单&#xff1a; ^(\d)-(.)$ 其中&#xff0c; ^ 表示字符串的开始&#xff0c;然后一个圆括号包裹的内容表示一个"组"&#xff1a;(\d) 表示一组…

【深度学习】2-1 神经网络 - 激活函数

激活函数 将输入信号的总和转换为输出信号&#xff0c;一般称为激活函数&#xff08;activation function&#xff09;。激活函数作用在于决定如何来激活输入信号的总和。 对激活函数&#xff0c;一般要求&#xff1a; 非线性&#xff1a;为提高模型的学习能力&#xff0c;如…

Nginx reuseport导致偶发性卡顿

背景 从2018年开始&#xff0c;我们有个业务陆续接到反馈 Nginx 线上集群经常出现不响应或者偶发性的“超慢”请求。这种卡顿每天都有少量出现。而只有多个集群中的一个出现&#xff0c;其他压力更大的集群皆未出现。 业务结构比较简单&#xff1a;LVS->Nginx->后端&…

Advanced-C.01.基础知识

C语言程序设计概述 一个简单句的C程序 #include <stdio.h> int main(){printf("This is a C program.\n");retrun 0; }C程序的执行过程 数据单位 bit&#xff1a;位&#xff0c;计算机中最小的数据单位Byte&#xff1a;字节&#xff0c;计算机中信息组织和存…

C++ 搜索二叉树

目录 C 搜索二叉树一. 介绍二.简单实现搜索二叉树1. 基本框架2. 插入节点a. 图示&#xff1a;b. 递归实现&#xff1a;c. 非递归&#xff1a; 3. 删除节点a. 图示&#xff1a;b. 递归实现&#xff1a;c. 非递归&#xff1a; 三. 小结 C 搜索二叉树 又名&#xff1a;二叉搜索树…

bean的三种实例化方式

实例化bean的三种方式&#xff0c;构造方法,静态工厂和实例工厂 构造方法实例化&#xff08;常用&#xff09; 步骤1&#xff1a;准备一个BookDao和BookDaoImpl类 public interface BookDao {public void save(); } ​ public class BookDaoImpl implements BookDao {public…

Vue中如何进行表单图片裁剪与预览

Vue中如何进行表单图片裁剪与预览 在前端开发中&#xff0c;表单提交是一个常见的操作。有时候&#xff0c;我们需要上传图片&#xff0c;但是上传的图片可能会非常大&#xff0c;这会增加服务器的负担&#xff0c;同时也会降低用户的体验。因此&#xff0c;我们通常需要对上传…

Python:关于flask框架的flask_scrip._compat

关于flask框架的flask_scrip._compat compat是什么源码Flask版本书写不同 compat是什么 compat 英文单词同胞的意思 compat的功能是在py的不同版本之间做兼容处理 一些py2/py3兼容性支持基于精简版的six&#xff0c;因此我们不必依赖于它的特定版本。 源码 # -*- coding: u…

使用芯片和贴片天线解决多频带射频问题

智能手机和可穿戴电子设备等手持和便携式无线产品依赖可置入设备的微型芯片、贴片和印制线天线。尽管这些小型器件解决了在小尺寸系统中携带多频带天线阵列的问题&#xff0c;但它们也引入了辐射效率下降、阻抗匹配以及与附近物体和人体的交互等相关问题。 为解决这些问题&…

ASO优化之如何降低应用的卸载率

不管是苹果应用商店&#xff0c;还是国内的安卓市场和国外的Google Play&#xff0c;拥有超过200万个应用&#xff0c;每个应用都面临着众多的竞争对手&#xff0c;当应用在承诺之后没有及时兑现可以提供的功能&#xff0c;就会面临被卸载的风险。 对应用在不同平台的应用商店…

chatgpt赋能python:Python数据类型的确定方法

Python数据类型的确定方法 在Python中&#xff0c;一个变量可以保存任何类型的数据。数据类型是指数据的种类和形式。在使用Python时&#xff0c;数据类型通常是自动推断的&#xff0c;但有时我们需要手动确定数据类型。本文介绍了Python中确定变量数据类型的几种方法。 使用…

如何部署免交互脚本

目录 一、免交互 什么是免交互 Here Document免交互 二、Expect概述 expect sed命令 三、如何用ssh实现免交互 四、监控硬盘实现免交互 五、创建硬盘分区如何实现免交互 一、免交互 什么是免交互 交互&#xff1a;需要人工发出指令&#xff0c;来控制程序的运行&…

走向实用的AI编解码

基于AI的端到端数据压缩方法受到越来越多的关注&#xff0c;研究对象已经包括图像、视频、点云、文本、语音和基因组等&#xff0c;其中AI图像压缩的研究最为活跃。图像编解码的研究和应用历史悠久&#xff0c;AI方法要达到实用&#xff0c;需要解决诸多问题才能取得相比于传统…

金融大数据平台是怎么构建的?

大数据对银行业的价值不言而喻。 在业务上,如何去挖掘客户的内在需求,为客户提供更有价值的服务是目前金融机构的战略转型和业务创新的关键。大数据技术正是金融机构深挖数据资产、实现差异化竞争、推动业务创新的重要工具。 在运营上,通过大数据应用和分析,金融机构能够定位…

利用事务消息实现分布式事务

什么是事务 什么是事务呢&#xff1f;事务是并发控制的单位&#xff0c;是用户定义的一个操作序列。有四个特性(ACID)&#xff1a; 原子性(Atomicity)&#xff1a; 事务是数据库的逻辑工作单位&#xff0c;事务中包括的诸操作要么全做&#xff0c;要么全不做。一致性(Consist…

深入探究kubernetes resources - Part 2

你以为CPU请求只是用来调度的吗&#xff1f; 再想一想。 引入 CPU 份额&#xff0c;并为消除限制奠定基础&#xff01; 了解 CPU 请求 在上一篇文章中&#xff0c;我谈到了 Kubernetes 资源管理的基础。 在这篇文章中&#xff0c;我们将深入探讨当我们将 CPU 请求配置到 pod 的…

3D建模Cocos Creator3D:发射器模块(ShapeModule)

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 发射器模块(ShapeModule) 公有属性&#xff1a; 属性作用position相对于挂载节点的位置rotation相对于挂载节点的旋转scale相对于挂载节点的缩放sphericalDirectionAmount表示当前…

ESP32(Micro Python)LVGL 两个动画程序

本次发布两个程序&#xff0c;仪表盘动画程序对刻度数量等参数进行调整&#xff0c;方便布置多个小尺寸仪表盘&#xff1b;进度条动画程序展示了多个进度条的排列方式。 仪表盘程序 import lvgl as lv import time from espidf import VSPI_HOST from ili9XXX import ili93…