如何使当前的编码结构更灵活 [英] How to make the current coding structure more flexible

查看:60
本文介绍了如何使当前的编码结构更灵活的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要当前工作流程的帮助,尽管一切都可以按预期进行,但我想使结构更坚固.

I need help with my current workflow , though everthing works as expected but i would like to make the structure more robust.

我有一个应用程序,在其中我可以通过字符串文字来更改数据.

I have a application where i change the data by string literal.

WAVEFRONT*TREEVIEW*Main$Text*GEOMETRY*TEXT SET TEXT ABCD

如图所示,其中"Main $ Text"是树结构的数据项的路径.

as shown in the image where "Main$Text" is the path of the data item the the tree structure.

1)第一步->我有一个类来处理命令字符串并采取适当的措施.

1) First step-> i have a class to handle the command string and take appropriate action.

int SumCommandInterface::receiveCommand(std::string stdtsrCommand , const QModelIndex & RootIndex, TreeModel *myModel)
{   
    std::vector<std::string> vectorStrCommand;
    std::vector<std::string> vectorStrStarSplit;
    std::vector<std::string> vectorStrContainerNames;   
    boost::algorithm::trim(stdtsrCommand);
    boost::split(vectorStrCommand, stdtsrCommand, boost::is_any_of(" "), boost::token_compress_on);
    boost::split(vectorStrStarSplit, vectorStrCommand[0], boost::is_any_of("*"), boost::token_compress_on); 
    if (vectorStrStarSplit[1] == "TREEVIEW")  // for tree view
    {
        if (vectorStrCommand.size() < 4)
            return -1;

        boost::split(vectorStrContainerNames, vectorStrStarSplit[2], boost::is_any_of("$"), boost::token_compress_on);
        TreeItem* itm;
        QModelIndex  Index = RootIndex;
        for (auto &strName : vectorStrContainerNames)
        {
            if (!getTreeItem(strName, Index, myModel, &itm))
            {
                return 0;
            }
            Index = myModel->indexForTreeItem(itm);         
        }
        PluginTypeLookUp lookUp = lookUpPluginMap[vectorStrStarSplit[3]];
        Container *cont = itm->GetContainer();
        switch (lookUp)
        {
        case PluginTypeLookUp::GEOMTERY: // This can be function , texture etc, currently only showing code for geometry
        {
            Geometry *geom = cont->GetGeometry();
            if(vectorStrCommand[2] == "TEXT" )
                setFontPluginParam< Geometry , std::string >( geom, vectorStrCommand[2], vectorStrCommand[3]);

            if (vectorStrCommand[2] == "USESHADOW")
                setFontPluginParam< Geometry , bool >(geom, vectorStrCommand[2], (vectorStrCommand[3] == "0" ? false : true) );

            if (vectorStrCommand[2] == "FONTSIZE" || vectorStrCommand[2] ==  "SHADOWDIRECTION")
                setFontPluginParam< Geometry, int >(geom, vectorStrCommand[2], std::stoi(vectorStrCommand[3]) );

            if (vectorStrCommand[2] == "SHADOWDISTANCE" || vectorStrCommand[2] == "SHADOWOPACITY" || vectorStrCommand[2] == "KERNING" )
                setFontPluginParam< Geometry, float >(geom, vectorStrCommand[2], std::stof(vectorStrCommand[3]));

        }
        break;
        case PluginTypeLookUp::TEXTURE:
        {
            Sum_Texture_2D *texture;
            texture = cont->GetTexturePointer();

            if(vectorStrCommand[2] == "TEXTUREPATH" )
                setTexturePluginParam< Sum_Texture_2D, std::string >(texture, vectorStrCommand[2], vectorStrCommand[3]);

            if (vectorStrCommand[2] == "POSITIONX" || vectorStrCommand[2] ==  "POSITIONY" || vectorStrCommand[2] ==  "POSITIONZ" || vectorStrCommand[2] ==  "SCALINGX" || vectorStrCommand[2] ==  "SCALINGY" || vectorStrCommand[2] ==  "SCALINGZ" || vectorStrCommand[2] ==  "ROTATIONX" || vectorStrCommand[2] ==  "ROTATIONY" || vectorStrCommand[2] ==  "ROTATIONZ ")
            {
                setTexturePluginParam< Sum_Texture_2D, float >(texture, vectorStrCommand[2], std::stof(vectorStrCommand[3]));
            }

            break;
        }
        default:
            break;
        }
        return 1;
    }   
    return 0;
}

我在命令中传递了几何参数,并据此获得了if条件.

i am passing the geometry parameter in command and based on that i have a if condition.

例如USESHADOW的命令如下所示.

for example for USESHADOW the command would look like.

    WAVEFRONT*TREEVIEW*AMain$Text*GEOMETRY*TEXT SET USESHADOW 1

