用链表解决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[];
}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, );
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, , 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, ) == )
{
return TRUE;
}
else
{
return FALSE;
}
}
testMessage.c
#include <stdio.h>
#include "message.h"
#include "gtest/gtest.h" TEST(MESSAGE,makeMessage){
Message *message = makeMessage(,"");
EXPECT_EQ(, 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 > );
for(i = length - ; i >= ; 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 = ;
int data[] = {,,};
EXPECT_EQ(data[i], *(int*)node->ptr);
i++;
} TEST(NODE,makeListWithArray){
int i;
int data[] = {,,};
void *aSet[] = {&data[], &data[], &data[]};
Node *list = makeListWithArray(aSet, );
foreach(list, printNode);
}
程序入口实现(main.c)
#include <stdio.h>
#include <string.h>
#include "message.h"
#include "node.h" # define FALSE
# define TRUE typedef int BOOL;
typedef BOOL (*FuncIsAllowSend)(Message *, Node*); BOOL isAllowSendCheckDate(Message *message, Node *node)
{
FuncIsAllowSend isAllowSend = NULL; if(strcmp(message->date, "") == )
{
return FALSE;
} isAllowSend = (FuncIsAllowSend) node->next->ptr;
return isAllowSend(message, node->next);
} BOOL isAllowSendCheckWhiteList(Message *message, Node *node)
{
FuncIsAllowSend isAllowSend = NULL; if(message->sender == )
{
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(,"");
void *actionList[] = {(void*)&isAllowSendCheckDate,
(void*)&isAllowSendCheckWhiteList,
(void*)&isAllowSendWithDefault};
Node *theList = makeListWithArray(actionList, sizeof(actionList)/);
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
用链表解决if语句过多的问题(C/C++实现)的更多相关文章
- php实现单,双向链表,环形链表解决约瑟夫问题
传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季 http://php.itcast.cn 聊天篇: 数学对我们编程来说,重不重要? 看你站在什么样的层次来说. 如果你应用程序开发,对数学要求 ...
- PHP算法学习(8) 环形链表 解决约瑟夫问题
2019年2月25日17:29:17 Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓.于是决定了自杀方式,41个人排成一个圆圈 ...
- mysql 线程等待时间,解决sleep进程过多的办法
如果你没有修改过MySQL的配置,缺省情况下,wait_timeout的初始值是28800. wait_timeout 过大有弊端,其体现就是MySQL里大量的SLEEP进程无法及时释放,拖累系统 ...
- TCP之再谈解决服务器TIMEWAIT过多的问题
原则 TIMEWAIT并不是多余的.在TCP协议被创造,经历了大量的实际场景实践之后,TIMEWAIT出现了,因为TCP主动关闭连接的一方需要TIMEWAIT状态,它是我们的朋友.这是<UNIX ...
- VS2017一步一步断点调试解决Dapper语句出现的Bug
最近再做一个项目,出现一个小bug,bug虽小,但是却要命啊.下面我show下我解决问题的方法. View层代码: @model List<mhq.Blog.Model.Blog> < ...
- 解决insert语句插入时,需要写列值的问题
今天发现解决这个问题其实很简单,闲话不多谈,我直接附上语句 ) select @s = isnull(@s+',', '') + [name] from syscolumns where id = o ...
- 使用java的循环单向链表解决约瑟夫问题
什么是约瑟夫问题 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定 ...
- 单向环形链表解决约瑟夫环(Josephus)问题
一.约瑟夫环问题 Josephu 问题为:设编号为1,2,- n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那 ...
- PHP+Redis链表解决高并发下商品超卖问题
目录 实现原理 实现步骤 上一篇文章聊了一下使用Redis事务来解决高并发商品超卖问题,今天我们来聊一下使用Redis链表来解决高并发商品超卖问题. 实现原理 使用redis链表来做,因为pop操作是 ...
随机推荐
- HTML5 Shiv – 让该死的IE系列支持HTML5吧(转)
摘自: http://www.cnblogs.com/yuzhongwusan/archive/2011/11/17/2252207.html HTML5能为我们做的事儿很多,最为可口的就是语义化标签 ...
- 【Android - 框架】之XBanner的使用
一.XBanner简介 XBanner是一个非常优秀的无限自动轮播框架,也是一个控件.这里是XBanner的GitHub地址 XBanner的主要功能如下: 根据传入的数据条数自动调整广告页数 当图片 ...
- Linux下配置SSL (转)
没有安装apache的情况: 首先安装SSL,再编译安装Apache,再配置证书即可 1.下载apache和openssl 网址:http://www.apache.org http://www.op ...
- Entity Framework CodeFirst------使用CodeFirst方式建立数据库连接(一)
本文分步演练介绍通过 Code First 开发建立新数据库.这个方案包括建立不存在的数据库(Code First 创建)或者空数据库(Code First 向它添加新表).借助 Code First ...
- Java的演变过程
1. 1996.01.23 JDK1.0 代号Oak:212个类.8个包: 2. 1997.02.19 JDK1.1 504个类.23个包: Java Bean.远程方法调用(RMI).JAR文件格式 ...
- CentOS 6.7编译安装MySQL 5.6
1.安装前准备 yum install make gcc gcc-c++ ncurses-devel perl bison-devel yum groupinstall "Developme ...
- Raphaël.js学习笔记
Rapheal.js 是一个矢量图绘图库.对于支持HTML5 SVG的浏览器使用SVG绘图,不支持SVG的IE(ie6,7,8)使用VML绘图.所以Raphael.js的兼容性非常好. Raphael ...
- MySQL存储过程学习笔记
MySQL在5.0以前并不支持存储过程,这使得MySQL在应用上大打折扣.MySQL 5.0终于开始支持存储过程了. MySQL的关键字大小写通用.该学习笔记对关键字使用大写:变量名,表名使用小写. ...
- GET和POST本质上有什么区别
如果有人问你,GET和POST,有什么区别?你会如何回答? 我的经历 前几天有人问我这个问题.我说GET是用于获取数据的,POST,一般用于将数据发给服务器之用. 这个答案好像并不是他想要的.于是他继 ...
- WebForm开发常用代码
1.获取服务器绝对路径: public static string GetMapPath(string strPath) { if (HttpContext.Current != null) { re ...