将数组元素作为对象常量属性提取到临时位置

时间:2013-04-12 18:39:38

标签: c++ linux

我是高级PHP / Perl开发人员,也是C ++的相对初学者。

我所拥有的是一个类的对象数组,其中一个元素是子类的数组指针(如果我使用正确的术语)。 我需要的是逐个处理主数组并将它们的元素提取到一个单独的位置,如果它们满足某个条件(唯一的Name属性)。 然后用它的子数组输出提取的一个。然后输出原始文件。

我提出了各种解决方案,并尝试在您的帮助下确定哪种解决方案最佳使用。

详情。

这是头文件中我提到的两个类的一部分:

/// class to define the modificable parameters of the machine
class CMachineParameter {
    public:
        /// Short name: "Cutoff"
        char const *Name;
        /// Longer description: "Cutoff Frequency (0-7f)"
        char const *Description;
        /// recommended >= 0. If negative, minValue is represented as 0 in the pattern
        int MinValue;
        /// recommended <= 65535. Basically so that it can be represented in the pattern
        int MaxValue;
        /// flags. (see below)
        int Flags;
        /// default value for params that have MPF_STATE flag set
        int DefValue;
};

///\name CMachineParameter flags
///\{
    /// shows a line with no text nor knob
    int const MPF_NULL = 0;
    /// shows a line with the text in a centered label
    int const MPF_LABEL = 1;
    /// shows a tweakable knob and text
    int const MPF_STATE = 2;
///\}

///\name CFxCallback::CallbackFunc codes
///\{
    int const CBID_GET_WINDOW = 0;
///\}
///\name CMachineInfo::HostEvent codes
///\{
    /// Sent by the host to ask if this plugin uses the auxiliary column. return true or false.
    int const HE_NEEDS_AUX_COLUMN = 0;
///\}

/*////////////////////////////////////////////////////////////////////////*/

/// class defining the machine properties
class CMachineInfo {
    public:
        CMachineInfo(
            short APIVersion, int flags, int numParameters, CMachineParameter const * const * parameters,
            char const * name, char const * shortName, char const * author, char const * command, int numCols
        ) :
            APIVersion(APIVersion), PlugVersion(0), Flags(flags), numParameters(numParameters), Parameters(parameters),
            Name(name), ShortName(shortName), Author(author), Command(command), numCols(numCols)
        {}

        CMachineInfo(
            short APIVersion, short PlugVersion, int flags, int numParameters, CMachineParameter const * const * parameters,
            char const * name, char const * shortName, char const * author, char const * command, int numCols
        ) :
            APIVersion(APIVersion), PlugVersion(PlugVersion), Flags(flags), numParameters(numParameters), Parameters(parameters),
            Name(name), ShortName(shortName), Author(author), Command(command), numCols(numCols)
        {}

        /// API version. Use MI_VERSION
        short const APIVersion;
        /// plug version. Your machine version. Shown in Hexadecimal.
        short const PlugVersion;
        /// Machine flags. Defines the type of machine
        int const Flags;
        /// number of parameters.
        int const numParameters;
        /// a pointer to an array of pointers to parameter infos
        CMachineParameter const * const * const Parameters;
        /// "Name of the machine in listing"
        char const * const Name;
        /// "Name of the machine in machine Display"
        char const * const ShortName;
        /// "Name of author"
        char const * const Author;
        /// "Text to show as custom command (see Command method)"
        char const * const Command;
        /// number of columns to display in the parameters' window
        int numCols;
};

这是我的代码:

