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

我有一个应用程序,在其中我可以按字符串文字更改数据。

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


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

c++ - 如何使当前的编码结构更灵活-LMLPHP

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

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条件。

例如对于USESHADOW,命令看起来像。

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


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

   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个。

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

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

最佳答案

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

所有你需要的是:


std::map链接输入文本与所需的行为。
一堆函数都具有相同的原型,可以执行所需的行为。当行为简单时,Lambda表达式是一个不错的选择,因为它们会将所有相关代码都放在一个位置


开始了!

    #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 ++编译器。

关于c++ - 如何使当前的编码结构更灵活,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57882270/

10-11 22:24
查看更多