📄 ccompilecomplex.h
字号:
// CCompileComplex.h: interface for the CCompileComplex class.
// 复数函数动态编译器CCompileComplex类
//////////////////////////////////////////////////////////////////////
#if !defined(HSS_CCOMPILECOMPLEX_H__39855E25_8C8B_4800_ACF7_D2199F6B3276__INCLUDED_)
#define HSS_CCOMPILECOMPLEX_H__39855E25_8C8B_4800_ACF7_D2199F6B3276__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//////////////////////////////////////////////////////////////////////////
// //
// 复数函数动态编译器CCompileComplex类(由Delphi引入) //
// 作者:侯思松 2003.3 //
// 有改进意见或发现任何错误请转告我,本人不胜感激。 //
// E-Mail:HouSisong@263.net //
// ( 转载时请保留本说明:) ) //
// //
//////////////////////////////////////////////////////////////////////////
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>///
/// <<功能简介>>: ///
/// CCompileComplex可以在程序运行过程中动态完成复数函数表达式字符串的 ///
/// 编译执行,(可以带复数参数;动态生成机器码执行,不是解释执行)执行速度超快!! ///
///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<///
/*
<<使用方法>>:
CCompileComplex Compilation; // 声明Compilation为复数函数动态编译器CCompileComplex类的实例
CString str="x+sin(i+y*PI/2)*i+Sqrt(-1)";
Compilation.SetText(str); //str为需要求值的复数表达式字符串
......
//如果有参数,可以获得参数地址,并赋值 (默认值为0+0*i)
//如:TComplex* PTComplexX:=Compilation.GetParameterAddress('x');
//如:TComplex* PTComplexY:=Compilation.GetParameterAddress('y');
// if (PTComplexX!=NULL) *PTComplexX=TComplex(2,1.5);
// if (PTComplexY!=NULL) *PTComplexY=0.5;
//也可以一次获得所有的参数列表:Compilation.GetParameterList(PList);
......
TComplex xValue:=Compilation.GetValue(); //获得表达式的值,
//可以多次改变参数值并多次调用(如放在循环中),这样才能显示出效率:)
......
简要声明:
任何用户使用本软件属于个人自愿选择,作者不会对用户使用本软件所引起
的对用户的任何形式的损失负责,作者也不承诺提供对本类的维护和服务等义务。
本类可以自由拷贝和使用,但必须包含完整的代码和说明,任何修改和用于
商业化目的的行为都应该尽量与作者取得联系,并得到授权。
( E-Mail: HouSisong@263.net )
本类的编写目的只是在程序运行过程中能够多次的快速的执行用户输入的
复数表达式,程序优化的目标是速度和高精度,所以基本数据类型采用的是80
位浮点型,很多地方的处理是以速度为首要目标,这样在计算的准确性和错误
处理方面就有所损失。
测试环境包括:Windows95、Win98、WindowsMe、Windows2000、WindowsXP。
测试过的CPU包括:奔腾、赛扬A、奔腾3、赛扬2、奔腾4。
*/
#include "TComplex.h" //提供 复数类 TComplex (利用了x86 CPU内置10字节浮点数类型)
// CCompileComplex的接口使用该种数据类型
// (特别是设置外部变量时一定要使用这种类型)
const char cmcx_DllName[] ="CompileDll.dll";
const int cmcx_Max_ParameterName_Length = 256;
typedef DWORD cmcx_Handle;
struct cmcx_TUserParameterList
{
char CName[cmcx_Max_ParameterName_Length]; //参数名称
TComplex* CAddress; //参数地址
};
//错误号定义
const int csTCmCx_NoError = 0; //没有发现错误!
const int csTCmCx_NoKnownError = 101; //不知道的错误!
const int csTCmCx_NoErrorCode = 102; //找不到错误号所对应的错误描述!
const int csTCmCx_CompileHexCodeError = 103; //编译时指令的十六进制代码错误!
const int csTCmCx_HexMod2_EQ_1_Error = 104; //编译时传入指令长度错误!
const int csTCmCx_PMMarker_Error = 105; //编译得到参数名称时发生错误!
const int csTCmCx_FMMarker_Error = 106; //编译得到函数名称时发生错误!
const int csTCmCx_Wording_Error = 107; //语法发生错误!
const int csTCmCx_Bracket_Error = 108; //语法错误,在 ( ) 处!
const int csTCmCx_Optimize_Error = 109; //编译优化时发生错误!
const int csTCmCx_Define_Error = 110; //函数编译错误(或超出定义域)!
const int csTCmCx_Handwriting_Error = 111; //函数书写格式错误!
const int csTCmCx_ReadFloat_Error = 113; //编译读取常数数字时发生错误!
const int csTCmCx_ReadMarker_Error = 114; //编译读取标识符时发生错误!
const int csTCmCx_Read_Error = 115; //语法错误,有不识别的字符!
const int csTCmCx_Note_Match_Error = 116; //注释符号不匹配! { } 或 /* */
const int csTCmCx_FPList_Error = 117; //参数列表错误!
const int csTCmCx_IFHandwriting_Error = 118; //If函数书写格式错误!
//////////////////////////////////////////////////////
// 复数函数动态编译器CCompileComplex类 //
//////////////////////////////////////////////////////
class CCompileComplex
{
cmcx_Handle m_cmcxHandle; // 复数函数编译类句柄
static bool LoadCompileDll();
public:
CCompileComplex();
virtual ~CCompileComplex();
//数据与字符串之间转换
static CString ExtendedToStr (const Extended & x);
static Extended StrToExtended (LPCSTR s);
static CString TComplexToStr (const TComplex & x);
static bool StrToTComplex (LPCSTR s,TComplex * x);
// 设置需要编译的字符串(要编译的字符串,虚参数列表字符串,是否自动编译);
// 比如:Value="Sqr(x)+Sqr(y)"; ParameterList="x,y" ;
bool SetText(LPCSTR TextValue,LPCSTR ParameterList=NULL,bool IfCompile=true); //(编译前调用,这是最先要做的)
// 编译当前字符串
bool Compile(); //一个表达式只能调用编译一次
// 调用函数返回表达式的值(实参数值列表); //等价于 cmcx_SetFunctionParameter + cmcx_GetValue
TComplex GetFunctionValue(TComplex* PList); // (编译后才能调用)
// 调用函数返回表达式的值;
TComplex GetValue(); // (编译前后都能调用)
void GetValue(TComplex* Result); // 同上
// 按当前设置的参数表传入参数值(实参数值列表)
void SetFunctionParameter(TComplex* PList);
// 测试是否使用了未定义的变量
bool IfHaveUnDefineParameter();//(编译后才能调用)
//设置一个外部变量(外部变量名称,外部变量地址); 这样就可以和高级语言或另一个编译类共享变量了
bool SetExteriorParameter(LPCSTR PName,TComplex* PAddress); //(编译前调用,如果是在编译后,需要调用cmcx_RefreshExeAddressCodeInPointer刷新地址)
// 设置外部数组(数组名称,数组地址);
bool SetExteriorArrayParameter(LPCSTR ArrayPName,TComplex* ArrayPAddress);
//刷新变更地址 //(设置完所有的外部变量以后需要调用一次该函数)
void RefreshExeAddressCodeInPointer();
// 处理预定义宏(要代换的标识符,代换为的描述字符串); // 可以用来处理常数,甚至定义新的函数!
// 如 Key="a"; Value="-0.5" , 或 Key="f(x,y)",Value="Max(x,Sin(y))"(即定义了一个函数f) 等;
bool Define(LPCSTR Key,LPCSTR Value); //(编译前调用)
// 处理常数定义(要代换的标识符,代换的值) // 常数定义, Value必须是一个可计算的值
// 如 Key="a"; Value="2" , 或 Key="b" , Value="2*sin(PI/2)" 等;
// 该功能完全可以用预定义宏(Define)来代替,
// 但当值为常数时这样处理有可能使最后得到的编译函数速度更快,并加快编译速度
bool DefineConst(LPCSTR Key,LPCSTR Value);//(编译前调用)
//根据参数名称PName得到参数地址值
TComplex* GetParameterAddress(LPCSTR PName);
//按参数名称PName设置参数值dValue
bool SetParameter(LPCSTR PName,const TComplex& dValue);
//按参数地址PAddress设置参数值dValue
void SetParameter(TComplex* PAddress,const TComplex& dValue);
//得到参数PName的值
TComplex GetParameterValue(LPCSTR PName);
//得到参数的总数目(不包括常数)
DWORD GetUserParameterCount();
//通过PList返回参数列表(不包括常数)
void GetUserParameterList(cmcx_TUserParameterList* PList);
//测试参数PName是否已经存在
bool IfHaveParameter(LPCSTR PName);
//设置随机函数Rnd()的初始种子值为完全随机种子(系统用当前精确到毫秒的时间设置)
void SetRandomize();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -