questions about data strcuture

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Doe

    #1

    questions about data strcuture

    Hi,

    I am currently developping a software where items that will be inserted
    into a graphical widget ListCtrl are first defined in static array as
    shown below :

    enum TUiContext
    {
    EUiContextMain = 0,
    EUiContextSched ule,
    EUiContextSetti ngs,
    EUiContextSubsc ription,
    EUiContextCount
    };

    typedef struct
    {
    int TextId;
    int ImgId;
    int Param;
    int nOptInfo;
    TCHAR szImgName[MAX_PATH];
    } ListInfo_t, *LPListInfo_t;


    ListInfo_t CMainView::ms_l istInfo_Main[]=
    {
    // String ID, Img, Param = CmdBarId Enabled ImgName
    { IDS_MENU_BACKUP , 0, IDM_MENU_CMDBAR _BACKUP, TRUE, _T( "" ) },
    { IDS_MENU_SCHEDU LE, 2, IDM_MENU_CMDBAR _OPTIONS, TRUE, _T( "" ) },
    { IDS_MENU_RESTOR E, 1, IDM_MENU_CMDBAR _RESTORE, TRUE, _T( "" ) },
    { IDS_MENU_MANAGE _SUBSCRIPTION, -1, IDM_MENU_MANAGE _SUBSCRIPTION,
    TRUE, _T( "Menu_Account_M anage.png" ) },
    };

    ListInfo_t CMainView::ms_l istInfo_Options[]=
    {
    // String ID, Img, Param = CmdBarId
    { IDS_MENU_FREQUE NCY, 0, IDM_MENU_SCHEDU LER, TRUE, _T( "" ) },
    { IDS_MENU_CONTEN T, 1, IDM_MENU_SELECT DB, TRUE, _T( "" ) },
    };
    ....


    Actually in functions of some parameters, some items won't be inserted
    and the field nOptInfo is used for this purpose. If this field equals 1
    it will be inserted into the List.

    So I have a method called InitResources that check the config parameters
    and update nOptInfo for each array.
    Once this has been done, I build a vector as shown below :

    void CMainView::Init Resources()
    {
    std::vector<Lis tInfo_tvecListI nfo;
    std::map<TUiCon text, std::vector<Lis tInfo_t listMap;

    // Test config parameters and update nOptInfo
    ...

    //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
    // Now build vector from ms_listInfo_Mai n
    //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
    vecListInfo.cle ar()
    for (int i = 0; i < _countof(ms_lis tInfo_Main); i++)
    {
    if (ms_listInfo_Ma in[i].nOptInfo == TRUE){
    vecListInfo.pus h_back(ms_listI nfo_Main[i]);
    }
    }
    listMap[ EUiContextMain ] = vecListInfo;

    //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
    // Now build vector from ms_listInfo_Opt ions
    //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
    vecListInfo.cle ar()
    for (int i = 0; i < _countof(ms_lis tInfo_Options); i++)
    {
    if (ms_listInfo_Op tions[i].nOptInfo == TRUE){
    vecListInfo.pus h_back(ms_listI nfo_Options[i]);
    }
    }
    listMap[ EUiContextSched ule] = vecListInfo;
    ...

    }

    I find all this code very ugly and I would like to suggestion to improve
    it. I am doing all this because I am switching between different
    graphical context and before to do it I save the index of current
    selected item in my ListCtrl.






  • Jerry Coffin

    #2
    Re: questions about data strcuture

    In article <48d39c19$0$293 57$426a34cc@new s.free.fr>,
    mosfet@anonymou s.org says...
    typedef struct
    {
    int TextId;
    int ImgId;
    int Param;
    int nOptInfo;
    TCHAR szImgName[MAX_PATH];
    } ListInfo_t, *LPListInfo_t;
    Since you're apparently using nOptInfo as a boolean, I'd advise defining
    it as a boolean. Although it's unrelated to any of the questions at
    hand, I'd look carefully at whether szImgName couldn't be an std::string
    as well.
    vecListInfo.cle ar()
    Rather than defining well ahead of time and clearing when used, I'd
    define this immediately before use, in which case it'll definitely be
    empty.
    for (int i = 0; i < _countof(ms_lis tInfo_Main); i++)
    {
    if (ms_listInfo_Ma in[i].nOptInfo == TRUE){
    vecListInfo.pus h_back(ms_listI nfo_Main[i]);
    }
    }
    Then I'd replace this with std::remove_cop y_if:

    std::remove_cop y_if(ms_listInf o_Main, end(ms_listInfo _Main), isOpt());

    where isOpt looks something like:

    struct isOpt {
    bool operator()(List Info_t const &li) { return !li.nOptInfo; }
    };

    At least if I understand your code correctly, I'd then create a single
    vector containing (pointers to?) the data you currently have in your
    ms_ListInfo_*. I'd then turn the bit of code above (the part that uses
    std::remove_cop y_if) into a small function (which, for now, I'll call
    build_list) that could be called in a loop:

    for (int i=0; i<EUiContextCou nt; i++)
    listMap[i] = build_list(i, ms_ListInfo);

    then I'd note that this is really equivalent to std::transform:

    std::transform( ms_ListInfo.beg in(), ms_ListInfo.end (),
    listMap, build_list());

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.

    Comment

    • Pascal J. Bourguignon

      #3
      Re: questions about data strcuture

      John Doe <mosfet@anonymo us.orgwrites:
      Hi,
      >
      I am currently developping a software where items that will be
      inserted into a graphical widget ListCtrl are first defined in static
      array as shown below :
      >
      enum TUiContext
      {
      EUiContextMain = 0,
      EUiContextSched ule,
      EUiContextSetti ngs,
      EUiContextSubsc ription,
      EUiContextCount
      };
      >
      typedef struct
      {
      int TextId;
      int ImgId;
      int Param;
      int nOptInfo;
      TCHAR szImgName[MAX_PATH];
      } ListInfo_t, *LPListInfo_t;
      >
      >
      ListInfo_t CMainView::ms_l istInfo_Main[]=
      {
      // String ID, Img, Param = CmdBarId Enabled ImgName
      { IDS_MENU_BACKUP , 0, IDM_MENU_CMDBAR _BACKUP, TRUE, _T( "" ) },
      { IDS_MENU_SCHEDU LE, 2, IDM_MENU_CMDBAR _OPTIONS, TRUE, _T( "" ) },
      { IDS_MENU_RESTOR E, 1, IDM_MENU_CMDBAR _RESTORE, TRUE, _T( "" ) },
      { IDS_MENU_MANAGE _SUBSCRIPTION, -1,
      IDM_MENU_MANAGE _SUBSCRIPTION, TRUE, _T( "Menu_Account_M anage.png"
      ) },
      };
      >
      ListInfo_t CMainView::ms_l istInfo_Options[]=
      {
      // String ID, Img, Param = CmdBarId
      { IDS_MENU_FREQUE NCY, 0, IDM_MENU_SCHEDU LER, TRUE, _T( "" ) },
      { IDS_MENU_CONTEN T, 1, IDM_MENU_SELECT DB, TRUE, _T( "" ) },
      };
      ...
      >
      >
      Actually in functions of some parameters, some items won't be inserted
      and the field nOptInfo is used for this purpose. If this field equals
      1 it will be inserted into the List.
      >
      So I have a method called InitResources that check the config
      parameters and update nOptInfo for each array.
      Once this has been done, I build a vector as shown below :
      >
      void CMainView::Init Resources()
      {
      std::vector<Lis tInfo_tvecListI nfo;
      std::map<TUiCon text, std::vector<Lis tInfo_t listMap;
      >
      // Test config parameters and update nOptInfo
      ...
      >
      //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
      // Now build vector from ms_listInfo_Mai n
      //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
      vecListInfo.cle ar()
      for (int i = 0; i < _countof(ms_lis tInfo_Main); i++)
      {
      if (ms_listInfo_Ma in[i].nOptInfo == TRUE){
      vecListInfo.pus h_back(ms_listI nfo_Main[i]);
      }
      }
      listMap[ EUiContextMain ] = vecListInfo;
      >
      //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
      // Now build vector from ms_listInfo_Opt ions
      //$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$ $$$$$$$$$$$
      vecListInfo.cle ar()
      for (int i = 0; i < _countof(ms_lis tInfo_Options); i++)
      {
      if (ms_listInfo_Op tions[i].nOptInfo == TRUE){
      vecListInfo.pus h_back(ms_listI nfo_Options[i]);
      }
      }
      listMap[ EUiContextSched ule] = vecListInfo;
      ...
      >
      }
      >
      I find all this code very ugly
      Yes, it is.
      and I would like to suggestion to
      improve it. I am doing all this because I am switching between
      different graphical context and before to do it I save the index of
      current selected item in my ListCtrl.
      You need more abstraction. Define classes to hold your data, instead
      of storing it in POD (plain old data) structures. When you build
      these objects, they will be able to implement any consistency check
      you need, so you won't have to check the POD and you won't have to
      convert.


      With smart use of operators, such as operator<< or operator, you can
      make it nice enough. Optional attributes can be fed optionnaly, after
      the construction.

      Since you seem to have here a hierarchical structure of contexts, be
      sure to make them have reference semantics, not value semantics,
      otherwise putting them in a std container would project them and lose
      data.



      Instead of using #define for constants or enums, you should use true
      const or enum declarations, with the help of namespaces to have nice
      names and avoid collisions:

      namespace ids {
      namespace menu {
      enum menu { backup, schedule, restore, manage_subscrip tion }; }}

      Notice the duplication of namespace X { enum X which allows to use
      the namespace to qualify the enum constants, without having to
      reinvent the wheel by prefixing the constants with the enum name to
      avoid collisions.



      void CMainView::Init Resources()
      {
      MainContext mctxt;
      mctxt<<(MInfo(i ds::menu::backu p, idm::menu::cmdb ar::backup) <<Image(0))
      <<(MInfo(ids::m enu::schedule,i dm::menu::cmdba r::options) <<Image(2))
      <<(MInfo(ids::m enu::restore, idm::menu::cmdb ar::restore) <<Image(1))
      <<(MInfo(ids::m enu::manage_sub scription,idm:: menu::manage::s ubscription)
      <<ImageName ("Menu_Account_ Manage.png"))
      <<(MInfo(ids::m enu::wild, idm::menu::cmdb ar::broken) <<Disabled()
      <<Color(ids::co lor::red)
      <<Etc("you can define whatever attribute you want"));

      ScheduleContext sctxt;
      sctxt<<(SInfo(i ds::menu::frequ ency,idm::menu: :scheduler) <<Image (0))
      <<(SInfo(ids::m enu::content, idm::menu::sele ctdb) <<Image (1));

      std::map<TUiCon text,Contextlis tMap;

      // Test config parameters and update nOptInfo
      // ...
      listMap[EUiContextMain ]=nctxt;
      listMap[EUiContextSched ule]=sctxt;
      // ...
      }


      --
      __Pascal Bourguignon__

      Comment

      Working...