Thread: comparing structures

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    2

    comparing structures

    hello everyone !

    I just wanted to know of there exist a way of comparing two values whose type is created by the programmer without having to compary all the structure's members ? (for eg , to compare string we user strcmp....)

    suppose we have this structure (record) :
    Code:
    typedef struct{
    int a,
    char b[];
    double c;
    }var1, var2;
    how to compare var1 and var1 ?

  2. #2
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    You can write a function to compare those however you like as there are many ways of doing it. It all depends on what those variables mean.
    For example, if b was a person's name, c was their birthdate, and a was their favourite colour, then one reasonable way to define a comparison function might be:
    Code:
    int compare(myStruct *l, myStruct *r)
    {
        int cmp = strcmp(l->b, r->b);
        if (cmp != 0) return cmp;
        if (l->c < r->c) return -1;
        if (l->c > r->c) return 1;
        return 0;
    }
    Note that b takes no part in the comparison here because it doesn't make sense for the array in question to have two people with the same name and the same birthdate, but with a different favourite colour.
    In order to know how you want YOUR data compared, you'll have to post a REAL struct definition.

    I'm pretty sure that you can't declare an array without a size, except as the last item in a struct (even then only on some compilers).
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  3. #3
    Registered User Maz's Avatar
    Join Date
    Nov 2005
    Location
    Finland
    Posts
    194
    Problem in declaring unknown sized array is a fundamental feature in C. It returns to the very basics of C and memory.

    The structs, variables, everything is just data in memory, starting from certain location, and continuing to certain amount of bytes. And when you handle, lets say a struct, the place of certain members is calculated based on the definition of a struct. Compiler needs to know the size of the struct members, in order to be able to calculate the starting address of the next member.

    However, if you know the size of a struct, you can compare it to another struct by just comparing the data from the starting adresses of the struct, untill the sizeof struct. You can do that easily in a loop, or with some standard functions like memcmp()

  4. #4
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Code:
    int compare(myStruct *l, myStruct *r)
    {
        int cmp = strcmp(l->b, r->b);
        if (cmp != 0) return cmp;
        if (l->c < r->c) return -1;
        if (l->c > r->c) return 1;
        return 0;
    }
    would that work? would be cool if it does, but I would have thought that it wouldent as structs arent null terminated. Maybe strncmp with sizeof(myStruct)

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Structs don't need to be null terminated, themselves - they are accessed by the size of their members which is known by the definition of the struct.

    A char array, inside a struct, can be marked with an end-of-string char, of course.

    BTW, Mike. Did you finish your Tic-Tac-Toe game?

    When I was writing up my TTT game, I found out I had only learned *one* of the three winning tricks in TTT, as a kid. I was taken aback, to be sure!
    Last edited by Adak; 02-15-2009 at 04:10 PM.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Maz View Post
    However, if you know the size of a struct, you can compare it to another struct by just comparing the data from the starting adresses of the struct, untill the sizeof struct. You can do that easily in a loop, or with some standard functions like memcmp()
    That works for comparing to see if two structs are equal. For any "greater/lesser than" it is unlikely to work - the reason being that it simply compares bytes until it finds either the end or a byte that is different [it may well do this in a way that assumes largely equality and compares LARGE chunks, e.g. 8 or 16 bytes at a time, and only resorts to comparing individual bytes when it's found a chunk that is different]. This really only works for strings and other arrays of bytes. For any other data structure, there are two problems:
    1. There may be gaps for alignment purposes in the structure that aren't filled in at all - so random bytes will disrupt the comparison, but do not actually contain valid data.
    2. Integer values are not always stored "big endian", and a little-endian value of 255 is "greater" than 16777216 - which of course isn't what you want if you want to know if x.a > y.a.
    3. If the structure contains pointers, it would be impossible to compare that in this way - that will ABSOLUTELY have to be compared a different way (unless you actually want to know if all pointers are pointing to the same place, rather than if they are pointing to equal content).

    --
    Mats

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Complete Beginner
    Join Date
    Feb 2009
    Posts
    312
    I can't see any reason for not comparing the struct member for member, as in x.m1==y.m1, x.m2==y.m2 and so on. On a sidenote, it's certainly not possible to write a generic struct comparing function.

    When I was writing up my TTT game, I found out I had only learned *one* of the three winning tricks in TTT, as a kid.
    There is no winning trick in TTT.

    TTT is a 2-player finite zero-sum game with perfect information, hence there exists an optimal strategy, the minimax algorithm. When playing against a perfect player, the best you can hope for is a tie.

    The same applies to other such games like go and chess, but there it's harder to become a perfect player.

    Greets,
    Philip
    Last edited by Snafuist; 02-16-2009 at 09:29 AM.
    All things begin as source code.
    Source code begins with an empty file.
    -- Tao Te Chip

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Snafuist View Post
    I can't see any reason for not comparing the struct member for member, as in x.m1==y.m1, x.m2==y.m2 and so on. On a sidenote, it's certainly not possible to write a generic struct comparing function.
    Of course it is. You can construct a list of elements of an object, and write a generic function that compares two structures arbitrarily according to some generic rules. A structure like this would work:
    Code:
    typedef { VOID = 0, INT, STR, CHAR, CHARPTR, FLOAT, DOUBLE } EType; 
    typedef struct SElement
    {
       char *name;   // Not actually needed - just because the macro CAN DO THAT. 
       offset_t offs;
       enum EType type;
    } Element;
    
    typedef struct SExample
    {
        int   a;
        char *str1;
        char str2[40];
        char b;
    } Example;
    
    #define ELEM(structname, name, type)   { #name, offsetof(structname, name), type }
    
    Element ExampleDescr [] = 
    {
       ELEM(Example, a, INT),
       ELEM(Example, str1, CHARPTR),
       ELEM(Example, str2, STR),
       ELEM(Example, b, CHAR)
    };
    
    int CompareStructsGeneric(void *struct1, void *struct2, Element descr, size_t nElements)
    {
       for(i = 0; i < nElements; i++)
       {
           switch(descr[i].type)
           {
               case INT:
                    if (*(int *)((char*)struct1+descr[i].offset) > *(int *)((char*)struct2+descr[i].offset)
                       return 1;
                    else if (*(int *)((char*)struct1+descr[i].offset) < *(int *)((char*)struct2+descr[i].offset)
                       return -1;
                    break;   /* Equal, continue to next element ... */
              .... 
            }
        }
        return 0;
    }
    Obviously, we'll need to make suitable pointer arithmetics to figure out the rest of the functions.

    But you could certainly use this mechanism to compare completely arbitrary structures, as long as they are both the same type.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by sleepywalker View Post
    hello everyone !

    I just wanted to know of there exist a way of comparing two values whose type is created by the programmer without having to compary all the structure's members ? (for eg , to compare string we user strcmp....)

    suppose we have this structure (record) :
    Code:
    typedef struct{
    int a,
    char b[];
    double c;
    }var1, var2;
    how to compare var1 and var1 ?
    How does this even compile? You can't have a array without a specified size in the middle of a struct. Also, you are declaring var1 and var2 as type synonyms, not variables.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  10. #10
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    BTW, Mike. Did you finish your Tic-Tac-Toe game?

    When I was writing up my TTT game, I found out I had only learned *one* of the three winning tricks in TTT, as a kid. I was taken aback, to be sure!
    Nah, i never bothered writing the game logic for it as thats not all that fun, and I dont think anyone would want to play the game anyway, lol. So i kinda dropped it after dealing with the move evaluation. I wrote an Othello game in Java using swing after that, which can be played 2 player and plan on adding AI to it when I get time.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    Code:
    typedef struct{
        int a;
        char b[10];
        double c;
    } bard;
    
    bard thee,summersDay;
    
    if ( memcmp( &thee, &summersDay ) == 0 ) {
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  2. Comparing structures?
    By difficult.name in forum C Programming
    Replies: 2
    Last Post: 11-07-2004, 08:05 PM
  3. Structures & Comparing
    By Cyber Kitten in forum C Programming
    Replies: 1
    Last Post: 10-22-2001, 11:41 AM
  4. Comparing strings w/in structures
    By vehl in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2001, 10:59 AM
  5. Methods for Sorting Structures by Element...
    By Sebastiani in forum C Programming
    Replies: 9
    Last Post: 09-14-2001, 12:59 PM