根据组合框中的选定项目选择算法

Choose algorithm in accordance with chosen item in combobox

本文关键字:项目 选择 算法 组合      更新时间:2023-10-16

美好的一天,

我正在编写一个程序"geocalculator"作为我们大学的作业。我面临着一个设计问题。接口包含两组:A 和 B。每组由两个组合框和一个表格组成。第一个组合框允许用户在几个参考系统(WGS-84、SK-42、SK-95 等)之间进行选择。第二个 - 在大地测量、空间和平面坐标系之间。该表用于输入一堆点(标签、X(或 B)、Y(或 L)、Z(或 H))。转换函数涉及大量常量和大量公式。

我的问题是:组织代码、连接组合框和函数以调用适当的转换函数的最佳方法是什么?

让我们进入正题。我子类化了一个抽象模型(PointsModel),我所有的点都被存储在那里。它对组合框和算法一无所知。组合框在 MainWindow 类中声明。我的模型确实有自定义委托:它用于将输入坐标的表示形式从十六进制(度、分和秒)转换为十进制(十进制度)。我有两个按钮(工具栏上的操作):将点从 A 转换为 B,反之亦然。我以以下方式想象这个过程:

  1. 用户按下"转换"按钮并调用相应的函数。
  2. 常规转换函数
  3. 读取组合框的值并选择所需的转换函数。...

我不想通过"如果否则"语句来做到这一点!因为会有大量的条件语句(如果一个组合框是 WGS-84,另一个是 SK-42,那么这样做,如果一个组合框是 SK-42,另一个是 WGS-84,那么对一堆参考系统执行这个,依此类推)。

我对声明函数和相应的函子有一些想法。我想以某种方式将此函子附加到组合框,然后时间到了,只需调用一个通用方法,它会自动将调用重定向到所需的函数。

我将介绍两个流行的选择:查找表和事件处理程序(又名按钮按下)。 算法的选择取决于您的计算器实现。

查找表

这里的基础知识是您希望将函数与符号相关联。 例如,您的解析器想要计算堆栈上表达式的"+"。 与其使用switchif-elseif梯,不如查找与"+"关联的函数并使用两个表达式执行该函数。

// Synonym for a pointer that accepts two parameters,
// performs an operation, and returns the result as a string.
typedef std::string (*Function_Pointer(const std::string& param1, const std::string& param2))
struct Table_Entry
{
  const char * operator_text;
  Function_Pointer p_operaton_function;
};
const Table_Entry Operation_Table[] =
{
  {"+", Perform_Addition},
  {"-", Perform_Subtraction},
  {"*", Perform_Multiplication},
};
// Or
typedef std::map<std::string, Function_Pointer> Operation_Container;
//...
Operation_Container operations_map;
operations_map["+"] = Perform_Addition;
operations_map["-"] = Perform_Subtraction;

事件处理程序

另一个想法是将计算放在按钮的处理程序中。

void On_Button_Dash(Event& e)
{
  result = operand_1 - operand2;
}

编辑 1:OOP

另一种方法是为操作创建基类。 基类将具有用于计算或执行操作的抽象方法。 为每个操作定义子类。 在词法分析阶段创建操作类,并存储在指向基类的指针向量中。

您的主循环可以是:

std::vector<Base_Operation *> operations;
for (unsigned int i = 0; i < operations.size(); ++i)
{
  operations[i].Evaluate(parameter_1, parameter_2);
}

有很多方法可以解决这个问题,但我认为最好的方法是在QComboBox中的每个元素上设置一个函子。

当你这样做(QComboBox::addData)[http://qt-project.org/doc/qt-5/qcombobox.html#addItem]时,你会注意到默认的userData参数。您可以在此处分配函子。

当你准备好使用它时,只需调用(QBomboBox::currentData)[http://qt-project.org/doc/qt-5/qcombobox.html#currentData-prop]将其取出并使用它。

至于将函子存储在QVariant中,您可以将函子存储在自己的数组中,只需将索引存储在该数组中,QVariant您可以使用QVariant(int typeId, const void * copy)直接将函子存储为 void*。

编辑:

从您的评论中,听起来像这样的事情可能是有序的:

将函数存储在std::map<std::string, std::map<std::string, std::function<X>>>中 其中外部映射的键是 from 类型,内部映射的键是 to 类型。

然后将密钥存储在QComboBoxuserData中。