定义各种运算符和常量的优雅方式
Elegant way to defining the various operations and costants
我正在创建一个 C++ wxWidgets 计算器应用程序。我需要一种方法来轻松定义程序中可用的各种操作和成本。
现在,在我的主框架 class 中,我私下声明了这些数组:
const wxString ops[5] = //operations that require a number before and after
{
L"+",
L"-",
L"\u00D7", //multiplication
L"\u00F7", //division
L"^"
};
const wxString extra[10] = //operations that only require a number after (don't know the right name for this)
{
L"\u221A", //square root
L"sin",
L"cos",
L"tan",
L"arcsin",
L"arccos",
L"arctan"
};
const wxString consts[2] = //constants
{
L"\u03C0" //pi
};
我正在使用 wxString,因为在解析方程式的函数中,它会检查是否找到其中之一,获取相应的数组索引并将其用于实际计算的开关中。
例如,如果我键入 sin45+5
,解析会找到 sin
,检查它是否属于 ops
、extra
或 consts
数组然后循环遍历 extra
数组并得到它的索引是 1 因为它是数组中的第二个元素。然后我有这段代码,其中 returns sin 操作的结果:
switch (GetExtraId(op)) { default: return 0;
case 0: return sqrt(b); //radice quadrata
case 1: return sin(b * 3.14159265359 / 180); //trasformazione da radianti a gradi
case 2: return cos(b * 3.14159265359 / 180);
case 3: return tan(b * 3.14159265359 / 180);
case 4: return asin(b) * 180 / 3.14159265359;
case 5: return acos(b) * 180 / 3.14159265359;
case 6: return atan(b) * 180 / 3.14159265359;
}
我在问:有没有更优雅的方法来做到这一点?事实上,如果我想为 + 操作创建一个按钮,我必须将其标签设置为 ops[0]
,这有点不方便。我试过类似的东西:
enum class ops : wxString
{
add = L"+",
sub = L"-",
mul = L"\u00D7",
div = L"\u00F7",
pow = L"^"
};
但是我必须以某种方式将它们转换为 int
才能在 switch 中使用它们。另外,我不能在枚举中使用 wxString,因为它不是整数类型。
似乎是 map
使用的经典案例。你可以往这方面看:
std::map<std::string, std::function<double(double, double)> ops;
然后填充它:
double add(double, double);
ops.insert({"+", add}); // Maps "+" to the pointer to add()
ops.emplace("-", subtract); // Or even like so
所以,那么你可以直接从 map
调用 return:
ops["+"](3.14, 1.61); // Returns 4.75
这种方式可以直接查询函数,不需要字符串到整数的映射,然后switch
基于这个整数。
关于与 wxString 一起使用,您可能需要查看此 list of conversions。
我正在创建一个 C++ wxWidgets 计算器应用程序。我需要一种方法来轻松定义程序中可用的各种操作和成本。 现在,在我的主框架 class 中,我私下声明了这些数组:
const wxString ops[5] = //operations that require a number before and after
{
L"+",
L"-",
L"\u00D7", //multiplication
L"\u00F7", //division
L"^"
};
const wxString extra[10] = //operations that only require a number after (don't know the right name for this)
{
L"\u221A", //square root
L"sin",
L"cos",
L"tan",
L"arcsin",
L"arccos",
L"arctan"
};
const wxString consts[2] = //constants
{
L"\u03C0" //pi
};
我正在使用 wxString,因为在解析方程式的函数中,它会检查是否找到其中之一,获取相应的数组索引并将其用于实际计算的开关中。
例如,如果我键入 sin45+5
,解析会找到 sin
,检查它是否属于 ops
、extra
或 consts
数组然后循环遍历 extra
数组并得到它的索引是 1 因为它是数组中的第二个元素。然后我有这段代码,其中 returns sin 操作的结果:
switch (GetExtraId(op)) { default: return 0;
case 0: return sqrt(b); //radice quadrata
case 1: return sin(b * 3.14159265359 / 180); //trasformazione da radianti a gradi
case 2: return cos(b * 3.14159265359 / 180);
case 3: return tan(b * 3.14159265359 / 180);
case 4: return asin(b) * 180 / 3.14159265359;
case 5: return acos(b) * 180 / 3.14159265359;
case 6: return atan(b) * 180 / 3.14159265359;
}
我在问:有没有更优雅的方法来做到这一点?事实上,如果我想为 + 操作创建一个按钮,我必须将其标签设置为 ops[0]
,这有点不方便。我试过类似的东西:
enum class ops : wxString
{
add = L"+",
sub = L"-",
mul = L"\u00D7",
div = L"\u00F7",
pow = L"^"
};
但是我必须以某种方式将它们转换为 int
才能在 switch 中使用它们。另外,我不能在枚举中使用 wxString,因为它不是整数类型。
似乎是 map
使用的经典案例。你可以往这方面看:
std::map<std::string, std::function<double(double, double)> ops;
然后填充它:
double add(double, double);
ops.insert({"+", add}); // Maps "+" to the pointer to add()
ops.emplace("-", subtract); // Or even like so
所以,那么你可以直接从 map
调用 return:
ops["+"](3.14, 1.61); // Returns 4.75
这种方式可以直接查询函数,不需要字符串到整数的映射,然后switch
基于这个整数。
关于与 wxString 一起使用,您可能需要查看此 list of conversions。