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 listprintf("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.取出对象jsoncJSON *json = cJSON_Parse(buf);//2.取出json下的ver和logincJSON *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下节点datanode = 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和typevalue1k = cJSON_GetObjectItem(value,"key");value2t = cJSON_GetObjectItem(value,"type");//malloc指针nodestruct 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.构造根节点rootcJSON * root = cJSON_CreateObject();// 2.给 root 添加 ver 的子节点,子节点类型是 stringcJSON_AddItemToObject(root, "ver", cJSON_CreateString("1.0"));// 3.给 root 添加 login 的子节点,子节点类型是 objectcJSON * 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和typecJSON_AddItemToObject(tmp_son, "key", cJSON_CreateNumber(tmp->key));cJSON_AddItemToObject(tmp_son, "type", cJSON_CreateNumber(tmp->type));// 7.3 往数组data字节点中增加val// 7.3.1 处理valchar 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));