zoukankan      html  css  js  c++  java
  • No!No!No! It's not fashion!

    还记得搞怪的hold住姐Miss Lin么,对于人们常规的行为,Miss Lin会挑起夸张的眉毛说:"Oh my God, it's not fashion!"。如果程序员圈子里有位Miss Lin,对于一些功能的实现,她会认为哪些编码实现方法是not fashion的,哪些是fashion的呢?

    下面示例中,循规蹈矩先生编码但求功能实现,喜好使用常规方法,hold住姐实现功能的同时,不忘fashion一把。

    问题一:事件触发库函数支持三种事件类型:IO事件(包括读/写)、信号和超时事件,请编码定义以上事件类型并说明使用方法。

    循规蹈矩先生

    1.事件类型定义

    #define EV_TIMEOUT 1                  
    #define EV_READ 2
    #define EV_WRITE 3
    #define EV_SIGNAL 4

    2.使用方法

    有效性判断:

    if(ev_events >= EV_TIMEOUT && ev_events <= EV_SIGNAL){……}

    根据事件类型进行事件处理:

    if(ev_events == EV_READ){……}


    No! No! No! it's not fashion!


    **Miss Lin**

    1.定义事件类型:

    #define EV_TIMEOUT 0x01
    #define EV_READ   0x02
    #define EV_WRITE   0x04
    #define EV_SIGNAL  0x08

    有效性判断:

    if (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)){……}

    根据事件类型进行事件处理:

    if (ev->ev_events & EV_READ){……}


    Miss Lin语:

    Well,well,well.循规蹈矩先生的方法 is very sample,让人一看就明白,but it's not fashion!

    假如一个事件既包含“读”,又包含“写”,是否还要添加一个EV_READ_WRITE宏?Think about that!

    But 使用我的方法就不一样了,EV_READ|EV_WRITE 即可表示一个读写事件。该方法同样适用于其他事件组合,比如一个限时的读事件可以这样定义:EV_READ|EV_TIMEOUT,so easy!

    另外,通过位运算,可以很方便地对事件类型进行操作:

    //添加超时类型
    ev_events |= EV_TIMEOUT;
    //删除超时类型
    ev_events &= ~EV_TIMEOUT;

    使用bit指示状态,通过位运算操作状态值——要知道,fashion也讲求节约!

    问题二:定义链表数据结构并编写相关操作函数。

    循规蹈矩先生

    //结点结构定义
    typedef struct _LIST_NODE{
         void* pdata;
         struct _LIST_NODE* next;
    }LIST_NODE;
    //链表结构定义
    typedef struct _LIST_HEAD{
         LIST_NODE* first;
    }LIST_HEAD;
    //头部插入结点函数
    void list_insert_head(LIST_HEAD* head, LIST_NODE* node){
        node->next = head->first;
        head->first = node;
    }


    No! No! No! it's not fashion!


    **Miss Lin**

    //链表头定义宏
    #define
    SLIST_HEAD(name, type) \
    struct name { \
    struct type *slh_first; /* first element */ \
    }
    //链表元素定义宏
    #define SLIST_ENTRY(type) \
    struct { \
     struct type *sle_next; /* next element */ \
    }
    //链表初始化
    #define SLIST_INIT(head) do {                       \
        (head)->slh_first = NULL;                   \
    } while (/*CONSTCOND*/0)
    //头部插入结点宏
    #define SLIST_INSERT_HEAD(head, elm, field) do {            \
        (elm)->field.sle_next = (head)->slh_first;          \
        (head)->slh_first = (elm);                  \
    } while (/*CONSTCOND*/0)


    Miss Lin语:

    Fashion是什么?to be different! 提到宏的使用,很多程序员能列出一堆缺点,比如展开容易出错、不方便调试,但是恰当地使用宏可以带来很多好处,以上方法相比函数的实现,运行效率更高(哪怕只是一点点地提升)。最最关键的一点,it's cool!
    以上关于链表的宏定义使用方法如下:

    //定义链表结点
    struct
    SLIST_ITEM{
    int value;
    SLIST_ENTRY(SLIST_ITEM) entries;
    };
    SLIST_HEAD(,SLIST_ITEM) slist_head;  //声明链表头结点
    struct SLIST_ITEM* item;
    SLIST_INIT(&slist_head);  //初始化链表
    item = malloc(sizeof(struct SLIST_ITEM));
    item->value = 10;
    SLIST_INSERT_HEAD(&slist_head, item, entries);  //在头部插入元素


    问题三:编写接口函数,分别实现动态数组和队列插入和删除。

    循规蹈矩先生

    //list.h
    struct
    _List;
    typedef struct _List List;
    //链表接口函数
    void list_insert(void* thiz, size_t index, void* data);
    void list_delete(void* thiz, size_t index);

    //darray.h
    struct _DArray;
    typedef struct _DArray DArray;
    //动态数组接口函数
    void darray_insert(void* thiz, size_t index, void* data);
    void darray_delete(void* thiz, size_t index);


    No! No! No! it's not fashion!


    **Miss Lin**

    //container.h
    struct container{
      void (*insert) (void*, size_t index, void* data);
      void (*delete) (void*, size_t index);
    };

    //list.h
    static void list_insert(void* thiz, size_t index, void* data);
    static void list_delete(void* thiz, size_t index);
    struct container list_container = {list_insert, list_delete};

    //darray.h
    static void darray_insert(void* thiz, size_t index, void* data);
    static void darray_delete(void* thiz, size_t index);
    struct container darray_container = {darray_insert, darray_delete};


    Miss Lin语:

    Fashion! Can you see that ?! 增加container结构、利用回调函数,实现了统一的接口,static关键字实现了隐藏,使用方法如下:

    struct container* containerp = &list_container;
    containerp->insert(……);
    containerp->delete(……);

     
    上文模仿Miss Lin的语气介绍了以下内容:

    1. 使用二进制和位运算定义类型;
    2. 使用宏定义结构和函数;
    3. 使用回调函数提供统一接口。

    ”循规蹈矩先生”们应向"Miss Lin"学习,学习她追求与众不同的精神。对于编程,除了常规的编码实现方法,我们还应多思考能同样达到目的的方法。通过不断思考与总结,逐渐提高编程技能。

  • 相关阅读:
    drupal drush 在windows下的安装和配置
    Drupal 7 配置ckeditor和ckfinder编辑器实现图片上传--不用wysisyg
    阿里云Centos配置iptables防火墙
    25个最常用的iptables策略
    防简单攻击iptables策略
    iptables防DDOS攻击和CC攻击设置
    Linux Web服务器网站故障分析常用的命令
    Linux/CentOS防CC攻击脚本
    Map字符串类型去掉空格处理
    读文件字节流大小的动态设置
  • 原文地址:https://www.cnblogs.com/bangerlee/p/2237800.html
Copyright © 2011-2022 走看看