Link to home
Start Free TrialLog in
Avatar of bansaldeep
bansaldeep

asked on

How to compare members of identical structures

Is there any way to parse through structure elements in a loop just like an array?
The requirement is to compare elements of two structures of same type.
e.g.
struct S{
int i;
char sz[4];
char *ptrC;
}s1, s2;

In real, our structure S is very large and at end of program, S1 and S2 are populated with different values. I can not compare each and every member like if(s1.ptrC == s2.ptrC) but using some logic want to compare if 3rd element of S1 is equal to 3rd element of S2.
 
Avatar of MURUGESAN N
MURUGESAN N
Flag of India image

This can be done on overloading the operator == inside the structure (in c++)

#include <iostream>
#include <string>
using namespace std;
struct S{
int i;
char sz[4];
char *ptrC;
bool operator == (struct S &s2)
{
        if(s2.i==i)
                if(!strcmp(s2.sz,sz))
                        if(s2.ptrC==ptrC)
                                return true;
        return false;
}
}s1, s2;
int main()
{
        s1.i=s2.i=12;
        strcpy(s1.sz,"mm");
        strcpy(s2.sz,"mm");
        s1.ptrC=s2.ptrC="TEST";
        if(s1==s2)
                cout<<"yes\n";
        else
                cout<<"no\n";
        return 0;
}

Open in new window

Avatar of pepr
pepr

As they are of the char* type (i.e. C-strings), you probably want to compare the pointed content and not the pointers. You probably want to use strcmp() function or strncmp() function. See

http://www.cplusplus.com/reference/clibrary/cstring/strcmp.html
http://www.cplusplus.com/reference/clibrary/cstring/strncmp.html

In C program, include <string.h>. In C++ application include <cstring>.
>> Is there any way to parse through structure elements in a loop just like an array?

No. Unless you're absolutely sure that each elemnt in the struct has the same (byte) size, and there's no padding between them.


>> I can not compare each and every member

Why not ? That's exactly how you should do this.
Can you maybe show the entire struct ? It would allow us to help you better.
Avatar of bansaldeep

ASKER

The structure is very big. It contains members of types char, char *, char **, structs, int, int * etc.
May be around 40-50 members of these types.
ASKER CERTIFIED SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
So there is no way to iterate.

Experts I am deleting this question.
>> Experts I am deleting this question.

Why ? Didn't we answer your question ?
May I ask why you gave a C grade ? That means the help I gave was REALLY bad. How could I have helped you better ?
No no don't take it this way. But I am still wondering about the solution.
>>>> Then there's really no (advisable) way to iterate through them.

That's not quite true. If the structure header (source code) is available at runtime you could parse the structure and make the comparisions for each member parsed. That isn't easy but actually I made such a job currently in order to output the contents of arbitrary C structures into a XML. If you don't want the header to be read at runtime you could consider to write a tool which parses the header and write a static array out of it like that:

   const int MAX_MYSTRUCT  = 99; // max members
   MyStruct ms = { 0 };  
   static FieldDef[MAX_MYSTRUCT] = {
   { "i", T_INT, 1, ((char*)&ms.i -  (char*)&ms)},
   { "sz", T_C, 4,  ((char*)&ms.sz -  (char*)&ms) },
   { "ptrC", T_PC, 1, ((char*)&ms.ptrC -  (char*)&ms) },
   ....

 };

The FieldDef would be defined like

class FieldDef
{
    const char* pszMember;
    int               type;
    int               arrsize;
    int               offset;
};

With that array you could evaluate an arbitrary instance of the structure and compare it or copy it or do something.

In case of nested structures or pointers to pointers things may get more complex or impossible as you would need further information, e. g. the size of a dynamic structure defined by pointer to pointer.
 
>> No no don't take it this way.

Ok.


>> But I am still wondering about the solution.

If you're not satisfied with the answer, then you don't have to close the question yet. Feel free to ask for clarification where needed.

But please keep in mind that the grading reflects how good the answer was, and that a C means that it was really bad :

        https://www.experts-exchange.com/help.jsp#hi97

or I quote :

        If you have given the Expert(s) ample time to respond to your clarification
        posts and you have responded to each of their posts providing requested
        information; or if the answers, after clarification, lack finality or do not
        completely address the issue presented, then a "C" grade is an option.

