链表是个好东西,可以实现很多东西,在Linux内核中发现一些宏的封装,感觉非常有意思,于是我也模仿了Linux内核的风格,实现了一个,先来看看头文件:

work.h

#ifndef __WORK_H

#define __WORK_H

#include

#include

#include

#include

#include

#define NR(x) (sizeof(x)/sizeof(x[0]))

typedef unsigned char u8 ;

typedef unsigned int u32;

typedef unsigned short u16;

typedef char s8 ;

typedef int s32;

typedef short s16;

typedef char * pchar;

typedef int * pint ;

typedef short * pshort ;

typedef void No_return;

//重定义函数指针的类型

typedef void (*work_fun)();

#define SUCCESS 0

#define ZERO 0

#define ERROR -1

//不需要排序

#define Not_sorted -1

//按编号从小到大

#define Positive 1

//按编号从大到小

#define Reverse 0

typedef struct __Work

{

//任务编号

//根据任务编号决定工作任务的优先级

//编号越小,优先级越高

s32 work_num ;

//任务名称

pchar work_name ;

//根据相应的任务名称,处理相应的任务

void (*work_handler)();

struct __Work *next ;

}work;

typedef work * _work ;

#define __INIT_WORK(_work)\

do {\

_work = Init_cwork(_work);\

} while (0)

//初始化任务,包括两步

//1.定义一个头指针

//2.初始化头节点

#define INIT_WORK(work_node) \

_work work_node = NULL ; \

__INIT_WORK(work_node);

//注册任务

//1.链表的尾插实现

#define REGISTER_WORK(__work,new_work) \

Register_work_fuc(__work,new_work);

//调度运行任务

//根据传入的direction决定任务的执行顺序,分三类情况

//1.Not_sorted : 不排序

//2.Positive : 按编号从小到大

//3.Reverse : 按编号从大到小

#define SCHEDULING_WORK(work_node,direction,array_size) \

Run_Priority_work(work_node,direction,array_size);

//销毁所有任务

#define DESTROY_WORK(work_node,array) \

work_node = Destroy_work(work_node ,array);

//初始化一个子任务

_work Init_cwork();

//创建一个子任务

_work create_cwork(s32 work_num,pchar work_name ,work_fun work_fuc) ;

//注册子任务

No_return Register_work_fuc(_work __work,_work new_work);

//查找子任务的编号

s32 Find_Work_Num(_work headler,s32 work_num);

//查找子任务的名称

pchar Find_Work_Name(_work headler,pchar work_name) ;

//执行子任务----根据任务名称来执行

s32 Run_work_for_work_name(_work headler,pchar work_name) ;

//销毁一个子任务

s32 Destroy_cwork(_work headler,pchar work_name);

//销毁全部任务

_work Destroy_work(_work headler,_work array);

//工作优先级调度执行--->工作编号小的优先级高,依次类推

s32 Run_Priority_work(_work handler,s32 direction,const s32 work_array_size) ;

#endif //__WORK_H头文件的实现很简单,就是定义一些基本的数据结构,宏,以及函数的声明。这里,我利用内核的编程思想,将子函数用几个宏封装起来。这里巧妙之处在于INIT_WORK这个宏,当我调用这个宏的时候,我只需要传一个变量名,它就帮我定义好了,然后再次调用__INIT_WORK子宏的时候会调用Init_cwork函数,完成头节点的初始化,并返回一个指针,这样,指针就初始化完毕了。内核链表,工作队列,也是利用很多这样的宏进行了封装,这样显得很方便。

下面看一下work.c的实现:

#include "work.h"

//初始化头节点

_work Init_cwork()

{

_work handler = NULL ;

handler = malloc(sizeof(work)) ;

assert(handler != NULL);

memset(handler,ZERO,sizeof(work));

handler->work_num = 0 ;

handler->work_name = NULL ;

handler->work_handler = NULL ;

handler->next = NULL ;

return handler ;

}

//创建一个子任务

_work create_cwork(s32 work_num , pchar work_name, work_fun work_fuc)

{

_work handler = NULL ;

handler = malloc(sizeof(work)) ;

assert(handler != NULL);

memset(handler,ZERO,sizeof(work));

handler->work_num = work_num ;

handler->work_name = work_name ;

handler->work_handler = work_fuc ;

handler->next = NULL ;

return handler ;

}

//注册任务,实际上就是尾插

No_return Register_work_fuc(_work __work,_work new_work)

