[英]C++ Dynamically Define Function
我正在使用Visual C ++在控制台計算器上工作,正在創建一種讓用戶定義自定義線性函數的方法。 這是讓我感到困惑的地方:一旦獲得用戶所需的函數名稱,斜率和y軸截距,我就需要使用該數據來創建可調用函數,然后將其傳遞給muParser。
在muParser中,您可以這樣定義自定義函數:
double func(double x)
{
return 5*x + 7; // return m*x + b;
}
MyParser.DefineFun("f", func);
MyParser.SetExpr("f(9.5) - pi");
double dResult = MyParser.Eval();
如何根據用戶輸入的值“ m”和“ b”動態創建類似這樣的函數,並將其傳遞給“ DefineFun()”方法? 這是我到目前為止的內容:
void cb_SetFunc(void)
{
string FuncName, sM, sB;
double dM, dB;
bool GettingName = true;
bool GettingM = true;
bool GettingB = true;
regex NumPattern("[+-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?");
EchoLn(">>> First, enter the functions name. (Enter 'cancel' to abort)");
EchoLn(">>> Only letters, numbers, and underscores can be used.");
try
{
do // Get the function name
{
Echo(">>> Enter name: ");
FuncName = GetLn();
if (UserCanceled(FuncName)) return;
if (!ValidVarName(FuncName))
{
EchoLn(">>> Please only use letters, numbers, and underscores.");
continue;
}
GettingName = false;
} while (GettingName);
do // Get the function slope
{
Echo(">>> Enter slope (m): ");
sM = GetLn();
if (UserCanceled(sM)) return;
if (!regex_match(sM, NumPattern))
{
EchoLn(">>> Please enter any constant number.");
continue;
}
dM = atof(sM.c_str());
GettingM = false;
} while (GettingM);
do // Get the function y-intercept
{
Echo(">>> Enter y-intercept (b): ");
sB = GetLn();
if (UserCanceled(sB)) return;
if (!regex_match(sB, NumPattern))
{
EchoLn(">>> Please enter any constant number.");
continue;
}
dB = atof(sB.c_str());
GettingB = false;
} while (GettingB);
// ------------
// TODO: Create function from dM (slope) and
// dB (y-intercept) and pass to 'DefineFun()'
// ------------
}
catch (...)
{
ErrMsg("An unexpected error occured while trying to set the function.");
}
}
我當時在想,沒有一種方法可以為每個用戶定義的函數定義一個單獨的方法。 我需要做一個vector<pair<double, double>> FuncArgs;
跟蹤適當的斜率和y軸截距,然后從函數中動態調用它們? 將其傳遞給DefineFun(FuncStrName, FuncMethod)
時,如何指定要使用的一對?
您需要的(除了腳本語言解釋器之外)被稱為“蹦床” 。 沒有標准的解決方案來創建這些代碼,特別是因為它涉及在運行時創建代碼。
當然,如果您接受固定數量的蹦床,則可以在編譯時創建它們。 如果它們都是線性的,則可能會更容易:
const int N = 20; // Arbitrary
int m[N] = { 0 };
int b[N] = { 0 };
template<int I> double f(double x) { return m[I] * x + b; }
這定義了一組20個函數f<0>...f<19>
,分別使用m[0]...m[19]
。
編輯:
// Helper class template to instantiate all trampoline functions.
double (*fptr_array[N])(double) = { 0 };
template<int I> struct init_fptr<int I> {
static const double (*fptr)(double) = fptr_array[I] = &f<I>;
typedef init_fptr<I-1> recurse;
};
template<> struct init_fptr<-1> { };
GiNaC是C ++庫,可以解析和評估數學表達式。
嘗試將一些腳本語言嵌入到您的應用程序中。 多年前,我將Tcl用於類似目的-但我不知道當前最好的選擇是什么。
您可以從Tcl開始,也可以自己搜索更好的東西:
請參閱: 將Tcl / Tk添加到C應用程序
我會保持簡單:
#include <functional>
std::function<double(double)> f; // this is your dynamic function
int slope, yintercept; // populate from user input
f = [=](double x) -> double { return slope * x + yintercept; };
現在,您可以將對象f
傳遞給解析器,然后解析器可以隨意調用f(x)
。 函數對象打包捕獲的slope
和yintercept
值。
生成可綁定到boost功能的固定功能數組。
有人已經說過類似的方法,但是由於我花了一些時間編寫代碼,所以還是可以的。
#include <boost/function.hpp>
enum {
MAX_FUNC_SLOTS = 255
};
struct FuncSlot
{
double (*f_)(double);
boost::function<double(double)> closure_;
};
FuncSlot s_func_slots_[MAX_FUNC_SLOTS];
template <int Slot>
struct FuncSlotFunc
{
static void init() {
FuncSlotFunc<Slot-1>::init();
s_func_slots_[Slot - 1].f_ = &FuncSlotFunc<Slot>::call;
}
static double call(double v) {
return s_func_slots_[Slot - 1].closure_(v);
}
};
template <> struct FuncSlotFunc<0> {
static void init() {}
};
struct LinearTransform
{
double m_;
double c_;
LinearTransform(double m, double c)
: m_(m)
, c_(c)
{}
double operator()(double v) const {
return (v * m_) + c_;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
FuncSlotFunc<MAX_FUNC_SLOTS>::init();
s_func_slots_[0].closure_ = LinearTransform(1, 0);
s_func_slots_[1].closure_ = LinearTransform(5, 1);
std::cout << s_func_slots_[0].f_(1.0) << std::endl; // should print 1
std::cout << s_func_slots_[1].f_(1.0) << std::endl; // should print 6
system("pause");
return 0;
}
因此,您可以使用以下命令獲取函數指針:s_func_slots_ [xxx] .f_並使用s_func_slots_ [xxx] .closure_設置操作
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.