Iterate Over Struct; Easily Display Struct Fields And Values In a RichEdit Box

后端 未结 9 1873
离开以前
离开以前 2020-12-13 22:10

Is there an easier way to display the struct fields and their corresponding values in RichEdit control?

This is what I am doing now:

<
9条回答
  •  不思量自难忘°
    2020-12-13 22:38

    There is no way to iterate the members of a struct unless you build your own metadata to describe the struct. The C++ compiler simply doesn't emit the information you would need automatically.

    However, with a bit of macro magic, you can build the metadata you would need pretty easily. I wrote some code to do this (actually a full blown Windows custom control) many years ago and I still use it all the time.

    The basic trick is to use a bit macro magic of get the compiler to help you build the metadata.

    // this is the structure I want to iterate
    typedef struct {
       int foo;
       char bar[16];
    } StructIWantToIterate;
    
    // this is the metadata I need for each field of the structure
    typedef struct {
       char * pszFieldName;
       size_t oFieldOffset;
       size_t cbFieldSize;
       int    eType;
    } MyStructMeta;
    
    // these are the field types I need to handle.
    enum {
      type_is_int,
      type_is_char,
    };
    
    // these macros help to emit the metadata
    #define NUMELMS(ary)     (sizeof(ary)/(sizeof(ary)[0]))
    #define FIELDOFF(tag,fld)  ((size_t)&(((tag *)0)->fld))
    #define FIELDSIZ(tag,fld)  sizeof(((tag *)0)->fld)
    #define STDFLD(tag,fld,as)  #fld, FIELDOFF(tag,fld), FIELDSIZ(tag,fld), as
    
    // now we declare the metadata for the StructIWantToIterate structure
    #undef MYFLD
    #define MYFLD(fld,as) STDFLD(StructIWantToIterate,fld,as)
    static const MyStructMeta aMeta[] = {
       MYFLD(foo, type_is_int), // expands to "foo", 0, sizeof(int), type_is_int
       MYFLD(bar, type_is_char),// expands to "bar", sizeof(int), 16, type_is_char
    };
    
    // and when we want to do the iteration,  assume ptr is a pointer to an instance
    // of StructIWantToIterate
    
    for (int ii = 0; ii < NUMELMS(aMeta); ++ii)
    {
       char szLine[100]; // pick your own worst case line size.
    
       // get a pointer to the current field within the struct
       void * pfld = ((byte*)ptr) + aMeta[ii].oFieldOffset;
    
       // print out the field data based on the type_is_xxx information
       switch (aMeta[ii].eType)
       {
          case type_is_int:
             sprintf(szLine, "%s : %d", aMeta[ii].pszFieldName, *(int*)pfld);
             break;
    
          case type_is_char:
             sprintf(szLine, "%s : %*s", 
                    aMeta[ii].pszFieldName, 
                    aMeta[ii].cbFieldSize, 
                    pfld);
             break;
       }
       // send it to the richedit control
       RichEdit1->Lines->Append(asLine);    
    }
    

提交回复
热议问题