I don't think the way this question was answered fits in that category, does it ? Feel free to correct me if I'm wrong.
>> No no don't take it this way.
IMO that isn't a sufficient solution. You should correct your wrong decision by asking for reopening the question.
>> If the structure header (source code) is available at runtime you could parse the structure and make the comparisions for each member parsed.

And would you advise that ? I hope not ... It takes more work to implement it correctly, it makes the executable depend on the presence of the source code, and it's a lot slower. I don't see any advantage.

(I did say "no (advisable) way")


Imo, a better approach in your case, Alex, would have been :
If you're really going through the trouble to parse the header file, then why not simply generate code for comparing the struct. Then compile the code, and it's ready to use in your application. I would really not do such things at runtime.
Btw, Alex, don't take my post the wrong way. I'm not criticizing your project - you probably had a good reason to do it that way. I'm just saying that this is by no means a solution that should be used just to compare a big struct.
>>>> it makes the executable depend on the presence of the source code, and it's a lot slower. I don't see any advantage.

Actually, any debugger does that and you won't say a debugger has no advantages, do you?
>> Actually, any debugger does that and you won't say a debugger has no advantages, do you?

Yes, but I thought we were talking about production code here ...
>>>> this is by no means a solution that should be used just to compare a big struct.
Hmm, actually a debugger won't compare two big structures. So, indeed it may be the only way to correctly compare the contents of structures at runtime. That was the purpose of my project. By logging the contents of structures to a xml (you can switch logging on/of at runtime) there is way to compare some functioniality before and after some major changes directly at the interfaces. It furthermore allows to read in the data again thus providing an excellent way to repeat a specific test-case.
>>>> but I thought we were talking about production code here ...
Thta isn't a contradiction. The solution operates like a debugger but runs in release mode.
It makes more sense to me now, Alex.
I'm not sure if it's applicable here though ... If I understood it correctly, bansaldeep simply wanted code like this :

    struct S {
        /* some members */
    };

    bool compare_S(struct S *s1, struct S *s2) {
        /* iterate through the members of s1 and s2, comparing them */
    }

    struct S s1, s2;
    if (compare_S(&s1, &s2) == 0) {
        /* equal !!! */
    }
>>>> bansaldeep simply wanted code like this
If the structure wouldn't have member pointers the compiler's operator== function could be used for free. Comparing two instances of a structure on identity also could mean that the 'objects' in the project were not managed as singletons but that multiple copies of the same object may occur. That doesn't sound like OOP but may be 'inherited' from a C design. But even for pure C structures it mostly can be avoided of using pointer members. We recently made a redesign of an elder C interface and replaced all pointers by fixed-sized arrays and or embedded structures. Only the most outer array was managed by a dynamic pointer. The redesign needs more memory but stability and usage has improved tremendously. Structures containing no pointers simply can be compared, assigned and copied.
>> Structures containing no pointers simply can be compared, assigned and copied.

Yes, but that's not the case here ;)

>> It contains members of types char, char *, char **, structs, int, int * etc.
bansaldeep, any chance I can get a response from you on the C grade ? Did you read those FAQ entries I posted ?
Parsing the header file is not good to me. I considered that earlier but it requires too much into parsing and during the development header file keeps changing.
My requirement is captured by infinity08 correctly. I want to operate on structure as if it is an array but with different type members.
struct S {
        /* some members */
    };

bool compare_S(struct S *s1, struct S *s2) {
        /* iterate through the members of s1 and s2, comparing them */
for(i=0;i<50;i++)
{
  compare s1[i] with s2[i], where 1st element could be an int.
  compare s1[i] with s2[i], where 2nd element could be a string.
}
    }

    struct S s1, s2;
    if (compare_S(&s1, &s2) == 0) {
        /* equal !!! */
    }
You need type information as well as offset information for each member stored somewhere, and then you can perform the loop. But it's not advisable, because it will increase the memory footprint of your application, and slow it down. On top of that the maintainability will be worse (you have to change the stored type and offset information every time you change the struct), and portability will be virtually nil.

The best way is to compare member by member. It might take a bit longer to write it out (you could generate the code if that's a problem), but at least you won't suffer any of the downsides I mentioned.
Btw, did you read the FAQ entries I posted about grading ? Do you understand why a C grade is not appropriate here ? Do you know that you can fix that by requesting a change of the grade ?
ok how do I request a change in grade?
>>>> ok how do I request a change in grade?
Goto the TA https://www.experts-exchange.com/Community_Support/General/ and ask a 0 points question by posting a link to this thread http:Q_23211772.html