1

Let's assume I got two arrays, one of which contains certain numbers and the other one contains the names corresponding to those numbers, in a way that sums[i] is associated with names[i].

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

int main()
{
  char *names[] = {"William","Olivia","Willaim","Olivai","Lily","Lyli"};
  int sums[6] = {58, 48, 58, 48, 30, 30};
  int i, j, s = 6;
  char *temp_char;
  int temp_int;
  for(i=0 ; i < s-1 ; i++){
    for (j=0; j<s-i; j++){
      if (sums[j]<sums[j+1]){
        temp_char = names[j+1];
        temp_int = sums[j+1];
        names[j+1] = names[j];
        sums[j+1] = sums[j];
        names[j] = temp_char;
        sums[j] = temp_int;
      }

      if ((sums[j] == sums[j+1]) && (strcmp(names[j], names[j+i])>0)) {
        temp_char = names[j+1];
        names[j+1] = names[j];
        names[j] = temp_char;
      }
    }
  }

  for (i = 0; i<s; i++){
    printf("%d ", sums[i]);
    printf("%s\n", names[i]);
  }

  return 0;
}

This is a part of an original code, which compiled but didn't really sort properly. However this one suddenly returns segmentation fault.

Why am I suddenly getting this error and why doesn't the sorting work?

1
  • Life will be easier when you learn about structures so that you can avoid having 'parallel arrays' that both have to be sorted. Commented Aug 5, 2019 at 6:45

2 Answers 2

1

Your program doesn't execute to segmentation fault. (at least when compiled & executed via GCC 7.2 in Ubuntu). However, there are a few points that you might need to focus upon in order to get your sorting part straight.

  1. Focus at this line : for (j=0; j<s-i; j++). Here, the final value that j will acquire will be 5. How ? You have declared s as 6 during it's initialization and the minimum value of i is 0. So by default j can range over 0 to 5 (note that j has to be less than s-i, therefore, the for loop won't let it go beyond 5). But how does it affect your logic? Now if the maximum value that j acquires is 5, then maximum of j+1 will be 6. Therefore, when you perform swapping in the extreme end(at j=5), you might end up with a garbage value in your array. You'll notice this fact, as soon as you'll execute your code multiple times. To resolve this issue, simply use for (j=0; j<s-i-1; j++).
  2. Now come at the line containing this (strcmp(names[j], names[j+i])>0) statement. Your code says that you're using bubble sort in the descending fashion. Therefore, for that to happen here, you need to have (strcmp(names[j+1], names[j])>0). This will allow you to compare your string at the (j+1)th index to that of jth index. If the string at (j+1)th index is bigger than the one at jth index, then you can go for swapping(since, you want your sorting to be done in descending fashion).

To put the above thoughts into practice, here we go :

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

int main()
{

    char *names[] = {"William","Olivia","Willaim","Olivai","Lily","Lyli"};
    int sums[6] = {58, 48, 58, 48, 30, 30};
    int i, j, s = 6;
    char *temp_char;
    int temp_int;
    for(i=0 ; i < s ; i++){
          for (j=0; j<s-i-1; j++){ //Change 1
              if (sums[j]<sums[j+1]){
                  temp_char = names[j+1];
                  temp_int = sums[j+1];
                  names[j+1] = names[j];
                  sums[j+1] = sums[j];
                  names[j] = temp_char;
                  sums[j] = temp_int;
              }
              if ((sums[j] == sums[j+1]) && (strcmp(names[j+1], names[j])>0)) { //Change 2
                  temp_char = names[j+1];
                  names[j+1] = names[j];
                  names[j] = temp_char;
              }           
          }
    }

    for (i = 0; i<s; i++){
          printf("%d ", sums[i]);
          printf("%s\n", names[i]);
    }

    return 0;
}

A suggestion for your code : Use struct to combine your names and sums array together. Efficiency wise it wouldn't seem like much, but it'll help your code to appear much more cleaner.

Sign up to request clarification or add additional context in comments.

1 Comment

If the OP uses structures, then the standard qsort() function can be used to do the sorting — it requires a comparison function, of course, but that wouldn't go completely amiss in this code either.
1

SOLUTION:

You are getting the error because of variable j which might cross the index bound.

So, you should check for j < s-i-1; in the inner loop. And also I optimized your code with the isSwapped boolean variable.

CODE:

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int main()
{

  char *names[] = {"William","Olivia","Willaim","Olivai","Lily","Lyli"};
  int sums[6] = {58, 48, 58, 48, 30, 30};
  int i, j, s = 6;
  char *temp_char;
  int temp_int;
  bool isSwapped; // for optimization
  for(i=0 ; i < s ; i++){
    isSwapped = false;
    for (j=0; j<s-i-1; j++) { 
      // Sort by sum
      if (sums[j]<sums[j+1]){
          temp_char = names[j+1]; temp_int = sums[j+1];
          names[j+1] = names[j]; sums[j+1] = sums[j];
          names[j] = temp_char; sums[j] = temp_int;
          isSwapped = true;
      }
      // Sort by name (only if values of sum is same)
      else if ((sums[j] == sums[j+1]) && (strcmp(names[j+1], names[j])>0)) {
          temp_char = names[j+1];
          names[j+1] = names[j];
          names[j] = temp_char;
          isSwapped = true;
      }
    }
    if (!isSwapped) break;
  }

  for (i = 0; i<s; i++){
    printf("%d ", sums[i]);
    printf("%s\n", names[i]);
  }

  return 0;
}

7 Comments

This works great, but I can't really comprehend why was isSwapped really needed. In my original code this kept swapping names back and fourth, even though they were already sorted correctly. Shouldn't (strcmp(names[j+1], names[j])>0)) allow it to swap only if they haven't been sorted yet?
@MLapaj Because the code always runs at O(n^2) but with isSwapped flag, for the best case it is O(n) and for the average case O(n Log n). Read more about it at geeksforgeeks.org/bubble-sort
Ok, I do understand this. But still ((sums[j] == sums[j+1]) && (strcmp(names[j+1], names[j])>0)) appears to be true even in some cases where sums are equal but the names already are in ascending order. This causes to unnecessarily swap the names.
What is more if I swap names and sums in the code above for char *names[] = {"Elijah,Chloe,Elizabeth,Matthew,Natalie,Jayden"}; int sums[6] = {32, 21, 58, 58, 37, 30}; once again the segmentation faults appears.
I am not sure why you are getting the segmentation fault. And for the case, char *names[] = {"Aa", "Ab", "Ba", "Bb", "Ca", "Cb"}; int sums[6] = {1,1,1,1,1,1};, the output will be in the order "Cb", "Ca", "Bb", "Ba", "Ab", "Aa". Can you provide any case at which you are getting the segmentation fault. It would be good if you update the question with that.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.