lesovsky lesovsky - 3 months ago 9
C Question

C - Sorting 3d string array by specific column

I have code example which sorts 3d string array.

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

static char * rand_string(size_t ssize)
{
char * str = malloc(sizeof(char) * ssize);
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
if (ssize) {
--ssize;
for (size_t n = 0; n < ssize; n++) {
int key = rand() % (int) (sizeof charset - 1);
str[n] = charset[key];
}
str[ssize] = '\0';
}
return str;
}

char *** init_array(char *** array, int n_rows, int n_cols, int ssize)
{
int i, j;
array = malloc(n_rows * sizeof(char **));
for (i = 0; i < n_rows; i++)
{
array[i] = malloc(n_cols * sizeof(char *));
for (j = 0; j < n_cols; j++)
array[i][j] = malloc(ssize * sizeof(char));
}
return array;
}

void gen_array(char *** array, int n_rows, int n_cols, int ssize)
{
int i, j, k;
for (i = 0; i < n_rows; i++)
for (j = 0; j < n_cols; j++)
snprintf(array[i][j], ssize, "%s", rand_string(ssize));
}

int str_compare(const void * a, const void * b)
{
const char *pa = **(const char ***) a;
const char *pb = **(const char ***) b;

// printf("debug: a = %s\n", **(const char ***) a);
return strcmp(pa, pb);
}

void print_array(char *** array, int n_rows, int n_cols)
{
int i, j;
for (i = 0; i < n_rows; i++) {
for (j = 0; j < n_cols; j++)
printf("%s ", array[i][j]);
printf("\n");
}
}

int main(void)
{
int n_rows = 3, n_cols = 5, ssize = 10;
char *** z;

z = init_array(z, n_rows, n_cols, ssize);
gen_array(z, n_rows, n_cols, ssize);
print_array(z, n_rows, n_cols);
printf("\n");
qsort(z, 3, sizeof(char *), str_compare);
print_array(z, n_rows, n_cols);

return 0;
}


with the following output, where are origin array and sorted array (these are example values and randomness doesn't matter):

nwlrbbmqb hcdarzowk kyhiddqsc dxrjmowfr xsjybldbe
fsarcbyne cdyggxxpk lorellnmp apqfwkhop kmcoqhnwn
kuewhsqmg bbuqcljji vswmdkqtb xixmvtrrb ljptnsnfw

fsarcbyne cdyggxxpk lorellnmp apqfwkhop kmcoqhnwn
kuewhsqmg bbuqcljji vswmdkqtb xixmvtrrb ljptnsnfw
nwlrbbmqb hcdarzowk kyhiddqsc dxrjmowfr xsjybldbe


I am looking for a way to sort by another column (second or third). Is it possible?

Thanks.

Answer

You can sort the matrix along its second column with this sorting function:

int str_compare2(const void * a, const void * b) {
    const char *pa = ((const char ***)a)[0][1];
    const char *pb = ((const char ***)b)[0][1];

    return strcmp(pa, pb);
}

Changing the 1 into 2 will sort along the third column, etc.

Note that you should invoke qsort this way:

qsort(z, 3, sizeof(char **), str_compare);

z is an array of char **, not char *. On most architectures, sizeof(char*) == sizeof(char **), so there is no difference, but for consistency and readability, using the correct type is advisable.