{

assert(__work != NULL);

_work work_handler = __work ;

while(NULL != work_handler->next)

work_handler = work_handler->next ;

work_handler->next = new_work ;

}

//寻找任务的编号,就是结构体中的work_num

s32 Find_Work_Num(_work headler,s32 work_num)

{

assert(headler != NULL);

_work temp = headler->next ;

while(NULL != temp->next)

{

if(temp->work_num == work_num)

return temp->work_num ;

temp = temp->next;

}

return temp->work_num ;

}

//寻找任务的名称,就是结构体中的work_name

pchar Find_Work_Name(_work headler,pchar work_name)

{

assert(headler != NULL);

_work temp = headler->next ;

while(NULL != temp->next)

{

if(temp->work_name == work_name)

return temp->work_name ;

temp = temp->next;

}

return temp->work_name ;

}

//匹配对应的work_name,执行对应的任务(work_handler是一个函数)

s32 Run_work_for_work_name(_work headler,pchar work_name)

{

assert(headler != NULL);

_work temp = headler->next ;

while(NULL != temp->next)

{

if(temp->work_name == work_name){

temp->work_handler();

return SUCCESS;

}

temp = temp->next;

}

if(temp->work_name == work_name){

temp->work_handler();

return SUCCESS ;

}

printf("not this work , return ERROR!\n");

return ERROR;

}

//匹配对应的work_num,执行对应的任务(work_handler是一个函数)

static s32 Run_work_for_work_num(_work headler,s32 work_num)

{

assert(headler != NULL);

_work temp = headler->next ;

while(NULL != temp->next)

{

if(temp->work_num == work_num){

temp->work_handler();

return SUCCESS;

}

temp = temp->next;

}

if(temp->work_num == work_num){

temp->work_handler();

return SUCCESS ;

}

printf("not this work , return ERROR!\n");

return ERROR;

}

//对任务编号进行排序(正向,反向,不排)

static No_return Sort_work_num(s32 *buf, s32 len ,int direction)

{

s32 min;

s32 index;

s32 i, j , n;

if(direction == Positive)

{

for(i = ZERO; i < len - 1; i++)

{

min = buf[i];

index = i;

for(j = i; j < len; j++)

{

if(buf[j] < min)

{

min = buf[j];

index = j;

}

}

buf[index] = buf[i];

buf[i] = min;

}

}

else if(direction == Reverse)

{

for(i = 0 ; i < len ; i++)

{

for(j = 0 ; j < len ; j++)

{

if(buf[i] < buf[i+1])

{

n = buf[i] ;

buf[i] = buf[i+1] ;

buf[i+1] = n ;

}

}

}

}

else

{

return ;

}

}

//执行任务

s32 Run_Priority_work(_work handler,s32 direction,const s32 work_array_size)

{

s32 count = 0 ;

s32 i ;

assert(handler != NULL);

_work temp = handler->next ;

s32 Curent_node_Array[work_array_size];

while(temp != NULL){

Curent_node_Array[count] = temp->work_num ;

temp = temp->next ;

if(count < work_array_size)

count++ ;

}

Sort_work_num(Curent_node_Array,NR(Curent_node_Array),direction) ;

for(i = 0 ; i < NR(Curent_node_Array) ; i++)

Run_work_for_work_num(handler,Curent_node_Array[i]);

return SUCCESS ;

}

//根据work_name销毁子任务

s32 Destroy_cwork(_work headler,pchar work_name)

{

assert(headler != NULL);

_work temp = headler ;

_work temp_header_prev = NULL ;

while(NULL != temp->next)

{

temp_header_prev = temp ;

temp = temp->next ;

if(temp->work_name == work_name)

{

if(temp->next != NULL)

{

temp_header_prev->next = temp->next ;

free(temp);

temp = NULL ;

}

else

{

temp_header_prev->next = NULL ;

free(temp);

temp = NULL ;

}

return SUCCESS ;

}

}

printf("Not Work node\n");

return ERROR ;

}

//销毁所有的任务

_work Destroy_work(_work headler,_work array)

{

s32 i ;

assert(headler != NULL);

_work temp = headler ;

for(i = ZERO ; i < NR(array) ; i++)

Destroy_cwork(headler,array[i].work_name);

headler = NULL ;

return headler ;

}基本设计思想,运用了单链表的尾插,删除,遍历,查找等。

接下来看一下测试结果:test_work.c

#include

#include "work.h"

