Thread: Sorting array of pointers to structures, nothing swapping??

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    25

    Question Sorting array of pointers to structures, nothing swapping??

    I have managed to get this most recent project of mine to compile and run just fine, the data displays as it should, however, the purpose of this project was to sort structs (DBrecords) in various ways. Unfortunately I must not be understanding how to swap which structure the pointer is assigned to correctly. I've tried a few methods, such as memcpy...that failed miserably as I don't fully know how to use that (tried sizeof(DBrecord) as size_t... set fault). I'll post the code below.

    Some Notes: DBrecord is name of structure,
    instructor wanted the student's ID to be a char array, I may have scanned that in wrong, should I have another loop to go and look of %c rather than use %s since the ID is all numerical in the data file? and how would I get scans to ignore the space between the name and id?


    program header file:

    Code:
    #include <stdio.h>
    #include <stdlib.h>    
    
    
        typedef enum {
            firstYear = 0,
            sophomore,
            junior,
            senior,
            grad
        }Year;
    
    
        typedef struct {
            int recordid;
            char *lastname;
            char *firstname;
            char ID[8];
            int age;
            Year year;
            float GPA;
            int gradYear;
        } DBrecord;

    Sort functions file:

    Code:
    #include "major4.h"#include <string.h>
    
    
    void swap(void *ptra, void *ptrb)
    {
    
    
        void *temp;
    
    
        temp = ptra;
        ptra = ptrb;
        ptrb = temp;
        
    
    
    
    
        
    }
    
    
    void sortFirst(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            if (strcmp((records[i]->firstname), (records[i + 1]->firstname)) > 0) swap(records[i], records[i + 1]);
    
    
        }
    
    
    
    
    
    
    
    
    
    
       
    }
    
    
    void sortLast(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            if (strcmp((records[i]->lastname), (records[i + 1]->lastname)) > 0) swap(records[i], records[i + 1]);
    
    
           
        }
    
    
    
    
    }
    
    
    void sortAge(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            if ( (records[i]->age) > (records[i + 1]->age)) swap(records[i], records[i + 1]);
    
    
        }
        
    }
    
    
    void sortGPA(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            if ((records[i]->GPA) < (records[i + 1]->GPA)) swap(records[i], records[i + 1]);
    
    
        }
    
    
    
    
       
    }
    
    
    void sortClass(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            if ((records[i]->year) > (records[i + 1]->year)) swap(records[i], records[i + 1]);
    
    
        }
    
    
        
    }
    
    
    void sortGrad(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            if ((records[i]->gradYear) > (records[i + 1]->gradYear)) swap(records[i], records[i + 1]);
    
    
        }
        
    }
    
    
    void sortID(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
    
    
            if (strcmp(records[i]->ID, records[i + 1]->ID) > 0) swap(records[i], records[i + 1]);
    
    
        }
    
    
        
    }
    
    
    void printyear(Year year)
    {
    
    
        switch (year) {
    
    
        case firstYear: printf("firstYear ");
            break;
        case sophomore: printf("sophomore ");
            break;
        case junior: printf("junior ");
            break;
        case senior: printf("senior ");
            break;
        case grad: printf("grad ");
            break;
    
    
    
    
    
    
        }
    
    
    
    
       
    }
    
    
    void printstruct(DBrecord *records[], int recordct)
    {
    
    
        int i;
    
    
        for (i = 0; i < recordct; i++) {
    
    
            printf("%s, %s: %s %d ", records[i]->lastname, records[i]->firstname, records[i]->ID, records[i]->age);
            printyear(records[i]->year);
            printf("%f %d\n\n", records[i]->GPA, records[i]->gradYear);
    
    
        }
    
    
        
    }

    main file which calls the functions:

    Code:
    /*  * File:   driver.c
     * Author: Alexander Hollis
     *
     * Created on April 3, 2012, 6:41 PM
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "major4.h"
    #include <string.h>
    
    
    /*
     * 
     */
    int main()
    {
    
    
        printf("CSE1040 Major 3 Assignment - Alex Hollis - [email protected] - Tested on CSP 01\n\n");
    
    
        int numrecords;
    
    
        scanf("%d", &numrecords);
    
    
    
    
        DBrecord * records[numrecords];
    
    
        int i;
    
    
        for (i = 0; i < numrecords; i++) {
    
    
            records[i] = (DBrecord *) malloc(sizeof (DBrecord));
    
    
            records[i]->lastname = (char *) malloc(sizeof (scanf("%s")));
            scanf("%s", records[i]->lastname);
            records[i]->firstname = (char *) malloc(sizeof (scanf("%s")));
            scanf("%s", records[i]->firstname);
            scanf("%s", records[i]->ID);
            scanf("%d", &records[i]->age);
    
    
            char testdata[10];
    
    
            scanf("%s", testdata);
    
    
            if (strcmp(testdata, "firstYear") == 0) records[i]->year = firstYear;
            else if (strcmp(testdata, "sophomore") == 0) records[i]->year = sophomore;
            else if (strcmp(testdata, "junior") == 0) records[i]->year = junior;
            else if (strcmp(testdata, "senior") == 0) records[i]->year = senior;
            else records[i]->year = grad;
    
    
            scanf("%f", &records[i]->GPA);
            scanf("%d", &records[i]->gradYear);
    
    
        }
    
    
    
    
        printf("Sorted by Last Name:\n");
        sortLast(records, numrecords);
        printstruct(records, numrecords);
    
    
        printf("Sorted by First Name:\n");
        sortFirst(records, numrecords);
        printstruct(records, numrecords);
    
    
        printf("Sorted by Student ID:\n");
        sortID(records, numrecords);
        printstruct(records, numrecords);
    
    
        printf("Sorted by Age:\n");
        sortAge(records, numrecords);
        printstruct(records, numrecords);
    
    
        printf("Sorted by Class:\n");
        sortClass(records, numrecords);
        printstruct(records, numrecords);
    
    
        printf("Sorted by GPA:\n");
        sortGPA(records, numrecords);
        printstruct(records, numrecords);
    
    
        printf("Sorted by Expected Graduation Data:\n");
        sortGrad(records, numrecords);
        printstruct(records, numrecords);
    
    
    
    
    
    
    
    
    
    
        return (EXIT_SUCCESS);
    }

    If you see anything else that could cause problems when more students are added, up to 320... I appreciate all feedback.

    Thank You.

    - Alex

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    the arguments to your swap function become local variables so the swapping doesn't affect the callers pointers. your swap should look like swap(void **a,void **b); pass in the address of the pointers you want to swap, not the value of the pointers. there will be more asterisks in your swap code. the implementation is left to you.

  3. #3
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You can not use scanf twice - once for the length, and another for getting the value. Use it once and then use strlen + 1 to malloc the appropriate amount.
    swap() should look like this:
    Code:
    void swap(DBrecord *ptra, DBrecord *ptrb) {
    DBrecord temp;
    temp = *ptra;
    *ptra = *ptrb;
    *ptrb = temp; }
    Also, your sort functions don't sort. They just migrate one element. There should be a nested loop for bubble sort.

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    There's more to sorting than what you have written here. You can't fully sort an array with just a single loop.

    The simplest example of where a single loop does not work, using an array of integers (3, 2, 1) for simplicity of demonstration:
    First it would swap the 3 and the 2, giving (2, 3, 1),
    Then it would swap the 1 and the 3, giving (2, 1, 3),
    Lastly, it actually tries to compare the 3 to whatever garbage happens to be in the next spot of memory, and possibly tries to swap the 3 with that. This is a buffer-overflow problem. And regardless of the buffer overflow, the 2 and 1 never end up the right way around.

    So as you can see, the method you are using will not fully sort an array even if you get the swap working. Perhaps look into a real sorting algorithm, such as Bubble Sort, Selection Sort, or Insertion Sort.
    Then, instead of making 7 copies of the algorithm, just write it once and pass in a parameter that tells it how to do the comparisons.

    As for the swap, you need space for a whole DBrecord to swap the items. Rather than just changing pointer values, actually copy data from one struct to another. Since you're not using qsort, you can just use the following function prototype:
    Code:
    void swap(DBrecord *ptra, DBrecord *ptrb)
    Alternatively using qsort, if you are allowed to, might be easier.
    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"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 05-26-2011, 06:44 AM
  2. Sorting array structures
    By Jaxtomtom89 in forum C Programming
    Replies: 1
    Last Post: 11-30-2010, 06:09 AM
  3. sorting an array of structures
    By kisiellll in forum C Programming
    Replies: 15
    Last Post: 04-06-2009, 05:25 AM
  4. Array of Structures: Sorting
    By Drainy in forum C Programming
    Replies: 3
    Last Post: 04-13-2005, 09:55 AM
  5. Sorting an Array of Structures
    By bob2509 in forum C++ Programming
    Replies: 7
    Last Post: 05-12-2002, 08:26 AM

Tags for this Thread