如果Geometry参数为TEXT,则命令如下所示.

if Geometry parameter is TEXT the command would look like.

   WAVEFRONT*TREEVIEW*AMain$Text*GEOMETRY*TEXT SET TEXT ABC





        case PluginTypeLookUp::GEOMTERY: // This can be function , texture 
        etc, currently only showing code for geometry
            {
                Geometry *geom = cont->GetGeometry();
                if(vectorStrCommand[2] == "TEXT" )
                    setFontPluginParam< Geometry , std::string >( geom, vectorStrCommand[2], vectorStrCommand[3]);

                if (vectorStrCommand[2] == "USESHADOW")
                    setFontPluginParam< Geometry , bool >(geom, vectorStrCommand[2], (vectorStrCommand[3] == "0" ? false : true) );

                if (vectorStrCommand[2] == "FONTSIZE" || vectorStrCommand[2] ==  "SHADOWDIRECTION")
                    setFontPluginParam< Geometry, int >(geom, vectorStrCommand[2], std::stoi(vectorStrCommand[3]) );

                if (vectorStrCommand[2] == "SHADOWDISTANCE" || vectorStrCommand[2] == "SHADOWOPACITY" || vectorStrCommand[2] == "KERNING" )
                    setFontPluginParam< Geometry, float >(geom, vectorStrCommand[2], std::stof(vectorStrCommand[3]));

            }
            break;

我当前面临的问题是,如果我有30个不同的几何参数,那么如果条件需要添加30个.

The current issue i am facing is that if i have 30 different geometry parameters i would need to add 30 if conditions.

如果我添加更多几何类型,我将再次需要重新访问此代码并添加更多参数.

If i add more geometry types i would again need to revisit this code and add more parameters.

我能以更优雅的方式处理此步骤吗?

can i handle this step in more graceful way.

推荐答案

基本的映射查找.这些使基于表的菜单系统和简单的解析器变得非常出色.它们可能不是最快的,但是代码确实很简单 1 ,易于阅读,而且很难搞清楚.添加新命令或关键字就像在 map 的初始化程序中添加另一行一样简单.

A basic mapped look-up. These make great table-based menu systems and simple parsers. They may not be the fastest, but the code is really simple1, easy to read, and hard to screw up. Adding a new command or keyword can be as simple as adding another line to the map's initializer.

您需要的是:

  1. 一个 std :: map ,用于将输入文本与所需的行为链接起来.
  2. 一堆具有相同原型的函数,可以执行所需的行为.当行为简单时,Lambda表达式是一个不错的选择,因为它们会将所有相关代码都放在一个地方
  1. A std::map to link the input text with the desired behaviour.
  2. A bunch of functions all with the same prototype that execute the desired behaviours. Lambda expressions are a great option when the behavour is simple since they keep all of the related code in one place

我们在这里!

    #include <map>
    #include <functional>
    #include <string>
    #include <iostream>
    #include <vector>

    // standing in for setFontPluginParam
    template<class T>
    void template_func(const std::string& name, const T & data)
    {
        std::cout << name << ":" << data << std::endl;
    }

    // functions to convert the data to the correct type for template_func
    void text_func(const std::string & name, const std::string & text)
    {
        std::cout << "text_func "; // make output easier to interpret
        template_func(name, text); // call correct template specialization
    }

    void int_func(const std::string & name, const std::string & num)
    {
        std::cout << "int_func ";
        template_func(name, std::stoi(num));
    }

    // maps the name to the function. Note: If you're not messing around with lambdas or 
    // member functions, an old school function pointer may work better that std::function
    std::map<std::string, std::function<void(const std::string &, const std::string &)>> call_function =
    {
     {"TEXT", text_func},
     {"INT", int_func},
     // same as above, but with a lambda expression to keep everything all in one place
     {"DOUBLE", [](const std::string & name, const std::string & num) {
         std::cout << "double_func ";
         template_func(name, std::stod(num));
      }}
    };

    void demo(const std::vector<std::string> & vectorStrCommand)
    {
        // uses map to look up correct function, then calls it
        // This is basically all that's left of the if/else if chain
        call_function[vectorStrCommand[2]](vectorStrCommand[2], vectorStrCommand[3]);
    }

    int main()
    {
        demo({"whatever", "whatever", "INT", "42"});
        demo({"whatever", "whatever", "TEXT", "I am the very model of a modern major general..."});
        demo({"whatever", "whatever", "DOUBLE", "3.14"});
    }

1 因为它很简单,所以最适合简单的事情.不要尝试编写这样的C ++编译器.

1 Because it's simple it works best for simple things. Don't try to write a C++ compiler like this.

这篇关于如何使当前的编码结构更灵活的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