By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,264 Members | 1,100 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,264 IT Pros & Developers. It's quick & easy.

Sorting an array of pointers to struct based on an element inside the struct

P: 4
Hi everyone . I'm still a beginner in C especially with structures and pointers. So what i want to do here is to sort an Array of pointers to Structs based on a string inside the Struct . All the Element are dynamically allocated . And i want to know how to free the allocated Memory . My code is written in German so i will be writing only the parts that i don't understand in English . thank you in advance I appreciate your help.

Expand|Select|Wrap|Line Numbers
  1. typedef struct Vehicle {
  2. char *manufacturer;
  3. char *serialnumber;
  4. int weight;
  5. };
  6. void SortByID(struct fahrzeug** data, int Anzahl){
  7.     struct Vehicle *temp= (struct Vehicle*)malloc( sizeof(struct Vehicle) ) ;
  8.     int i =0 ;
  9.     while ( i < Anzahl && strcmp(data[i]->serialnumber, data[i+1]->serialnumber) < 0)
  10.         {
  11.             temp = data[i+1];
  12.             data[i + 1] = person[i];
  13.             data[i]=temp ;
  14.             i++;
  15.         }
  16.     }   
  17.     free(temp);
  18.     temp=NULL;
  19. }
  20. int main(){
  21. struct Vehicle **array = NULL ;
  22. array=(struct Vehicle**)malloc(  5 * sizeof(struct Vehicle*)  );
  23. SortByID (  &array, count ) ;
  24. return 0; 
  25. }
and i will be uploading the whole Programme but it is written in German and there is a lot of non complete function in it .
Attached Files
File Type: zip forum c .zip (1.9 KB, 30 views)
Apr 23 '18 #1

✓ answered by yassinov

thank you for your Healp .I've already found a solution with you Help and the Help of Other Programmer on stackoverflow . I'm still a beginner in c that's why there is a lot that i have to learn. I appreciate your Help
this is a working version of what i am trying to do

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct Vehicle {
  6.     char *manufacturer;
  7.     char *serialnumber;
  8.     int weight;
  9. };
  10.  
  11. int cmp_serialnumber(const void *p1, const void *p2)
  12. {
  13.     const struct Vehicle *v1 = *(struct Vehicle * const *)p1;
  14.     const struct Vehicle *v2 = *(struct Vehicle * const *)p2;
  15.  
  16.     return strcmp(v1->serialnumber, v2->serialnumber);
  17.  
  18. /*
  19.     // Alternatively You could write this function as this less readable one liner
  20.     return strcmp((*(struct Vehicle * const *)p1)->serialnumber,
  21.                     (*(struct Vehicle * const *)p2)->serialnumber);
  22. */
  23. }
  24.  
  25. int cmp_manufacturer(const void *p1, const void *p2)
  26. {
  27.     const struct Vehicle *v1 = *(struct Vehicle * const *)p1;
  28.     const struct Vehicle *v2 = *(struct Vehicle * const *)p2;
  29.  
  30.     return strcmp(v1->manufacturer, v2->manufacturer);
  31. }
  32.  
  33. void print_vehicles(struct Vehicle **vehicles, int n) {
  34.     for (int i=0; i<n; i++) {
  35.         printf("%s, %s, %d\n", vehicles[i]->serialnumber,
  36.                 vehicles[i]->manufacturer, vehicles[i]->weight);
  37.     }
  38. }
  39.  
  40.  
  41. #define N_VEHICLES  5
  42. char *manufacturers[] = {"McLaren", "Ferrari", "Renault", "Mercedes", "Alfa Romeo"};
  43. char *serialnumbers[] = {"SN500", "SN4", "SN8", "SN2", "SN1"};
  44.  
  45.  
  46. int main(){
  47.     struct Vehicle **vehicles = NULL;
  48.  
  49.     vehicles = (struct Vehicle**)malloc(N_VEHICLES * sizeof(struct Vehicle *));
  50.  
  51.     for(int i=0; i<N_VEHICLES; i++) {
  52.         vehicles[i] = (struct Vehicle *)malloc(sizeof(struct Vehicle));
  53.         vehicles[i]->manufacturer = manufacturers[i];
  54.         vehicles[i]->serialnumber = serialnumbers[i];
  55.         vehicles[i]->weight = 1000;
  56.     }
  57.  
  58.     printf("Before\n");
  59.     print_vehicles(vehicles, N_VEHICLES);
  60.     printf("\n");
  61.  
  62.     // sort by serial number
  63.     qsort(vehicles, N_VEHICLES, sizeof(struct Vehicle *), cmp_serialnumber);
  64.     printf("Sorted by serial number\n");
  65.     print_vehicles(vehicles, N_VEHICLES);
  66.     printf("\n");
  67.  
  68.     // sort by manufacturer
  69.     qsort(vehicles, N_VEHICLES, sizeof(struct Vehicle *), cmp_manufacturer);
  70.     printf("Sorted by manufacturer\n");
  71.     print_vehicles(vehicles, N_VEHICLES);
  72.  
  73.     return 0;
  74. }

Share this Question
Share on Google+
5 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
You might read this:

https://bytes.com/topic/c/insights/7...rrays-revealed


You create each Vehicle using malloc.

You load data into each Vehicle.

You place the Vehicle* for these Vehicle in the array of Vehicle**

When you are finished with each Vehicle*, you free the pointer.

The sort just rearranges the Vehicle* in the array. It does not malloc.