void work1()

{

printf("hello world! \n");

}

void work2()

{

printf("hello kitty! \n");

}

void work3()

{

printf("hello debug! \n");

}

work work_Register[] = {

{3,"hello world",work1},

{1,"hello kitty",work2},

{2,"hello debug",work3},

};

int main(void)

{

s32 i ;

INIT_WORK(work_node);

for(i = ZERO ; i < NR(work_Register) ; i++)

{

REGISTER_WORK(work_node , create_cwork(work_Register[i].work_num ,work_Register[i].work_name , work_Register[i].work_handler));

}

SCHEDULING_WORK(work_node,Positive,NR(work_Register));

DESTROY_WORK(work_node,work_Register);

printf("work_node:%p\n",work_node);

return 0 ;

}运行结果:

调用SCHEDULING_WORK这个宏的时候,根据传入的为Positive,那么链表会进行排序,最终根据编号从小到大输出。

于是,上面的结果为:

hello kitty

hello debug

hello world

我们看到Android的expr语言中有这样一个函数,它其实是将这些函数全部存在一个fn_table的结构体数组里。

当然下面我们就会看到它使用realloc进行分配空间,然后再将数据放到这个结构体数组里。

这个fn_entries就类似是一个引用计数,这样,每次调用RegisterFunction,传入名称和函数,调用一次,引用计数加一,就把数据存到结构体数组里面去了,这不就是典型的线性表嘛。

// -----------------------------------------------------------------

// the function table

// -----------------------------------------------------------------

static int fn_entries = 0;

static int fn_size = 0;

NamedFunction* fn_table = NULL;

void RegisterFunction(const char* name, Function fn) {

if (fn_entries >= fn_size) {

fn_size = fn_size*2 + 1;

fn_table = realloc(fn_table, fn_size * sizeof(NamedFunction));

}

fn_table[fn_entries].name = name;

fn_table[fn_entries].fn = fn;

++fn_entries;

}那么这个表肯定也是一个数据结构:

typedef struct {

const char* name;

Function fn;

} NamedFunction;其中Function是一个重定义的函数指针,实现如下:

typedef struct {

int type;

ssize_t size;

char* data;

} Value;

typedef Value* (*Function)(const char* name, State* state,

int argc, Expr* argv[]);下面应用它的时候,expr语言中实现了一个函数,对函数进行注册操作:

void RegisterBuiltins() {

RegisterFunction("ifelse", IfElseFn);

RegisterFunction("abort", AbortFn);

RegisterFunction("assert", AssertFn);

RegisterFunction("concat", ConcatFn);

RegisterFunction("is_substring", SubstringFn);

RegisterFunction("stdout", StdoutFn);

RegisterFunction("sleep", SleepFn);

RegisterFunction("less_than_int", LessThanIntFn);

RegisterFunction("greater_than_int", GreaterThanIntFn);

}然后调用FinishRegistration进行排序

static int fn_entry_compare(const void* a, const void* b) {

const char* na = ((const NamedFunction*)a)->name;

const char* nb = ((const NamedFunction*)b)->name;

return strcmp(na, nb);

}

void FinishRegistration() {

qsort(fn_table, fn_entries, sizeof(NamedFunction), fn_entry_compare);

}设计思想与这个类似,上面写的工作任务用的是链式存储,而这里直接用结构体数组进行管理。

