Thread: Explorations in Structs and sorting.

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94

    Explorations in Structs and sorting.

    I couldn't help myself. I quickly skimmed over structs and was so thrilled with the idea that I had to try and incorporate this into what I have just learned about sorting. So I built a struct array and populated it with a couple records then did a swap. the first step to sorting.

    I know it's a bit ugly but I will clean that up tomorrow. I just had to get my ideas down and give it a shot to see if I got the gist of structs and if I could apply that to my recent studies.

    So heres the code and output.

    Code:
    /* 
     * File:   Structplay.c
     * Author: jim
     *
     * Created on June 14, 2010, 10:50 PM
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    
     typedef struct{
            int feet;
            double inches;
        }Height;
    
    typedef struct{
        char *name;
        Height height;
        int weight;
        int age;
    }personal_info;
    
    void SwapClient(personal_info *clientA,personal_info *clientB);
    
    int main(void) {
    
        personal_info client [10];
        int i;
        i = 1;
    
        client[0].name = "Wilson, Bob";
        client[0].height.feet = 5;
        client[0].height.inches = 10.5;
        client[0].weight = 185;
        client[0].age = 46;
    
        client[1].name = "Jones Shirley";
        client[1].height.feet = 5;
        client[1].height.inches = 2.25;
        client[1].weight = 121;
        client[1].age = 29;
    
        printf("before the swap ---------------------------\n\n");
        printf("Client:%s, height %d foot %.2f inches, weight = %d, age = %d\n",
        client[0].name, client[0].height.feet,client[0].height.inches,
        client[0].weight, client[0].age);
    
        printf("Client:%s, height %d foot %.2f inches, weight = %d, age = %d\n\n",
        client[1].name, client[1].height.feet,client[1].height.inches,
        client[1].weight, client[1].age);
    
    
    
        SwapClient(client,client+1);
    
    
    
        printf("after the swap ---------------------------\n\n");
        printf("Client:%s, height %d foot %.2f inches, weight = %d, age = %d\n",
        client[0].name, client[0].height.feet,client[0].height.inches,
        client[0].weight, client[0].age);
    
        printf("Client:%s, height %d foot %.2f inches, weight = %d, age = %d\n\n",
        client[1].name, client[1].height.feet,client[1].height.inches,
        client[1].weight, client[1].age);
    
        return 0;
    }
    void SwapClient(personal_info *clientA,personal_info *clientB){
        personal_info tempClient;  
    
        tempClient = *clientA;
        *clientA = *clientB;
        *clientB = tempClient;    
    }
    /*
     * Sample output------------------------------------
    
     before the swap ---------------------------
    
    Client:Wilson, Bob, height 5 foot 10.50 inches, weight = 185, age = 46
    Client:Jones Shirley, height 5 foot 2.25 inches, weight = 121, age = 29
    
    after the swap ---------------------------
    
    Client:Jones Shirley, height 5 foot 2.25 inches, weight = 121, age = 29
    Client:Wilson, Bob, height 5 foot 10.50 inches, weight = 185, age = 46
    
    Press [Enter] to close the terminal ...
    
     */
    I know I shouldn't skim through a subject like structs and just start coding but I couldn't help my excitement. I will do a more thorough examination of the references in the next few days.
    Last edited by jimtuv; 06-14-2010 at 10:36 PM.

  2. #2
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Erm, what's your question?

    Why not define a "print struct" function? You seem to be copy & pasting.

  3. #3
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Quote Originally Posted by zacs7 View Post
    Erm, what's your question?

    Why not define a "print struct" function? You seem to be copy & pasting.
    I don't have a question yet other then did I do anything stupid?? I am exploring new ground here and have no place for feed back. So I hope that anyone that has experience might be kind enough to check what I have done and add there ideas and comments so that I may learn from their experience on the subject.

    The lack of a print function was the ugliness I mentioned in my first post. I also need to add a way to populate the array. I am debating if I should do that from a file to learn something new or stick to what I know and just use user input.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Just keep in mind these:
    Code:
        client[0].name = "Wilson, Bob";
        client[1].name = "Jones Shirley";
    Are string literals and so cannot be modified.

    You might want to look into "linked lists" soon. There's another issue here too, just a minute...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    You might probably want to learn/master array,pointer and dynamic memory allocation,variable scope, type promotion, etc.

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Nevermind -- this is just slightly unorthodox to my eye, but it does work:
    Code:
    void SwapClient(personal_info *clientA,personal_info *clientB){
        personal_info tempClient;  
        tempClient = *clientA;
        *clientA = *clientB;
        *clientB = tempClient;    
    }
    Maybe someone else will have an opinion about that.

    Quote Originally Posted by Bayint Naung View Post
    You might probably want to learn/master array,pointer and dynamic memory allocation,variable scope, type promotion, etc.
    Yeah, I think the "orthodox" method here would involve that (allocated pointers). I think the way it is now may suffer from a lack of flexibility, but I could be wrong since I don't generally do that (I think the structs are being copied here, instead of swapping addresses. Which if that is the case, swapping addresses is definitely more efficient).
    Last edited by MK27; 06-15-2010 at 07:59 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Also why not define init function.

    Code:
    void init_person(personal_info *person,char *name, Height height,int weight,int age);
    
    init_person(&client[0],"MK27",height,140,99);   // eg usage

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Bayint Naung View Post
    Also why not define init function.
    That would simplify things. Writing functions is very important -- it avoids duplication of code, improves "modularity" and keeps everything better organized.

    Code that involves a lot of duplication and not enough modularity is sometimes called "spaghetti".
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Quote Originally Posted by MK27 View Post
    Just keep in mind these:
    Code:
        client[0].name = "Wilson, Bob";
        client[1].name = "Jones Shirley";
    Are string literals and so cannot be modified.

    You might want to look into "linked lists" soon. There's another issue here too, just a minute...
    Yea I do understand they are string literals. I will look into linked lists today. Thanks for the heads up.

    Quote Originally Posted by Bayint Naung View Post
    You might probably want to learn/master array,pointer and dynamic memory allocation,variable scope, type promotion, etc.
    I have been studying arrays and pointers and have a basic understanding of memory allocation. I understand pretty well variable scope and have studied type promotion but wouldn't call myself and expert on it.

    Master array I will have to look up as I haven't studied that yet.


    Quote Originally Posted by MK27 View Post
    Yeah, I think the "orthodox" method here would involve that (allocated pointers). I think the way it is now may suffer from a lack of flexibility, but I could be wrong since I don't generally do that (I think the structs are being copied here, instead of swapping addresses. Which if that is the case, swapping addresses is definitely more efficient).
    LOL yep unorthodox is not surprising. I tend to want to try things out first then find the (normal) way of doing it. Might not be the best idea but it is funner for me that way.

    You are right I copied the structs and I was pretty aware it wasn't going to be super efficient. Mainly I wanted to see how to copy a struct so that is why I did it that way.


    Quote Originally Posted by Bayint Naung View Post
    Also why not define init function.

    Code:
    void init_person(personal_info *person,char *name, Height height,int weight,int age);
    
    init_person(&client[0],"MK27",height,140,99);   // eg usage
    Again this was part of the ugliness. I just ran out of steam last night and thought it best to sleep a little before trying anything else. Not going to have a lot of time today. I cleaned up a little adding the print function. I will try to get more done tonight.

    Thanks again everyone you are all so much help. I am learning much faster then I anticipated and I know I owe that to all the input I have received here.

    Here is the code so far with the print function.

    Code:
    /* 
     * File:   Structplay.c
     * Author: jim
     *
     * Created on June 14, 2010, 10:50 PM
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    
    typedef struct{
        int feet;
        double inches;
    }Height;
    
    typedef struct{
        char *name;
        Height height;
        int weight;
        int age;
    }personal_info;
    
    void SwapClient(personal_info *clientA,personal_info *clientB);
    void PrintClients(personal_info *client,int a, int n);
    
    
    int main(void) {
    
        personal_info client [10];
        int i;
        i = 1;
    
        client[0].name = "Wilson, Bob";
        client[0].height.feet = 5;
        client[0].height.inches = 10.5;
        client[0].weight = 185;
        client[0].age = 46;
    
        client[1].name = "Jones Shirley";
        client[1].height.feet = 5;
        client[1].height.inches = 2.25;
        client[1].weight = 121;
        client[1].age = 29;
    
        printf("before the swap ---------------------------\n\n");
    
        PrintClients(client,0,2);
    
        SwapClient(client,client+1);
    
        printf("after the swap ---------------------------\n\n");
    
        PrintClients(client,0,2);
    
        return 0;
    }
    /*
     * SwapClient                       swaps two client records
     * parameters:
     *      personal_info *clientA:     The first client record to swap
     *      personal_info *clientB:     The second client record to swap
     * prints:                          nothing
     * returns:                         nothing
     */
    void SwapClient(personal_info *clientA,personal_info *clientB){
        personal_info tempClient;
        int i;
        i = 0;
    
        tempClient = *clientA;
        *clientA = *clientB;
        *clientB = tempClient;    
    }
    /*
     * PrintClients     prints out n number of client records
     * parameters:
     *      personal_info *client:  is the pointer to the client array
     *      int a:                  the record to begin with
     *      int n:                  the number of records to print from a
     * prints:                      client records
     * returns:                     nothing
     */
    void PrintClients(personal_info *client,int a, int n){
        int i;
    
        for ( i = 0 ; i < n ; i++){
            printf("Client:%s, height %d foot %.2f inches, weight = %d, age = %d\n\n",
            client[a+i].name, client[a+i].height.feet,client[a+i].height.inches,
            client[a+i].weight, client[a+i].age);
        }
    }

  10. #10
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Nothing wrong with copying entire structs that way. But as others have hinted at, data movement can become the slow part of the code. Once you've done the sorting algorithm you can start thinking about allocating a new array of pointers that point to the structs. Then only swap the pointers during sorting.

  11. #11
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Quote Originally Posted by nonoob View Post
    Nothing wrong with copying entire structs that way. But as others have hinted at, data movement can become the slow part of the code. Once you've done the sorting algorithm you can start thinking about allocating a new array of pointers that point to the structs. Then only swap the pointers during sorting.
    That is brilliant! by pointing the pointers to the data then sorting the pointers by dereferencing you end up with an array of pointers that can be searched the same as you would if you had actually moved the data structure. So the idea is move only the pointer and not the data. I can see why that would be so much more efficient. Would you then set up an array of pointers for each member of the struct to allow searches by any data that would be desired such as by age, height or weight?? Once you have sorted an array of pointers and new data record and pointer were added then to place the pointer in the sorted array would be a matter of finding the place where it should go and shifting the pointers up in the array to make space. That then would require an dynamic array correct? Would that involve using calloc? Or am I completely off the wall on this I am pretty new to all this and maybe misunderstanding the concepts?

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by jimtuv View Post
    That is brilliant! by pointing the pointers to the data then sorting the pointers by dereferencing you end up with an array of pointers that can be searched the same as you would if you had actually moved the data structure. So the idea is move only the pointer and not the data. I can see why that would be so much more efficient. Would you then set up an array of pointers for each member of the struct
    In fact it is not very different than your existing code:
    Code:
    /* 
     * File:   Structplay.c
     * Author: jim
     *
     * Created on June 14, 2010, 10:50 PM
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    
    typedef struct{
        int feet;
        double inches;
    }Height;
    
    typedef struct{
        char *name;
        Height height;
        int weight;
        int age;
    }personal_info;
    
    void SwapClient(personal_info **clientA,personal_info **clientB);
    void PrintClients(personal_info **client, int n);
    
    
    int main(void) {
    
        personal_info *client[10];
        int i;
    
    	for (i=0;i<10;i++) {
    		client[i] = malloc(sizeof(personal_info));
    	/* error handling */
    		if (!client[i]) {
    			puts("OUT OF MEMORY!");
    			return -1;
    		}
    	}
    
        i = 1;
    
        client[0]->name = "Wilson, Bob";
        client[0]->height.feet = 5;
        client[0]->height.inches = 10.5;
        client[0]->weight = 185;
        client[0]->age = 46;
    
        client[1]->name = "Jones Shirley";
        client[1]->height.feet = 5;
        client[1]->height.inches = 2.25;
        client[1]->weight = 121;
        client[1]->age = 29;
    
        printf("before the swap ---------------------------\n\n");
    
        PrintClients(client,2);
    
        SwapClient(&client[0],&client[1]);
    
        printf("after the swap ---------------------------\n\n");
    
        PrintClients(client,2);
    
    	for (i=0;i<10;i++) free(client[i]);
    
        return 0;
    }
    /*
     * SwapClient                       swaps two client records
     * parameters:
     *      personal_info *clientA:     The first client record to swap
     *      personal_info *clientB:     The second client record to swap
     * prints:                          nothing
     * returns:                         nothing
     */
    void SwapClient(personal_info **clientA,personal_info **clientB){
        personal_info *tempClient;
        int i;
        i = 0;
    
        tempClient = *clientA;
        *clientA = *clientB;
        *clientB = tempClient;    
    }
    /*
     * PrintClients     prints out n number of client records
     * parameters:
     *      personal_info *client:  is the pointer to the client array
     *      int a:                  the record to begin with
     *      int n:                  the number of records to print from a
     * prints:                      client records
     * returns:                     nothing
     */
    void PrintClients(personal_info **client, int n){
        int i;
    
        for ( i = 0 ; i < n ; i++){
            printf("Client:%s, height %d foot %.2f inches, weight = %d, age = %d\n\n",
            client[i]->name, client[i]->height.feet,client[i]->height.inches,
            client[i]->weight, client[i]->age);
        }
    }
    I did not change any of the comments. If you want to get a look at all the differences on linux, run:

    diff yourcode.c thiscode.c

    Diff's pretty handy, the first time you use it notice the > vs. < arrows on the left.

    Quote Originally Posted by Elysia View Post
    You don't necessarily have to use malloc/calloc. So long as the data is still valid when you're searching, you can just have the actual data on the stack. Pointers can point anywhere - it just has to be a valid memory location.
    Yes, but generally they might as well be on the heap (that is, malloc'd). Eg, in this case you would need to have two arrays to use the stack:
    Code:
        personal_info client[10];   
        personal_info *clientptrs[10];
        for (i=0;i<10;i++) clientptrs[i] = client[i];
    And then the swapping would be in the clientptrs array, which is kind of messy.
    Last edited by MK27; 06-16-2010 at 08:33 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You don't necessarily have to use malloc/calloc. So long as the data is still valid when you're searching, you can just have the actual data on the stack. Pointers can point anywhere - it just has to be a valid memory location.
    You only need a pointer to the actual struct. Then you implement some semantics on how the structs are actually sorted. You would only move the pointers around, so no data is copied anyway if you use pointers to the structs only.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    But malloc/free are inefficient anyway. Plus they add bugs. So best avoid them if you can
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Elysia View Post
    But malloc/free are inefficient anyway. Plus they add bugs. So best avoid them if you can
    Well, this is the "C" forum, Elysia, not the C++ forum, or the Fortran forum, et. al. Malloc/free are fundamental to C programming -- you are unlikely to get very far without them. They do not "add bugs" unless you use them incorrectly, which every programming command in every programming language ever could be used to "add bugs". You might as well "avoid C programming" if this is how you feel.

    Vis, efficiency, I'm surprised to hear this coming from an STL advocate. If you wanted to use one malloc/free call above instead of ten, you could implement a simple mempool. However, I'm not too sure how critical that is for the OP right now, and to do so you first need to learn and understand the basics. C is a minimalist language, for better or worse: we do not just hand everyone everything on a ready-made platter here.
    Last edited by MK27; 06-16-2010 at 09:29 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 03-31-2009, 12:34 PM
  2. Sorting an Array of Structs not working
    By ashcan1979 in forum C++ Programming
    Replies: 9
    Last Post: 09-28-2006, 03:07 PM
  3. sorting containers of structs
    By bigSteve in forum C++ Programming
    Replies: 2
    Last Post: 01-06-2004, 02:50 PM
  4. sorting an array of structs
    By jo_jo2222 in forum C++ Programming
    Replies: 2
    Last Post: 04-08-2002, 11:52 PM
  5. sorting an array of structs
    By singletrackmind in forum C++ Programming
    Replies: 8
    Last Post: 11-13-2001, 03:33 AM