技术宅,fat-man

增加语言的了解程度可以避免写出愚蠢的代码

导航

用链表解决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>\n", \
        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>\n", 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\n",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

 

 

posted on 2014-02-07 14:38  codestyle  阅读(1825)  评论(5编辑  收藏  举报