views:

59

answers:

2

I have a bunch of strings that look like:

'Hello1-FOO', 'Aello2-FOO', 'Bye1-BAR', 'Bye3-BAR', 'Hello22-FOO', 'Bye4-BAR', 'Welcome-BAR' ...

All of them are stored on a struct.

struct str {
    char *strings;
}
...
struct str **t_str;
size_t j;
t_str = malloc(sizeof *t_str * 20);
for (j = 0; j < 20; j++)
    t_str[j] = malloc(sizeof *t_str[j]);
...
t_str[0]->strings = "Hello1-FOO";
t_str[1]->strings = "Aello2-FOO";
....

What I would like to do is to display (sort) them by category, so they look similar to this:

FOO:
 Hello1-FOO
 Aello2-FOO
 Hello22-FOO

BAR:
 Bye4-BAR
 Welcome-BAR
 Bye1-BAR
 Bye3-BAR

Basically group them by the token after the '-'

What would be a good way of doing this? Should I store them on a second struct after processing the string? Any idea will be appreciated. Thanks

+1  A: 

Just use qsort. The following code makes some assumptions but you should be able to change it to suit your needs.

int categoryComparitor(const void * a, const void * b)
{
  char *string1 = (char *)a;
  char *string2 = (char *)b;

  string1 = strrchr(string1, '-') + 1;
  string2 = strrchr(string2, '-') + 1;

  return strcmp(string1, string2);
}


{
  ...
  char *strings[];  // Array of string pointers
  int stringCount;  // Holds current number of valid elements in strings.
  ...
  qsort(strings, stringCount, sizeof(char *), categoryComparitor);
}
torak
+1 for using standard libary functions instead of reinventing.
schot
A: 

As David Thornley already pointed out, your struct isn't really defined well to handle this situation (well at all). Since your input is two separate logical pieces, you really want to define the struct accordingly -- containing two separate strings, one for each part of the input.

struct record { 
    char *category;
    char *string;
};

Then you want to read each piece into one of those two strings:

record read_line(FILE *infile) { 
    char buffer1[128], buffer2[128];
    fscanf(infile, "%[^-]-%s", buffer1, buffer2);
    record ret;
    ret.string = dupe_string(buffer1);
    ret.category = dupe_string(buffer2);
    return ret;
}

Then, to sort those records, you'll want to define a comparison function with the signature expected by qsort, that does a comparison on the category member:

int cmp(void *a, void *b) { 
    return strcmp(((record *)a)->category, ((record *)b)->category);
}

Then you'll sort your array of records using that comparison function.

Jerry Coffin