簡體   English   中英

將數組的元素作為對象的常量屬性提取到一個臨時位置

[英]Extract array's elements as object's constant properties into a temporary place

我是高級PHP / Perl開發人員,也是C ++的相對入門者。

我所擁有的是一個類的對象數組,而其中的一個元素又是子類的數組指針(如果我使用正確的術語)。 我需要的是一個主數組一個接一個地處理,如果滿足特定條件(唯一的Name屬性),則將其元素提取到一個單獨的位置。 然后輸出提取的子數組。 然后輸出原稿。

我想出了各種解決方案,並嘗試定義哪種方法最適合您的幫助。

細節。

這些是我提到的2個類的頭文件部分:

/// 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'=> psycle_info.Author,'parameters'=> array(psycle_param.MinValue,psycle_param.MaxValue,psycle_param.DefValue,psycle_param。標志));

在C ++中,我發現可以使用std :: map和std :: vector STL庫實現類似的功能。 本文顯示了一個非常相似的問題以及我也從其他來源獲得的解決方案: http : //www.dreamincode.net/forums/topic/67804-c-multiDimension-associative-arrays/

但是,這樣做的一般方式是什么? 也許我需要創建2個新的非常量元素類? 還是一個簡單的標准數組並一直使用標准數組循環功能?

非常感謝您的關注!

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)創建Plugin(類對象)插件,以便最終可以通過psycle_info = plug.GetInfo()獲得對象CMachineInfo psycle_info。 其中包含我們需要輸出的所有信息
  3. 比較psycle_info.Name中的名稱。 如果已經顯示,請跳到下一個。 否則,輸出數據。

這是我包含的頭文件,其中包含我最初顯示的2個類: http : //sourceforge.net/p/psycle/code/HEAD/tree/trunk/psycle-plugins/src/psycle/plugin_interface.hpp

再次總結一下:由於我只能迭代訪問對象,而且我需要對數據執行一些操作(例如將所有空格替換為Name中的“ +”),所以我想到了創建一個臨時數組/類。 但是可能創建一個簡單的數組char nameShown [100]就足夠了,在這里我可以存儲所有已經顯示的名稱以及每首歌曲。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

請注意,在新添加的周期中,我嘗試將其用於(int k(0); k <sizeof(nameShown); k ++),對於PHP程序員來說,這聽起來更明顯,但即使在第一首歌上也是如此。 (i)迭代,它會自行循環很多次,然后產生段錯誤,因此我將其更改為“ k <i”。

基本上這就是我所需要的。 我只是好奇這是否是正確的方法,因為每次循環遍歷過濾器數組中不存在的元素對我來說都是原始且無效的。

另一件事是,在我剛剛完成輸出唯一機器之后,我需要輸出整個列表。 那么,我將不得不再次創建整個song.machine(i)周期,因此為了避免代碼重復,我想到將所需的值提取到一個更簡單的數據句柄中。 在PHP中,我會為此使用關聯數組。

再次總結一下,首先我需要輸出唯一的機器列表,然后為所有機器設置不同的詳細信息。

可能解釋起來似乎很復雜(但實際上這是一個非常簡單的任務,XML生成),我會堅持可行的方法,在這種情況下,尋找最佳的代碼可能太奢侈了。

讓我們先說清楚,您有一個數組song.machine(i)

算法:

  1. 比較song.machine中的名稱(i)
  2. 如果匹配,則動態將song.machine(i)投射到插件(類對象)插件
  3. 使用它通過psycle_info = plug.GetInfo();將對象CMachineInfo設置為psycle_info。
  4. 處理此數據/輸出/ 提取它?

讓我們從您在類定義中編寫的內容開始:

  • 字符*

    聲明的char *在堆/堆棧上分配內存。 反過來,由於在應用程序中銷毀了對象,因此必須將其刪除。 您的代碼創建了很多對象,然后您將它們復制,然后將它們傳遞給另一個對象。 指針的內存位置未分配(例如new []運算符/ malloc),最終將被任何類型/對象數據覆蓋。 有時您可能不會遇到分段錯誤,但是在這種情況下您的數據肯定不安全。

    在這種情況下,您應該使用string ,內置char *或char數組。 他們自行分配和銷毀。 因此,沒有內存故障,像string.compare()之類的函數也易於使用。 請參考這里

  • 復制/分配運算符

    復制和分配運算符(例如CMachineInfo obj1 = CMachineInfo Obj2)在類的對象上工作,顧名思義,它們旨在在對象之間傳遞數據。 默認情況下,C ++為您定義了運算符。 但是,在處理指針時,該行為很棘手。 您可以通過定義所需內容來覆蓋它(請參見下文)。

  • 委員

    在c ++類中,成員可以是具有規則的const(沒有變通的整數), 帶有const成員的對象不能在COPY AND ASSIGNMENT OPERATOR中使用 這很容易理解。 您有一個對象obj1,現在您要將其所有內容復制到另一個對象obj2(同一類)。 創建Obj2后,將其成員定義為常量,現在您正嘗試覆蓋這些值。 編譯器將不允許這樣做。 解決此問題的方法是,您將此類成員聲明為private 不允許私人成員直接訪問(例如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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM