RoadRunner RoadRunner - 2 months ago 7
C Question

Column Value Reporting String Array C

I made this sample 2d array of strings

char *strings[][4] = {{"Sport", "gender", "country", "medal"},
{"Cycling", "Womens", "China", "first"},
{"Swimming", "Womens", "China", "second"},
{"Swimming", "Womens", "Indonesia", "third"},
{"Cycling", "Womens", "New Zealand", "second"},
{"Cycling", "Womens", "New Zealand", "third"},
{"Swimming", "Womens", "New Zealand", "first"}}


Which has already been pre-sorted based on columns
3 1
, whereby it was sorted first by country(column 3) and then when that column had ties, then it was sorted based on sports(column 1).

I am trying to do some simple hierarchical reporting, something like this:

China
Cycling 1
Swimming 1

Indonesia
Swimming 1

New Zealand
Cycling 2
Swimming 1


Where the data is grouped firstly by the countries(column 3), then counts of the sports for each country are taken, where no repeats for any sport must occur in each country.

I also want to make this diverse, let's say the array is pre sorted on columns
3 1 2
, then this would look like this:

{{"Sport", "gender", "country", "medal"},
{"Cycling", "Womens", "China", "first"},
{"Swimming", "Womens", "China", "second"},
{"Swimming", "Womens", "Indonesia", "third"},
{"Cycling", "Womens", "New Zealand", "second"},
{"Cycling", "Womens", "New Zealand", "third"},
{"Swimming", "Womens", "New Zealand", "first"}}


but then the hierarchical reporting would look a bit different:

China
Cycling
Womens 1
Swimming
Womens 1

Indonesia
Swimming
Womens 1

New Zealand
Cycling
Womens 2
Swimming
Womens 1


I have already got the sorting figured out, my issue is just getting this sort of hierarchical reporting to work.

For the column specifications, I have just been using command line arguments, and my program looks like this so far:

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

#define MAXSIZE 10

int
main(int argc, char **argv) {
char *strings[][4] = {{"Sport", "gender", "country", "medal"},
{"Cycling", "Womens", "China", "first"},
{"Swimming", "Womens", "China", "second"},
{"Swimming", "Womens", "Indonesia", "third"},
{"Cycling", "Womens", "New Zealand", "second"},
{"Cycling", "Womens", "New Zealand", "third"},
{"Swimming", "Womens", "New Zealand", "first"}};

int count, start_index, i;
int columns[MAXSIZE];

/* Storing command line args in array */
start_index = 1;
count = 0;
for (i = 0; i < argc-1; i++) {
columns[i] = atoi(argv[start_index]);
count++;
start_index++;
}

/* printing command line args out */
for (i = 0; i < count; i++) {
printf("%d ", columns[i]);
}

return 0;
}


Is there any way I can achieve this sort of hierarchical reporting? Is there some sort of special algorithm I need to implement for this?

Answer

This may give you some ideas. The function will need a depth for the number of columns to consider ( 1, 2...). If those columns match, increment the count. Otherwise print the count and reset the count to 1. col[] is the sort order for the columns. This assumes that row zero is the column headings instead of data.

void print_array(char str[][COLS][MAX_CH], int nrows, int ncols, int depth, int col[]) {
    int i, j;
    int count = 1;
    int width = 0;
    int same = 0;
    int wide = 0;
    int widest = 0;
    int order[COLS] = { 0};

    for (i = 1; i < nrows; i++) {
        for (j = 0; j < ncols; j++) {
            if ( strlen ( str[i][j]) > widest) {
                widest = strlen ( str[i][j]);//the widest element
            }
        }
    }
    widest += 2;

    for (i = 1; i < nrows; i++) {
        same = 0;
        for (j = 0; j < ncols; j++) {
            if ( j < depth) {
                if ( strcmp ( str[i][order[j] - 1], str[i - 1][order[j] - 1]) == 0) {
                    same++;
                }
                else {
                    break;
                }
            }
        }
        if ( same == depth) {
            count++;
        }
        else {
            if ( i > 1) {
                printf ( "%*d\n", widest - wide, count);
            }
            count = 1;
            if ( same == 0 && i > 1) {
                printf ( "\n");
            }
        }
        if ( count == 1) {
            for (j = 0; j < ncols; j++) {
                if ( ( same - j) > 0 && ( strcmp (str[i][order[j] - 1], str[i - 1][order[j] - 1]) ==  0)) {
                    continue;
                }
                if ( j < depth) {
                    width = strlen ( str[i][order[j] - 1]) + j * 4;
                    wide = strlen ( str[i][order[j] - 1]);
                    printf("%*s", width, str[i][order[j] - 1]);
                    if ( j < depth - 1) {
                        printf ( "\n");
                    }
                }
            }
        }
    }
    printf ( "%*d\n", widest - wide, count);
}
Comments