If you have malloc data inside your struct you need to write your own free function that will free the member allocations and then free the struct itself.

Post again if this does not help.
Apr 23 '18 #2

P: 4
thank you for replying
I've tried to sort the array of pointer just by swapping the pointers inside it . it will be easier . i 've used the qsort funtion but without success
Expand|Select|Wrap|Line Numbers
  1. int compare(const void *a, const void *b) {
  2.   struct Vehicle * const *one = a;
  3.   struct Vehicle * const *two = b;
  4.  
  5.   return strcmp((*one)->serialnumber, (*two)->serialnumber);
  6. }
  7. void SortByID(struct Vehicle** data, int Anzahl){
  8.      qsort( data, Anzahl, sizeof(struct Vehicle*) ,compare );
  9. }
Apr 24 '18 #3

weaknessforcats
Expert Mod 5K+
P: 9,197
Have you got a clean compile yet?

This code:
Expand|Select|Wrap|Line Numbers
  1. void fahrzeugSortByID(struct fahrzeug** daten, int Anzahl){
  2.     struct fahrzeug *temp= (struct fahrzeug*)malloc( sizeof(struct fahrzeug) ) ;
  3.     for(int i =0 ; i<Anzahl ; i++){
  4.         temp = &(daten[i]);
  5.         daten[i]=&(daten[i+1]);
  6.         daten[i+1] =&temp ;
  7.     }
has indirection errors. daten is a fahrzeug** so daten[i] is a fahrzeug*. Therefore, &daten[i] is a fahrzeug**. It is being assigned to temp which is a fahrzeug*. My compiler says no-no.

Also, this is C so you can't assign a struct using the assignment operator =. You have to write a function to make a memberwise copy of each element of the struct.

This code: temp = &(daten[i]) will destroy the contents of temp which is a pointer to memory allocated by malloc. This memory is now not able to be freed. This is, this is a leak.
Apr 24 '18 #4

P: 4
thank you for your Healp .I've already found a solution with you Help and the Help of Other Programmer on stackoverflow . I'm still a beginner in c that's why there is a lot that i have to learn. I appreciate your Help
this is a working version of what i am trying to do

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. struct Vehicle {
  6.     char *manufacturer;
  7.     char *serialnumber;
  8.     int weight;
  9. };
  10.  
  11. int cmp_serialnumber(const void *p1, const void *p2)
  12. {
  13.     const struct Vehicle *v1 = *(struct Vehicle * const *)p1;
  14.     const struct Vehicle *v2 = *(struct Vehicle * const *)p2;
  15.  
  16.     return strcmp(v1->serialnumber, v2->serialnumber);
  17.  
  18. /*
  19.     // Alternatively You could write this function as this less readable one liner
  20.     return strcmp((*(struct Vehicle * const *)p1)->serialnumber,
  21.                     (*(struct Vehicle * const *)p2)->serialnumber);
  22. */
  23. }
  24.  
  25. int cmp_manufacturer(const void *p1, const void *p2)
  26. {
  27.     const struct Vehicle *v1 = *(struct Vehicle * const *)p1;
  28.     const struct Vehicle *v2 = *(struct Vehicle * const *)p2;
  29.  
  30.     return strcmp(v1->manufacturer, v2->manufacturer);
  31. }
  32.  
  33. void print_vehicles(struct Vehicle **vehicles, int n) {
  34.     for (int i=0; i<n; i++) {
  35.         printf("%s, %s, %d\n", vehicles[i]->serialnumber,
  36.                 vehicles[i]->manufacturer, vehicles[i]->weight);
  37.     }
  38. }
  39.  
  40.  
  41. #define N_VEHICLES  5
  42. char *manufacturers[] = {"McLaren", "Ferrari", "Renault", "Mercedes", "Alfa Romeo"};
  43. char *serialnumbers[] = {"SN500", "SN4", "SN8", "SN2", "SN1"};
  44.  
  45.  
  46. int main(){
  47.     struct Vehicle **vehicles = NULL;
  48.  
  49.     vehicles = (struct Vehicle**)malloc(N_VEHICLES * sizeof(struct Vehicle *));
  50.  
  51.     for(int i=0; i<N_VEHICLES; i++) {
  52.         vehicles[i] = (struct Vehicle *)malloc(sizeof(struct Vehicle));
  53.         vehicles[i]->manufacturer = manufacturers[i];
  54.         vehicles[i]->serialnumber = serialnumbers[i];
  55.         vehicles[i]->weight = 1000;
  56.     }
  57.  
  58.     printf("Before\n");
  59.     print_vehicles(vehicles, N_VEHICLES);
  60.     printf("\n");
  61.  
  62.     // sort by serial number
  63.     qsort(vehicles, N_VEHICLES, sizeof(struct Vehicle *), cmp_serialnumber);
  64.     printf("Sorted by serial number\n");
  65.     print_vehicles(vehicles, N_VEHICLES);
  66.     printf("\n");
  67.  
  68.     // sort by manufacturer
  69.     qsort(vehicles, N_VEHICLES, sizeof(struct Vehicle *), cmp_manufacturer);
  70.     printf("Sorted by manufacturer\n");
  71.     print_vehicles(vehicles, N_VEHICLES);
  72.  
  73.     return 0;
  74. }
Apr 24 '18 #5

P: 4
Thank you. you are the only one who helped me here .
Apr 24 '18 #6

Post your reply

Sign in to post your reply or Sign up for a free account.