There are a number of ways to approach this task, as you can see from the number of answers. One element you will need, for either the countries, or the events (but not both), is a simple lookup table containing either country entries or event entries to allow you to distinguish whether the values in results are country names or event names. A simple country lookup (made global here, but could be function scope as well) such as the following works:
char *countries[] = { "Canada", "India", "New Mexico" }; /* countries lookup */
Another shortcut you can take is recognizing that the pointers within results have function scope as defined, so there is no need to copy or allocate memory to hold them -- they already exist in readonly memory.
One other struct element that helps is to keep a count of the events associated with the country, say eventcnt. That can be incremented each time an event is added under the country. You can use a country/events struct similar to:
typedef struct {
char *country;
char *event[MAXE];
int eventcnt;
} host;
(the MAXE is a simple constant for the maximum events involved to allow you to use automatic storage with your array of structs. (it can easily be changed to allocate/reallocate storage on an as needed basis)
You then need to simply loop through the results array, once, understanding that events always follow the country before them. Using several nested loops keeps the number of times you traverse results to one-time. Essentially, you loop over each pointer in results, determine if it points to a country name, if it is a country name, then either add it if it doesn't exists as one of your host.country values, or skip it if it does (no need to updated pointers to point to the last occurrence of the country name)
Since nested loops are involved, a simple goto provides all the control you need to determine when you are dealing with country names of when you are dealing with event names and allows you to take the action needed in each case.
Then it is just a matter of printing/using the results you wanted which are now contained in a array of struct with hidx (host index) containing the total number of unique hosts involved.
Putting the pieces together, you could do something similar to the following:
#include <stdio.h>
#include <string.h>
/* constants max(countries, events) */
enum { MAXC = 8, MAXE = 16 };
char *countries[] = { "Canada", "India", "New Mexico" }; /* countries lookup */
typedef struct {
char *country;
char *event[MAXE];
int eventcnt;
} host;
int main (void) {
char *results[] = { "Canada", "Cycling", "Canada", "Swimming",
"India", "Swimming", "New Mexico", "Cycling",
"New Mexico", "Cycling", "New Mexico", "Swimming"};
host hosts[MAXC] = {{ .country = NULL }};
int hidx = 0, i, j, country_count, current = 0, nelements;
country_count = sizeof countries/sizeof *countries;
nelements = sizeof results / sizeof *results;
for (i = 0 ; i < nelements; i++) { /* for each element */
for (j = 0; j < country_count; j++) { /* check if country */
if (strcmp (results[i], countries[j]) == 0) { /* if so */
int k;
for (k = 0; k < hidx && /* check if already assigned */
strcmp (hosts[k].country, countries[j]); k++) {}
if (!hosts[k].country) { /* if not, assign ptr, increment */
hosts[hidx++].country = results[i];
current = hidx - 1;;
}
goto nextc; /* skip event adding */
}
} /* results[i] is not a country, check if event exists for host */
if (hosts[current].eventcnt < MAXE) { /* if it doesn't, add it */
int k;
for (k = 0; k < hosts[current].eventcnt; k++)
if (strcmp (results[i], hosts[current].event[k]) == 0)
goto nextc; /* already exists for host, skip add */
hosts[current].event[hosts[current].eventcnt++] = results[i];
}
nextc:;
}
for (i = 0; i < hidx; i++) { /* output countries & events for each */
printf (" %s\n", hosts[i].country);
for (j = 0; j < hosts[i].eventcnt; j++)
printf (" %s\n", hosts[i].event[j]);
}
return 0;
}
Example Use/Output
$ ./bin/events
Canada
Cycling
Swimming
India
Swimming
New Mexico
Cycling
Swimming
Look over all the answers. There are many good points contained. Let me know if you have any questions.
char *results[][2]for starters.mapin c++?