for(int i(0) ; i < MAX_MACHINES ; ++i) if(song.machine(i)) {
    if (song.machine(i)->GetDllName() == "") continue;
    Plugin & plug = *((Plugin*)song.machine(i));
    const psycle::plugin_interface::CMachineInfo  psycle_info = plug.GetInfo();

    // Process machine general info: psycle_info.Name, psycle_info.ShortName, psycle_info.Author etc

    if(psycle_info.numParameters > 0 && psycle_info.Parameters) {
        const int n = psycle_info.numParameters;
        for(int i(0) ; i < n; ++i) {
            const psycle::plugin_interface::CMachineParameter & psycle_param(*psycle_info.Parameters[i]);

            // Process machine's parameters: psycle_param.MinValue, psycle_param.MaxValue, psycle_param.DefValue, psycle_param.Flags etc

基本上,我有一个虚拟机列表,每个虚拟机都有其参数。只有ShortName不同(机器红色1,机器红色3,机器灰色4)。我需要按名称输出唯一的机器和它的参数(机器红色,机器灰色)。

在PHP中我会简单地创建和数组像$ original [psycle_info.Name] = array('author'=&gt; psycle_info.Author,'parameters'=&gt; array(psycle_param.MinValue,psycle_param.MaxValue,psycle_param) .DefValue,psycle_param.Flags));

在C ++中我发现我可以用std :: map和std :: vector STL库实现这样的功能。 这篇文章展示了一个非常类似的问题以及我从其他来源找到的解决方案: http://www.dreamincode.net/forums/topic/67804-c-multidimensional-associative-arrays/

但这样做的一般方法是什么? 也许我需要创建一个2个新的非const元素类?或者可能是一个简单的标准数组并且一直使用标准数组循环函数?

非常感谢您的关注!

PS。数据示例:

0.
Name: 'Red Machine v.098'
ShortName: 'Red Machine 1'
Author: 'Jeremy'
Parameters: 0(Name: 'OSC type', MinValue: 0, MaxValue: 255, DefValue:0), 1(Name: 'CutOff', MinValue: 0, MaxValue: 16555, DefValue: 1000), 2(Name: 'LFO', MinValue: 100, MaxValue: 30555, DefValue: 3000)

1.
Name: 'Red Machine v.098'
ShortName: 'Red Machine 2'
Author: 'Jeremy'
Parameters: 0(Name: 'OSC type', MinValue: 0, MaxValue: 255, DefValue:0), 1(Name: 'CutOff', MinValue: 0, MaxValue: 16555, DefValue: 1000), 2(Name: 'LFO', MinValue: 100, MaxValue: 30555, DefValue: 3000)

2.
Name: 'Yellow Machine v.2.4.5'
ShortName: 'Yellow Machine 1'
Author: 'Anthony'
Parameters: 0(Name: 'OSC 1 wave', MinValue: 0, MaxValue: 255, DefValue: 0), 1(Name: 'OSC 2 Wave', MinValue: 0, MaxValue: 255, DefValue: 0), 2(Name: 'OSC 3 Wave', MinValue: 0, MaxValue: 255, DefValue: 0)

3.
Name: 'Yellow Machine v.2.4.5'
ShortName: 'Yellow Machine 2'
Author: 'Anthony'
Parameters: 0(Name: 'OSC 1 wave', MinValue: 0, MaxValue: 255, DefValue: 0), 1(Name: 'OSC 2 Wave', MinValue: 0, MaxValue: 255, DefValue: 0), 2(Name: 'OSC 3 Wave', MinValue: 0, MaxValue: 255, DefValue: 0)

显然,作为这种情况下的输出,我需要有2台独特的机器。

PS2。我现在将进一步描述我拥有的和需要做的事情。

我有一个数组song.machine(i)

算法:

  1. 由于song.machine(i)信息有限,请循环播放以获取另一个对象并使用它进行操作
  2. 在循环中,从每首song.machine(i)创建插件(类对象)插件,这样终于可以得到 object CMachineInfo psycle_info via psycle_info = plug.GetInfo(); 它具有我们输出所需的所有信息
  3. 比较psycle_info.Name中的名称。如果已经显示,请跳到下一个。 否则,输出数据。
  4. 这是我包含的头文件,其中包含我最初显示的2个类: http://sourceforge.net/p/psycle/code/HEAD/tree/trunk/psycle-plugins/src/psycle/plugin_interface.hpp

    再次总结:因为我只能迭代地访问对象,而且我需要对数据执行一些操作(比如在Name中将所有空格替换为'+'),我想到了创建一个临时数组/类。但可能,创建一个简单的数组char nameShown [100]就足够了,我可以存储所有已显示的名称和每个song.machine(i)迭代,循环遍历整个nameShown,如果它包含当前Name,继续下一个。 我只是不想每次循环“nameShown”而在PHP中我们可以使用关联数组:所以我只能检查($ nameShown [$ Name])是否存在。 就像你说的那样在我看来也很头疼,我无法复制属性和参数,因为它们是常量! 看起来像一个非常简单的任务,但像我这样的初学者很难。 希望我已经涵盖了所有令人困惑的地方!

    PS4。我刚刚更新了主题的名称,因此它会包含“常量”提及。

    PS5。这是基本上应该做我需要的代码:

    std::string nameShown[100];
    bool should_skip = false;
    for (int k(0); k < i; k++) {
        if (nameShown[k] == psycle_info.Name) {
            should_skip = true;
        }
    }
    if(should_skip)  continue;
        nameShown[i] = psycle_info.Name;
    std::ostringstream l; l << "Plugin: " << psycle_info.Name; loggers::warning()(l.str());
    

    所以整篇文章看起来像是:

    std::string nameShown[100];
    for(int i(0) ; i < MAX_MACHINES ; ++i) if(song.machine(i)) {
        if (song.machine(i)->GetDllName() == "") continue;
        Plugin & plug = *((Plugin*)song.machine(i));
        const psycle::plugin_interface::CMachineInfo  psycle_info = plug.GetInfo();
    
        // Process machine general info: psycle_info.Name, psycle_info.ShortName, psycle_info.Author etc
        bool should_skip = false;
        for (int k(0); k < i; k++) {
            if (nameShown[k] == psycle_info.Name) {
                should_skip = true;
            }
        }
        if(should_skip)  continue;
        nameShown[i] = psycle_info.Name;
        std::ostringstream l; l << "Plugin: " << psycle_info.Name; loggers::warning()(l.str());
    
        if(psycle_info.numParameters > 0 && psycle_info.Parameters) {
            const int n = psycle_info.numParameters;
            for(int i(0) ; i < n; ++i) {
                const psycle::plugin_interface::CMachineParameter & psycle_param(*psycle_info.Parameters[i]);
    
                // Process machine's parameters: psycle_param.MinValue, psycle_param.MaxValue, psycle_param.DefValue, psycle_param.Flags etc
    

    插入循环之前的输出:

    log:  446322us: W: main: Plugin: Sublime 1.1
    log:  446413us: W: main: Plugin: Pooplog FM UltraLight0.68b
    log:  446497us: W: main: Plugin: Phantom 1.2
    log:  446581us: W: main: Plugin: Pooplog FM UltraLight0.68b
    log:  446649us: W: main: Plugin: FeedMe 1.2
    log:  446729us: W: main: Plugin: Drum Synth v.2.5
    log:  446793us: W: main: Plugin: Sublime 1.1
    log:  446876us: W: main: Plugin: Arguru Compressor
    log:  446945us: W: main: Plugin: Pooplog Filter 0.06b
    log:  447016us: W: main: Plugin: Slicit
    log:  447095us: W: main: Plugin: EQ-3
    log:  447163us: W: main: Plugin: Arguru Compressor
    log:  447231us: W: main: Plugin: Pooplog Filter 0.06b
    log:  447294us: W: main: Plugin: Koruz
    log:  447361us: W: main: Plugin: Pooplog Filter 0.06b
    log:  447425us: W: main: Plugin: EQ-3
    log:  447496us: W: main: Plugin: Arguru Compressor
    log:  447558us: W: main: Plugin: EQ-3
    

    后:

    log:  414242us: W: main: Plugin: Sublime 1.1
    log:  414331us: W: main: Plugin: Pooplog FM UltraLight0.68b
    log:  414415us: W: main: Plugin: Phantom 1.2
    log:  414499us: W: main: Plugin: FeedMe 1.2
    log:  414560us: W: main: Plugin: Drum Synth v.2.5
    log:  414622us: W: main: Plugin: Arguru Compressor
    log:  414694us: W: main: Plugin: Pooplog Filter 0.06b
    log:  414761us: W: main: Plugin: Slicit
    log:  414830us: W: main: Plugin: EQ-3
    log:  414897us: W: main: Plugin: Koruz
    

    注意,在新添加的循环中,我尝试使用for(int k(0); k&lt; sizeof(nameShown); k ++),对于PHP程序员来说,这听起来更明显,但即使在第一首song.machine(i)迭代,它循环了很多次然后给出一个段错误,所以我把它改为“k&lt; i”。

    这基本上就是我所需要的。并且只是好奇它是否是正确的做法,因为每次通过滤波器阵列的不存在的元素循环听起来对我来说是原始的和无效的。

    另一件事是,在我刚刚完成的独特机器的输出之后,我需要输出整个列表。那么,我必须创建整个song.machine(i)再循环,所以为了避免代码重复,我想到了将我需要的值提取到更简单的数据句柄中。在PHP中,我会使用关联数组。

    再次总结一下,首先我需要输出唯一的机器列表,然后为每个列表设置不同的详细信息。

    可能,因为解释似乎很复杂(但实际上这是一个非常简单的任务,XML生成),我将坚持在这种情况下可能过于奢华的代码最有效的方法。

1 个答案:

答案 0 :(得分:0)

让我们从清楚的东西开始,你有一个阵列song.machine(i)

算法:

  1. 比较song.machine(i)
  2. 中的名称
  3. 如果Match,Dynamic Cast song.machine(i)to Plugin(class object)plug
  4. 使用它通过psycle_info = plug.GetInfo();
  5. 制作对象CMachineInfo psycle_info
  6. 处理此数据/输出/ 提取它?
  7. 让我们从你在课堂定义中所写的内容开始:

    • <强>字符*

      一个char *,声明在堆/ Stack上分配内存。这反过来必须删除,因为对象在应用程序中被销毁。您的代码创建了很多对象,然后复制它们,将它们传递给另一个对象。未分配指针的存储器位置(例如new [] operator / malloc),它最终将被任何类型/对象数据覆盖。有时您可能不会出现分段错误,但在这种情况下您的数据肯定不安全。

      在这种情况下,您应该使用字符串,内置char *或char数组。他们自己分配和销毁。因此,没有内存错误以及string.compare()等函数可以很容易地使用。参考here

    • Copy / Assignment Operator

      复制和赋值运算符(例如CMachineInfo obj1 = CMachineInfo Obj2)处理类的对象,并且如名称所示,它们意味着在对象之间传递数据。 C ++默认为您定义运算符。但是当你处理指针时,这种行为很棘手。您可以通过定义所需内容来覆盖它(参见下文)。

    • Const成员

      在c ++类中,成员可以是const(没有解决的整数)和规则,具有const成员的对象不能在COPY AND ASSIGNMENT OPERATOR中使用。这很容易理解。你有一个对象说obj1,现在你想把它的所有内容复制到另一个对象obj2(同一个类)。创建Obj2时,它的成员被定义为常量,现在您正在尝试覆盖这些值。编译器不允许这样做。解决此类问题的方法是将此类成员声明为私有。不允许私有成员直接访问(例如pyscle_info.Name)。你必须编写一个公共函数,然后可以提供对它们的访问权限(例如pyscle_info.GET_NAME_OF_MACHINE();)

    让我们看看修改后的代码CMachineParameter:

    class CMachineParameter{
    
    public:
    
        CMachineParameter(string Name, string Description, int MinValue, 
                            int MaxValue, int Flags, int DefValue
        ): Name(Name), Description(Description), MinValue(MinValue), MaxValue(MaxValue), Flags(Flags), DefValue(DefValue)
        {}
    
        /*DeFault Constructor*/
        CMachineParameter(): Name("TEST"), Description("Temp Object")
        {}
    
        //  Copy Constructor
        CMachineParameter(const CMachineParameter &TO_BE_COPIED)
        : Name(TO_BE_COPIED.Name), Description(TO_BE_COPIED.Description), MinValue(TO_BE_COPIED.MinValue),
          MaxValue(TO_BE_COPIED.MaxValue) ,Flags(TO_BE_COPIED.Flags), DefValue(TO_BE_COPIED.DefValue)
        {}
    
        //  Assignment Operator
        CMachineParameter & operator=(const CMachineParameter & TO_BE_Assigned)
        {
            if(this != &TO_BE_Assigned)
            {
                Name        = TO_BE_Assigned.Name;
                Description = TO_BE_Assigned.Description;
                MinValue    = TO_BE_Assigned.MinValue;
                MaxValue    = TO_BE_Assigned.MaxValue;
                Flags       = TO_BE_Assigned.Flags;
                DefValue    = TO_BE_Assigned.DefValue;
            }
    
            return *this;
        }
    
        void show(void) const;
    
        /*To access the Private members*/
        std::string GET_NAME(void) const;
    
        /// recommended >= 0. If negative, minValue is represented as 0 in the pattern
        int MinValue;
        /// recommended <= 65535. Basically so that it can be represented in the pattern
        int MaxValue;
        /// flags. (see below)
        int Flags;
        /// default value for params that have MPF_STATE flag set
        int DefValue;
    
    private:
        /*
         * Making them as Private as Assignment and copy operator Cannot be used with Const members.
        */
        /// Short name: "Cutoff"
        string Name;
        /// Longer description: "Cutoff Frequency (0-7f)"
        string Description;
    };
    
    void CMachineParameter::show() const
    {
        cout << "------------------------------------------------------\n";
        cout << "My Machine " << Name << endl
             << "\t" << Description << endl
             << "\tMinValue:    " << MinValue << endl
             << "\tMaxValue:    " << MaxValue << endl
             << "\tFlags:       " << Flags << endl
             << "\tDefValue:    " << DefValue << endl;
        cout << "------------------------------------------------------\n";
    }
    
    std::string CMachineParameter::GET_NAME(void) const
    {
        return Name;
    }
    

    对于CMachineInfo,您需要实现分配/复制运算符。我实现了一个CMachineParameter const *的向量。

    class CMachineInfo {
        public:
            CMachineInfo(
                short APIVersion, int flags, int numParameters,
                string name, string shortName, string author, string command, int numCols
            ) :
                APIVersion(APIVersion), PlugVersion(0), Flags(flags), numParameters(numParameters),
                Name(name), ShortName(shortName), Author(author), Command(command), numCols(numCols)
            {}
    
            CMachineInfo(
                short APIVersion, short PlugVersion, int flags, int numParameters,
                string name, string shortName, string author, string command, int numCols
            ) :
                APIVersion(APIVersion), PlugVersion(PlugVersion), Flags(flags), numParameters(numParameters),
                Name(name), ShortName(shortName), Author(author), Command(command), numCols(numCols)
            {}
    
            //  Copy Constructor
            CMachineInfo (const CMachineInfo &TO_BE_COPIED)
            : APIVersion(TO_BE_COPIED.APIVersion), PlugVersion(TO_BE_COPIED.PlugVersion),
            Flags(TO_BE_COPIED.Flags), numParameters(TO_BE_COPIED.numParameters), Name(TO_BE_COPIED.Name),
            ShortName(TO_BE_COPIED.ShortName), Author(TO_BE_COPIED.Author), Command(TO_BE_COPIED.Command),
            numCols(TO_BE_COPIED.numCols), Parameter(TO_BE_COPIED.Parameter)
            {}
    
            //  Assignment Operator
            CMachineInfo & operator=(const CMachineInfo &TO_BE_Assigned)
            {
                if(this != &TO_BE_Assigned)
                {
                    APIVersion      = TO_BE_Assigned.APIVersion; 
                    PlugVersion     = TO_BE_Assigned.PlugVersion;
                    Flags           = TO_BE_Assigned.Flags;
                    numParameters   = TO_BE_Assigned.numParameters; 
                    Name            = TO_BE_Assigned.Name;
                    ShortName       = TO_BE_Assigned.ShortName; 
                    Author          = TO_BE_Assigned.Author; 
                    Command         = TO_BE_Assigned.Command;
                    numCols         = TO_BE_Assigned.numCols;
                    Parameter       = TO_BE_Assigned.Parameter;
                }
                return *this;
            }
    
            void SHOW(void) const;
    
            /// a pointer to an array of pointers to parameter infos
            /// CMachineParameter const * const * const Parameters;
            vector<CMachineParameter const *> Parameter;
    
            /// "Name of the machine in listing"
            std::string Name;
    
            /// "Name of the machine in machine Display"
            std::string ShortName;
    
            /// "Name of author"
            std::string Author;
    
            /// "Text to show as custom command (see Command method)"
            std::string Command;
    
            /// number of columns to display in the parameters' window
            int numCols;
    
    private:
            /// API version. Use MI_VERSION
            short APIVersion;
    
            /// plug version. Your machine version. Shown in Hexadecimal.
            short PlugVersion;
    
            /// Machine flags. Defines the type of machine
            int Flags;
    
            /// number of parameters.
            int numParameters;
    };
    
    void CMachineInfo::SHOW() const
    {
        cout << "My Machine IS: " << endl
             << "\tAPIVersion:    " << APIVersion << endl
             << "\tPlugVersion:   " << PlugVersion << endl
             << "\tFlags:         " << Flags << endl
             << "\tnumParameters: " << numParameters << endl
             << "\tName:          " << Name << endl
             << "\tShortName:     " << ShortName << endl
             << "\tAuthor:        " << Author << endl
             << "\tCommand:       " << Command << endl
             << "\tnumCols:       " << numCols << endl;
    }