C/C++实现模糊控制,借助MATLAB辅助设计和fis.c文件

上一篇文章C /C++语言实现模糊控制介绍了C/C++中实现模糊控制该怎么做,开始提到的MATLAB模糊控制的C/C++模糊控制接口fis.c库,不过这个文件有点老,在用VS2010编译的时候一大堆错误,在网上找关于C++中使用 fis.c 的资料,结果一点结果都没有,说怎么引用fis.c文件,网上的都是说什么头文件,extern "C"{} 的老一套,问题是fis.c文件中大多数的函数都是static修饰的,不可能自己再做个.h的头文件,途径只有一条,用#include "fis.c" 包含这个C语言文件,问题是一包含就是一大堆错误,后来看fis.c的代码发现,原来里面有很多过时的语法,C语言可以编译,但是C++不可以,比如模糊控制的主要数据结构FIS的定义,原先的定义如下:

typedef struct fis_node {
	int handle;
	int load_param;
	char name[STR_LEN];
	char type[STR_LEN];
	char andMethod[STR_LEN];
	char orMethod[STR_LEN];
	char impMethod[STR_LEN];
	char aggMethod[STR_LEN];
	char defuzzMethod[STR_LEN];
	int userDefinedAnd;
	int userDefinedOr;
	int userDefinedImp;
	int userDefinedAgg;
	int userDefinedDefuzz;
	int in_n;
	int out_n;
	int rule_n;
	int **rule_list;
	DOUBLE *rule_weight;
	int *and_or;	/* AND-OR indicator */
	DOUBLE *firing_strength;
	DOUBLE *rule_output;
	/* Sugeno: output for each rules */
	/* Mamdani: constrained output MF values of rules */
	struct io_node **input;
	struct io_node **output;
	DOUBLE (*andFcn)(DOUBLE, DOUBLE);
	DOUBLE (*orFcn)(DOUBLE, DOUBLE);
	DOUBLE (*impFcn)(DOUBLE, DOUBLE);
	DOUBLE (*aggFcn)(DOUBLE, DOUBLE);
	DOUBLE (*defuzzFcn)();
	DOUBLE *BigOutMfMatrix;	/* used for Mamdani system only */
    DOUBLE *BigWeightMatrix;/* used for Mamdani system only */
	DOUBLE *mfs_of_rule;	/* MF values in a rule */

	DOUBLE *bias; /*bias, to be tuned when no rules are fired*/
	int isbias;

	struct fis_node *next;
} FIS;

上述的定义中,defuzzFcn这个指针函数的定义没有参数,而后面的Defuzzification methods都是带参数的,甚至第一个参数就是FIS结构体本身,如:

static DOUBLE defuzzCentroid(FIS *fis, int m, DOUBLE *mf, int numofpoints)

所以要修改这个定义,如下:

typedef struct fis_node FIS;

typedef struct fis_node {
	int handle;
	int load_param;
	char name[STR_LEN];
	char type[STR_LEN];
	char andMethod[STR_LEN];
	char orMethod[STR_LEN];
	char impMethod[STR_LEN];
	char aggMethod[STR_LEN];
	char defuzzMethod[STR_LEN];
	int userDefinedAnd;
	int userDefinedOr;
	int userDefinedImp;
	int userDefinedAgg;
	int userDefinedDefuzz;
	int in_n;
	int out_n;
	int rule_n;
	int **rule_list;
	DOUBLE *rule_weight;
	int *and_or;	/* AND-OR indicator */
	DOUBLE *firing_strength;
	DOUBLE *rule_output;
	/* Sugeno: output for each rules */
	/* Mamdani: constrained output MF values of rules */
	struct io_node **input;
	struct io_node **output;
	DOUBLE (*andFcn)(DOUBLE, DOUBLE);
	DOUBLE (*orFcn)(DOUBLE, DOUBLE);
	DOUBLE (*impFcn)(DOUBLE, DOUBLE);
	DOUBLE (*aggFcn)(DOUBLE, DOUBLE);
	
	//DOUBLE (*defuzzFcn)();  hemmingway <hemmingway@163.com>  2013/01/02
	DOUBLE (*defuzzFcn)(FIS *fis, int m, DOUBLE *mf, int numofpoints);  
	
	DOUBLE *BigOutMfMatrix;	/* used for Mamdani system only */
    DOUBLE *BigWeightMatrix;/* used for Mamdani system only */
	DOUBLE *mfs_of_rule;	/* MF values in a rule */

	DOUBLE *bias; /*bias, to be tuned when no rules are fired*/
	int isbias;

	struct fis_node *next;
} FIS;