c语言用户注册用链表,基于C语言链表实现的工作任务注册与执行相关推荐

  1. linux c语言 信号,linux下基于C语言的信号编程实例

    搜索热词 本文实例讲述了linux下基于C语言的信号编程方法.分享给大家供大家参考.具体如下: #include #include #include #include #include void si ...

  2. r语言 线性回归 相关系数_基于R语言的lmer混合线性回归模型

    原文 基于R语言的lmer混合线性回归模型​tecdat.cn 混合模型适合需求吗? 混合模型在很多方面与线性模型相似.它估计一个或多个解释变量对响应变量的影响.混合模型的输出将给出一个解释值列表,其 ...

  3. go语言打印日期_基于 Go 语言开发在线论坛(八):消息、视图及日期时间本地化...

    我们接着上篇在线论坛的进度,由于之前所有页面和消息文本都是英文的,而我们开发的应用基本都是面向中文用户的,所以需要对项目进行本地化,今天正好借着这个入门项目给大家介绍下如何在 Go Web 应用中进行 ...

  4. c语言编程TLC2543AD采集,基于C语言的89C51与TLC2543AD转换器的驱动程序的设计 实训报告...

    电子信息技术综合实训报告 竞赛题名称:基于C语言的89C51与TLC2543AD转换器的驱动程序的设计 队员名称: 评阅人签名:设计思路描述: 设计思路: 硬件部分基于80C51单片机和TLC2543 ...

  5. c语言五子棋学年论文,基于c语言五子棋小游戏生本科论文.doc

    基于c语言五子棋小游戏生本科论文 五子棋小游戏 需求分析 现在有越来越多的人使用电脑,而且五子棋的受众广泛但实体棋操作较为繁琐且平时较难实现,所以电脑版的五子棋游戏应运而生.大家对于这个小游戏的需求如 ...

  6. c语言 字数统计 字符串,基于C语言的字数统计

    摘要:字数统计是文档处理中经常要用到的功能,这其中要包括英文单词.数字和中文等,而且又要和全角或半角的标点符号进行区分,故此在中英文混合文件中进行准确的字数统计也是有一定难度的.这里提出了一种较好的字 ...

  7. c语言图书管理系统解析,基于C语言的图书管理系统的设计与实现解析.doc

    毕业论文 题目:基于C语言的图书管理系统的设计与实现 英文题目:Design and Implementation of Books Management System Based on C Lang ...

  8. 基于c语言的物业管理系统设计,基于C#语言的小区物业管理系统的设计与实现

    摘要: 随着人们生活水平和消费水平的不断提高,人们在追求物质生活的同时,更注重生活的质量,小区物业管理作为一种服务行业,与人们的生活息息相关,是人们生活质量的最基本需求.因此,小区物业管理系统的研究和 ...

  9. r语言pls分析_基于R语言的PLS算法的实现解读.pptx

    基于R语言的PLS算法的实现及研究 目录 使用的开发工具 偏最小二乘的设计思想 基于R语言.MATLAB的偏最小二乘的实现 通径分析 测定系数 实验分析 使用的开发工具 R 语言(R是用于统计分析.绘 ...

  10. c语言编写订货系统,基于C语言的仓库订货系统的仿真.doc

    基于C语言的仓库订货系统的仿真 本科毕业论文(设计.创作) 题目: 基于C语言的仓库订货系统的仿真 学生姓名: 学号: 所在系院: 信息与通信技术系 专业: 电子信息工程 入学时间: 2010 年 9 ...

最新文章

  1. 【iCore4 双核心板_FPGA】例程八:乘法器实验——乘法器使用
  2. php学习之------[运算符相关概念]
  3. 视频 | BIM数据中心模型
  4. linux查看目录下 开头,Linux下ls如何看到.开头的文件
  5. python基于web可视化_python可视化(转载)
  6. Linux内存管理:函数调用图谱-1
  7. 【SQLServer】将Job运行结果发送电子邮件通知用户
  8. cef 加载flash 弹框_cef 3.2357之后加载flash的方法
  9. EasyPR--开发详解
  10. 象棋程序 android,中国象棋人机对弈程序在Android系统上的设计与实现
  11. 记python opencv的一次恶搞
  12. 元气骑士远程联机(仅安卓)
  13. image target behaviour 和image target的关系_Behance大神为你揭秘任天堂、Target的UI为何这样设计?...
  14. 简单理解目标检测的IOU究竟是什么
  15. 服务器控件与客户端控件
  16. 【按键精灵学习记录】以DOTA2人机为例
  17. 这个横行霸道的美食,也是中秋节的一大特色,我用Python爬取京东1546条大闸蟹商品数据带大家看看
  18. 每日力扣009——575. 分糖果(OnO1)
  19. 5G网络部署行业应用的关键使能技术
  20. Java Applet实现五子棋游戏

热门文章

  1. java select 不是date,iPhonedateselect器,而不是键盘?
  2. mysql索引久了需要重新_mysql索引更新要多久
  3. rshd: 0826-813 Permission is denied.
  4. 5.1 损坏联机日志的恢复方法
  5. 动态打印sql,服务报was not registered for synchronization because synchronization is not active
  6. Fragment学习3--底部tab布局
  7. 做三维模型_这几款倾斜实景三维裸眼3D采集软件你了解吗?
  8. linux ubuntu mysql 安装_1.MySQL的安装(linux Ubuntu环境下)
  9. 线性表的链式存储-单链表
  10. [洛谷P3242] [HNOI2015]接水果