• 用链表解决if语句过多的问题(C/C++实现)


    起因

    http://www.cnblogs.com/code-style/p/3499408.html

    设计模式的解决方案(基于python语言)

    http://www.cnblogs.com/code-style/p/3501713.html

    http://www.cnblogs.com/code-style/p/3502105.html

    用设计模式实现完以后我突然发现,所谓的设计模式其实在C语言里不就是链表吗?当前节点能处理就处理不能处理让下一个节点处理,不多说,上代码

    消息类的设计


     message.h

    #ifndef MESSAGE_H
    #define MESSAGE_H
    
    #define TRUE 1
    #define FALSE 0
    
    typedef struct {
        int sender;
        int isSend;
        int isCharge;
        char date[8];
    }Message;
    
    Message * makeMessage(const int sender, const char *date);
    void setSendFlag(Message * const message);
    void setChargeFlag(Message * const message);
    int isSameDate(const Message * const message, const char * const date);
    char * format(const Message * const message);
    const char * boolStr(const int value);
    
    #endif

    message.c

    #include <assert.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include "message.h"
    
    Message * makeMessage(const int sender, const char *date)
    {
        Message *message = (Message*)malloc(sizeof(Message));
        assert(message != NULL);
        message->sender   = sender;
        message->isSend   = FALSE;
        message->isCharge = FALSE;
        strncpy(message->date, date, 8);
        return message;
    }
    
    const char * boolStr(const int value)
    {
        return value == TRUE ? "TRUE" : "FALSE";
    }
    
    char * format(const Message * const message)
    {
        #define BUF_SIZE 1024
        static char buffer[BUF_SIZE];
        memset(&buffer, 0, BUF_SIZE);
        snprintf((char*)&buffer, BUF_SIZE, "Message <%d isSend:%s isCharge:%s>
    ", 
            message->sender, boolStr(message->isSend), boolStr(message->isCharge));
        return (char*)buffer;
    }
    
    void setSendFlag(Message * const message)
    {
        message->isSend = TRUE;
    }
    
    void setChargeFlag(Message * const message)
    {
        message->isCharge = TRUE;
    }
    
    int isSameDate(const Message * const message, const char * const date)
    {
        if (strncmp(message->date, date, 8) == 0)
        {
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }

    testMessage.c

    #include <stdio.h>
    #include "message.h"
    #include "gtest/gtest.h"
    
    TEST(MESSAGE,makeMessage){
        Message *message = makeMessage(1,"20131212");
        EXPECT_EQ(1, message->sender);
        EXPECT_STREQ("Message <1 isSend:FALSE isCharge:FALSE>
    ", format(message));
    }

    链表类的实现


     node.h

    #ifndef NOTE_H
    #define NOTE_H
    
    typedef struct Node{
        void *ptr;
        struct Node *next;
    }Node;
    
    Node *makeListWithArray(void *array[], int length);
    void foreach(Node *list, void (*process) (Node *));
    #endif

    node.c

    #include <stdlib.h>
    #include <assert.h>
    #include "node.h"
    
    Node *makeListWithArray(void *array[], int length)
    {
        int i;
        Node *last = NULL;
    
        assert(array != NULL && length > 0);
        for(i = length - 1; i >= 0; i--)
        {
            Node *node = (Node*)malloc(sizeof(Node));
            node->ptr  = array[i];
            node->next = last;
            last = node;
        }
    
        return last;
    }
    
    void foreach(Node *list, void (*process) (Node *))
    {
        Node *current = NULL;
    
        assert(list != NULL && process != NULL);
        for(current = list; current != NULL; current = current->next)
        {
            process(current);
        }
    }

    testNode.c

    #include <stdio.h>
    #include "node.h"
    #include "gtest/gtest.h"
    
    void printNode(Node *node)
    {
        static int i = 0;
        int data[] = {1,2,3};
        EXPECT_EQ(data[i], *(int*)node->ptr);
        i++;
    }
    
    TEST(NODE,makeListWithArray){
        int i;
        int data[] = {1,2,3};
        void *aSet[] = {&data[0], &data[1], &data[2]};
        Node *list = makeListWithArray(aSet, 3);
        foreach(list, printNode);
    }

    程序入口实现(main.c)


    #include <stdio.h>
    #include <string.h>
    #include "message.h"
    #include "node.h"
    
    # define FALSE 0
    # define TRUE  1
    
    typedef int BOOL;
    typedef BOOL (*FuncIsAllowSend)(Message *, Node*);
    
    
    BOOL isAllowSendCheckDate(Message *message, Node *node)
    {
        FuncIsAllowSend isAllowSend = NULL;
    
        if(strcmp(message->date, "20130101") == 0)
        {
            return FALSE;
        }
        
        isAllowSend = (FuncIsAllowSend) node->next->ptr;
        return isAllowSend(message, node->next);
    }
    
    
    BOOL isAllowSendCheckWhiteList(Message *message, Node *node)
    {
        FuncIsAllowSend isAllowSend = NULL;
    
        if(message->sender == 10)
        {
            return TRUE;
        }
    
        isAllowSend = (FuncIsAllowSend) node->next->ptr;
        return isAllowSend(message, node->next);
    }
    
    BOOL isAllowSendWithDefault(Message *message, Node *node)
    {
        setChargeFlag(message);
        return TRUE;
    }
    
    int main()
    {
        Message *message = makeMessage(1,"20131212");
        void *actionList[] = {(void*)&isAllowSendCheckDate, 
                            (void*)&isAllowSendCheckWhiteList, 
                            (void*)&isAllowSendWithDefault};
        Node *theList = makeListWithArray(actionList, sizeof(actionList)/4);
        FuncIsAllowSend isAllowSend = (FuncIsAllowSend)theList->ptr;
        if(isAllowSend(message, theList) == TRUE)
        {
            setSendFlag(message);
        }
        printf("%s
    ",format(message));
    }

    代码风格其实是C风格,但是因为要使用gtest不得不使用了g++对程序进行编译调试,命令如下:

    # 前提:我已经把gtest编译成库放在了系统目录下
    
    g++ -c message.c
    g++ -c testMessage.c
    g++ message.o testMessage.o -lgtest -lpthread
    ./a.out
    
    g++ -c node.c
    g++ -c testNode.c
    g++ node.o testNode.o -lgtest -lpthread
    ./a.out 
    
    g++ -c main.c
    g++ message.o node.o main.o
    ./a.out
  • 相关阅读:
    唯一元素List UniqueList
    汉诺塔 Hanoi 递归示例demo附代码
    TreeView控件保存恢复结点展开状态
    F#个人学习笔记2(F# survey)
    F#个人学习笔记1(F# survey)
    多文件上传控件(附示例下载)
    由desktopsavemode引起的Emacs配置失效
    Emacs+hideif.el 隐藏预编译代码(或彩色显示预编译代码)
    Emacs的Tab键
    Emacs+highlightparentheses高亮括号
  • 原文地址:https://www.cnblogs.com/code-style/p/3539494.html
Copyright © 2020-2023  润新知