接下来是printf和double的宏定义问题,原先针对的是控制台程序,或者Linux下控制台,如果要把模糊控制用到MFC环境,需要修改这个宏定义,方便用到MFC界面程序中,修改过后如下所示:

/* Define portable printf and double */
#if defined(MATLAB_MEX_FILE)
# define PRINTF mexPrintf
# define DOUBLE real_T
#elif defined(__SIMSTRUC__)
# define PRINTF ssPrintf
# define DOUBLE real_T
#elif defined(_MSC_VER)

#define PRINTF odprintf

#include <stdarg.h>
#include <Windows.h>

int _cdecl odprintf(const char* fmt, ...)	
{
	char buf[4096], *p=buf;
	va_list	args;
	int		ret = -1;

	va_start(args, fmt);
	ret = vsnprintf_s(p, sizeof(buf), _TRUNCATE, fmt, args);
	p +=ret;
	va_end(args);

	while (p>buf && isspace(*p))
	{
		*--p = '\0';
		*p++ = '\r';
		*p++ = '\n';
		*p = '\0';
	}

	OutputDebugStringA(buf);

	return(ret);
}
#else
# define PRINTF printf
# define DOUBLE double
#endif


接下来修改一下fisError这个函数,里有有个exit(1); 在MFC界面程序中不需要这个的,需要修改一下:

static void fisError(char *msg)
{
#ifdef MATLAB_MEX_FILE
	mexErrMsgTxt(msg);
#else
	PRINTF("%s\n",msg);

#ifndef _MSC_VER
		exit(1);
#endif

#endif
}


还有一个函数封装了fopen()函数打开文件,里面有个多余的定义语句, FILE *fopen();  这个在C++中不支持,需要注释掉它:

/* an friendly interface to fopen() */
static FILE *fisOpenFile(char *file, char *mode)
{
	FILE *fp /*, *fopen()*/;

	if ((fp = fopen(file, mode)) == NULL){
		PRINTF("The file %s cannot be opened.", file);
		fisError("\n");
	}
	return(fp);
}


再就是fis.c文件后面的几个函数定义,使用 __STDC__ 宏支持了一种老旧的语法格式,如下所示:

/* return data matrix */
DOUBLE **
#ifdef __STDC__
returnDataMatrix(char *filename, int *row_n_p, int *col_n_p)
#else
returnDataMatrix(filename, row_n_p, col_n_p)
char *filename;
int *row_n_p;
int *col_n_p;
#endif
{
	//code...
}

问题是MFC程序中 定义 __STDC__ 宏会出现错误的,而那种默认的老旧C语法格式C++中又不支持,所以所有这样定义的函数都要删掉那些多余的东西,如上面的函数改成这样:

/* return data matrix */
DOUBLE **returnDataMatrix(char *filename, int *row_n_p, int *col_n_p)
{
	//code...
}


改完以后,没有错误了,用下面的语句将fis.c文件包含到一个CPP文件的时候,问题又来了,出现 fatal error LNK1169: 找到一个或多个多重定义的符号,按照一般在网上搜索的解决方法是:项目->属性->链接器->命令行->附加选项中加 /force  这样没有错误了,但是还是有很多警告Warning Link 一大堆乱七八糟的警告,其实真正的方法是:在【解决方案资源管理器】中选中fis.c文件,单击右键的属性,打开fis.c属性页对话框,在 【配置属性】->【常规】->【项类型】中,将这个配置为【C/C++ 标头】,这样就没有什么问题了。

/*Start of the regular fis control*/
extern "C"{
#include "fis.c"
}


                                      


 

============================================

使用方法总结如下:

/*

* 这是修改过后的fis.c模糊推理系统库函数,可以移植C/C++环境使用,在VS2010的MFC环境经过测试

* 1、将fis.c文件拷贝到项目中;

* 2、修改VS2010的配置属性,项目->属性->C/C++->预处理器->预处理器定义,添加

* _CRT_SECURE_NO_WARNINGS

* 3、在【解决方案资源管理器】中选中fis.c文件,单击右键的属性

* 【配置属性】->【常规】->【项类型】,配置为【C/C++ 标头】

* 4、如果是C语言文件(*.c)使用

* #include "fis.c"

* 包含接口库文件;

* 5、如果是C++文件,使用

* extern "C"{

* #include "fis.c"

* }

* 包含库文件。

* 祝你使用愉快!

* hemmingway <hemmingway@163.com> 2013/1/2

*/


修改过后的fis.c文件可以从这里下载:

http://download.csdn.net/detail/hemmingway/4953923



  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值