0

So I am a complete beginner to C, and I was trying to sort an array of strings without using qsort. Here is the code:

#include <stdio.h>
#include <string.h>
void sort(char *ar[],int n)
{
    int i,j;
    char temp[10]; 
    for (i=0;i<n-1;i++)
    {
        for (j=0;j<n-i-1;j++)
        {
            if ((strcmp (*(ar+j),*(ar+j+1)))>0)
            {
                strcpy (temp, *(ar+j));
                strcpy (*(ar+j), *(ar+j+1));
                strcpy (*(ar+j+1), temp);
                printf ("%s\n", temp);
            }
        }
    }
    /*printf ("After sorting: \n");
    for (i=0;i<n;i++)
    printf ("%s\n", *(ar));*/
}
int main()
{
    int i,n;
    char* ar[]={"ghi","def","abc"};
    n = sizeof(ar)/sizeof(*ar);
    printf ("Before sorting: \n");
    for (i=0;i<n;i++)
    printf ("%s\n", *(ar+i));
    sort (ar,n);
    printf ("After sorting: \n");
    for (i=0;i<n;i++)
    printf ("%s\n", *(ar+i));
    return 0;
}

However, it only prints the strings before sorting. What am I doing wrong here?

3 Answers 3

3

You have undefined behavior in your sorting function.

There are two reasons:

  1. You use an array of pointers, and each pointer is pointing to a literal string;
  2. You use strcpy to copy contents between the strings.

In C attempting to modify a literal string is undefined behavior. Literal strings are in essence read-only. Note that they are not constant, even through it's always recommended to use const pointers.

You have two possible way of solving this:

  1. Use an array of arrays instead:

    char ar[][10] = { ... };
    

    Then the contents of the strings are modifiable, and you can use strcpy.

  2. Or swap the pointers instead:

    char *temp = ar[j];
    ar[j] = ar[j + 1];
    ar[j + 1] = temp;
    
Sign up to request clarification or add additional context in comments.

Comments

0

Your main problem is that you're using strcpy() with string literals, which isn't allowed. If you swap the pointers instead, your algorithm works perfectly. Here's an updated version of sort():

void sort(char *ar[],int n)
{
    int i,j;
    char* temp; 
    for (i=0;i<n-1;i++)
    {
        for (j=0;j<n-i-1;j++)
        {
            if (strcmp (ar[j], ar[j + 1] ) > 0)  // more readable with indexing syntax
            {
                temp = ar[j];
                ar[j] = ar[j+1];
                ar[j+1] = temp;
                printf ("%s\n", temp);
            }
        }
    }
}

Comments

0

I think you'd better use strdup() to copy a string instead of using strcpy, because the former string will store in heap while the latter string will store in stack which is easily lost after your calling sort().

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

void sort(char *array[], int start, int end) {
    for (int i = start; i <= end - 1; i++) {
        for (int j = i + 1; j <= end; j++) {
            // swap if array[i] > array[j]
            if (strcmp(array[i], array[j]) > 0) {
                char *tmp = strdup(array[j]);
                array[j] = strdup(array[i]);
                array[i] = strdup(tmp);
            }
        } 
    }
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <string> ...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    sort(argv, 1, argc - 1);            // sort

    for (int i = 1; i < argc; i++) {
        printf("%s ", argv[i]);
    }
    printf("\n");

    exit(EXIT_SUCCESS);
}
$ ./sort_string_array ghi def abc

abc def ghi

or you could just swap between pointers instead of copying one string to another string.

Comments

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.