Home > Enterprise >  Bubble Sorting structures alphabetically by a last_name string
Bubble Sorting structures alphabetically by a last_name string

Time:10-22

Here is my code for a bubble sort that is supposed to put the customer structs in order by the last name of the customer that is read in by ...last_customer. I am not sure why it isn't working.

    void sort_customers (struct customers *p_info, int num_customers) { 
    struct customers *p_temp,
                     *p_walker;
   int current;
   
   for (current = 0; current < (num_customers-1); current  ) 0
      for(p_walker = p_info; (p_walker-p_info) > current; p_walker--)
         if (strcmp(p_walker->last_name, (p_info)->last_name) != 0)
         {
            p_temp   = p_walker;
            p_walker = p_info;
            p_info   = p_temp;
         }       
   return;
}

Given the ideal input: Jones, Smith, Allen

This would be the ideal output: Allen, Jones, Smith

As you can see this loop is supposed to set the structures in order so that when i call the structure last names in a print function, they will appear in order.

CodePudding user response:

Problems

Hey, I think I found several problems in your code.

  • Both of your for loops don't have any {}
first loop
  • by using (num_customers-1) you skipped one element.
second loop
  • the for loop is never executed. Your condition is never met.
  • if you decrement the p_walker u "walk" in the wrong direction. I believe your pointer p_info is the lowest pointer in the array.
  • in general, I think the pointer arithmetic in the for loop is causing a lot of problems in readability and understanding. I personally would do the pointer arithmetic after you calculated your indexes in the loops.

Example from wiki:

void bubblesort(int array[], int length)  
{
   int i, j, tmp;

   for (i = 1; i < length; i  )
   {
      for (j = 0; j < length - i; j  ) 
      {
          if (array[j] > array[j   1]) 
          {
              tmp = array[j];
              array[j] = array[j   1];
              array[j   1] = tmp;
          }
      }
   }
}
if statement
  • you compared all your values you walked through with the start of your vector at p_info. I believe in typical bubble sort, you would compare with the next neighbor.
  • != 0 in your if statement would be true when the values(Strings) are greater and also if they are lesser. They would just switch all the time if the strings are not equal.
swap
  • one of the swapping strings was at p_info. This would destroy your reference to the beginning of the string. And possible cause a seg-fault error.
  • if you want to use pointer arithmetic in the index of the second for-loop u need to swap the values of your structs and not only the pointers.

Possible Solution

full compilable solution

Your function in a way it should work.

void sort_customers (struct customers *p_info, int num_customers){
    struct customers *p_walker;
    struct customers temp;
    int current;
   
    for (current = 0; current < num_customers; current  ){
        printf("%s\n", "1");
        for(p_walker = p_info; p_walker < p_info (num_customers-current-1); p_walker  ){
            printf("%s\n", "2");
            if (strcmp(p_walker->last_name, (p_walker 1)->last_name) > 0)
            {
                temp   = *p_walker;
                *p_walker = *(p_walker 1);
                *(p_walker 1)   =temp;
            }  
        }
    }     
   return;
}

the input p_info is expected as a pointer to an array of struct customers * that are defined as followed:

struct customers{
    char* last_name;
};

CodePudding user response:

Some issues that I found:

for(p_walker = p_info; (p_walker-p_info) > current; p_walker--)

will not execute ever, as p_walker-p_info is 0 (after setting them to the same value that is).

strcmp does not directly tell you which last_name is alphabetically "later", only that they are different. So your code would swap the two customers always if they were of different name.

I tried to fix the code and came up with this (quite different):

void sort_customers (customers *p_info, int num_customers) 
{
    customers *p_temp = 0;

    do
    {
        for (int i = 1; i <= num_customers - 1; i  )
        {
            if (strcmp( p_info[i].last_name, p_info[i-1].last_name) != 0)
            {
                for (int idx = 0; idx < strlen( p_info[i].last_name); idx   )
                {
                    if (p_info[i].last_name[idx] < p_info[i-1].last_name[idx])
                    {
                        /* found a difference, and i-1 th element is bigger (i.e. later in the alphabet) */
                        memcpy(p_temp, &p_info[i], sizeof(customers));
                        memcpy(&p_info[i], &p_info[i-1], sizeof(customers));
                        memcpy(&p_info[i-1], p_temp, sizeof(customers));
                    }
                    break;
                }
            }
        }
        num_customers--;
    }while(num_customers > 1);

    return;
}

An example main function with

typedef struct
{
    char last_name[5];
} customers;

int main (void)
{
    customers c[6] = {{"ghi"},{"abc"}, {"def"}, {"hij"}, {"sdf"}, {"auf"}};
    
    sort_customers(c, 6);
    
    for (int i = 0; i<6; i  )
    printf ("c[%d].last_name = %s\n", i, c[i].last_name);
    return -1;
}

returns:

c[0].last_name = abc
c[1].last_name = auf
c[2].last_name = def
c[3].last_name = ghi
c[4].last_name = hij
c[5].last_name = sdf
  • Related