Need help in structure comparison

This is a discussion on Need help in structure comparison within the C Programming forums, part of the General Programming Boards category; Hi, I have a structure with two elements namely name and zip. I need to sort the zip first and ...

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    7

    Need help in structure comparison

    Hi,

    I have a structure with two elements namely name and zip.
    I need to sort the zip first and within the zip, I need to sort the name.

    My structure is a dynamic structure.

    I have created the below program it is able to print the sorted zip. But it is unable to sort the name based on the zip. I know I am missing something. But could not figure out what could be wrong.

    I need your help in understanding what I have done wrong.

    Please help me.

    Thanks in Advance
    Chari

    ---------------------------------------------------------------------------------------------------
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    struct address {
    char name[40];
    char zip[11];
    };

    int struct_cmp_by_zip(const void *a, const void *b)
    {
    struct address **ia = (struct address **)a;
    struct address **ib = (struct address **)b;
    return strcmp((*ia)->zip, (*ib)->zip);
    }

    int struct_cmp_by_name(const void *a, const void *b)
    {
    struct address **ia = (struct address **)a;
    struct address **ib = (struct address **)b;
    return strcmp((*ia)->name, (*ib)->name);
    }

    void print_struct_array(struct address **array, size_t len)
    {
    size_t i;

    for(i=0; i<len; i++)
    printf("[ name: %s \t zip: %s ]\n", array[i]->name, array[i]->zip);

    puts("--");
    }

    /* sorting structs using qsort() example */
    void sort_structs_example(void)
    {
    int i, count, iContinue, iStart, iEnd, iCount;
    char n[100];

    size_t structs_len;
    struct address **structs = NULL;

    iContinue = 1;
    count = 0;
    printf("Do you want to enter the details: (1 to enter, 0 to quit)");
    scanf("%d", &iContinue);
    while (iContinue)
    {
    structs = (struct address **)realloc(structs, (sizeof(struct address *) * (count + 1)));
    if (structs == NULL) {printf("unable to allocate memory\n"); return;}

    structs[count] = (struct address *)malloc(sizeof(struct address));
    if (structs[count] == NULL) {printf("unable to allocate memory\n"); return;}

    printf("Enter name:"); scanf("%s", structs[count]->name);
    printf("Enter zip:"); scanf("%s", structs[count]->zip);

    printf("Do you want to enter the details: (1 to enter, 0 to quit)");
    scanf("%d", &iContinue);

    count++;
    structs_len = (size_t)count;
    }


    //size_t structs_len = sizeof(structs *) / sizeof(struct address *);
    printf("structs_len = %d\n", structs_len);


    puts("*** Struct original ...");

    /* print original struct array */
    print_struct_array(structs, structs_len);



    puts("*** Struct sorting (zip)...");

    /* sort array using qsort functions */
    qsort(structs, structs_len, sizeof(struct address *), struct_cmp_by_zip);

    /* print sorted struct array */
    print_struct_array(structs, structs_len);


    puts("*** Struct sorting (zip/name)...");
    iStart = iEnd = iCount = 0;
    for(i=0; i<=structs_len; i++)
    {
    if (i == 0)
    {
    strcpy(n, structs[i]->zip);
    iStart = i;
    iCount = 1;
    continue;
    }
    if (i < structs_len)
    {
    if (!strcmp(n, structs[i]->zip))
    {
    iCount++;
    continue;
    }
    }
    iEnd = iStart + (iCount);
    qsort(*structs+iStart, iEnd-iStart, sizeof(struct address *), struct_cmp_by_name);
    strcpy(n, structs[i]->zip);
    iStart = i;
    iCount = 1;
    }

    /* print sorted struct array */
    print_struct_array(structs, structs_len);


    for (i = 0; i < structs_len; i++)
    if (structs[i] != NULL) {free(structs[i]); structs[i] = NULL;}
    if (structs != NULL) {free(structs); structs = NULL;}

    }
    ---------------------------------------------------------------------------------------------------

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    So if you only have one sorting method (zip, then name), why do you have two sorting functions? It's possible that your sub-sorting method is right, but given that you are complaining about it and it's un-indented state I'm not going to read it to find out.

    Just write one function, that returns negative if the first element should be sorted before the second, positive for vice versa, and 0 if they are the same.

  3. #3
    Registered User
    Join Date
    Oct 2009
    Posts
    7
    I have two functions because one is for comparing the zip and the other one is for comparing the name. Please correct me if I am wrong. To my knowledge, I don't think it is possible to have just one function do both the comparisons since both needs to be compared on separate calls. There is no way we can identify whether we want to compare zip or name since we are using qsort().
    Probably we may have to write a custom qsort to do that.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I would create a new string member, and add it to your struct, and sort only by it. The new string member would be the zip code, and appended onto it, would be the name.

    So Charles Howard in zip code 94102, would have a new struct member of:
    941026HowardCharles

    Now you're using Qsort to sort with just one key. You'll have to change your comparison function over to work with only strcmp(), of course.

  5. #5
    Registered User
    Join Date
    Oct 2009
    Posts
    7
    Adak,

    That was a good suggestion. I combined the zone and name and added that as a new member to my structure and just sort that member alone which was very easy.
    Thank you so much for your help.

  6. #6
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Your assertion that you can't do both comparisons in the same function is false, and I'm not sure why you would even think that.

    First you check the zip. If the zips are unequal, return that status. OTHERWISE, the zips are equal, so you check the name, and return that status.

    Code:
    int struct_cmp_by_zip_then_name(const void *a, const void *b)
    {
    struct address **ia = (struct address **)a;
    struct address **ib = (struct address **)b;
    int zipCompare = strcmp((*ia)->zip, (*ib)->zip);
    if( zipCompare != 0 ) return zipCompare;
    return strcmp((*ia)->name, (*ib)->name); 
    }
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    Registered User
    Join Date
    Oct 2009
    Posts
    7
    brewbuck,

    Thanks for your suggestion. It works. I take my words back..... my bad. Sorry for that.
    This is a good lesson learnt.
    Appreciate your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 26
    Last Post: 07-05-2010, 10:43 AM
  2. Problem referencing structure elements by pointer
    By trillianjedi in forum C Programming
    Replies: 19
    Last Post: 06-13-2008, 05:46 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 09:52 AM
  5. C structure within structure problem, need help
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 11-30-2001, 04:48 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21