我制作了这个样本的2d字符串数组
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"}}
已经根据列3 1
对其进行了预先排序,其中首先按国家/地区排序(第3列),然后当该列具有关联时,则根据体育(第1列)对其进行排序。
我正在尝试做一些简单的分层报告,标题位于顶部,如下所示:
Country
Sport Count
-----------------
China
Cycling 1
Swimming 1
Indonesia
Swimming 1
New Zealand
Cycling 2
Swimming 1
如果数据首先由国家分组(第3列),则每个国家的运动计数都会被采用,而每个国家的运动都不得重复。
我也想让它变得多样化,让我们说数组预先排在列3 1 2
上,然后这将是这样的:
{{"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"}}
但是,分层报告看起来会有所不同:
China
Cycling
Womens 1
Swimming
Womens 1
Indonesia
Swimming
Womens 1
New Zealand
Cycling
Womens 2
Swimming
Womens 1
我已经找到了排序,我的问题只是让这种分层报告工作。
对于列规范,我刚刚使用命令行参数,到目前为止我的程序看起来像这样:
#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];
/* printing command line args out */
for (i = 0; i < count; i++) {
printf("%d ", columns[i]);
}
return 0;
}
有什么方法可以实现这种层次化报告吗?我需要为此实现某种特殊算法吗?
我知道你提到过你对这些数据进行手工排序,但是在你愿意采用其他数据结构(例如字符串图形而不是字符串数组)之前,如果没有动态排序,你将无法获得任何数据结构......忍受我一会儿,我会带你快速的方式:
让我们重新发明
qsort
...等等!让我们使用qsort
!
事实上,在我们研究现有轮子之前,我们有一种重新发明轮子的文化,这是一种耻辱。
您可能希望每行都有一个比较函数。这些将成为分类的标准。在他们最基本的形式中,他们可能看起来像这样:
int sport_compare(void const *x, void const *y) {
typedef char const * const row[4];
row *fu = x, *ba = y;
return strcmp(fu[0], ba[0]);
}
int gender_compare(void const *x, void const *y) {
typedef char const * const row[4];
row *fu = x, *ba = y;
return strcmp(fu[1], ba[1]);
}
... 等等。
我如何使用这些来重新发明
qsort
轮?
#define nelem(array) (sizeof array / sizeof *array)
qsort(array, nelem(array), sizeof *array, country_compare);
现在array
按国家排序......你关注?
qsort(array, nelem(array), sizeof *array, gender_compare);
... 等等。
现在您已经知道如何在几乎任何条件下使用五到六行代码来使用数组,您可以更多地考虑比较函数来解决您的实际问题(即您希望的层次结构)。
例如,当两行在运动中相等时,它们在其他一切中是否相等?您可能想要考虑修改sport_compare
以在两列具有相同运动时检查其余列...例如:
int sport_compare(void const *x, void const *y) {
typedef char const * const row[4];
row *fu = x, *ba = y;
# define maybe_return(condition) do { int c = (condition); if (c) { return c; } } while (0)
maybe_return(strcmp(fu[0], ba[0]));
maybe_return(strcmp(fu[1], ba[1]));
maybe_return(strcmp(fu[2], ba[2]));
return strcmp(fu[3], ba[3]);
}
这仍然主要以运动为主,但如果有必要,还会考虑比较中的其他专栏,这将为您提供来自同一国家的所有女性和运动组合在一起,这样您就可以轻松地消除重复......例如......
对于四列,按列的顺序总共有十六种排列。我会把它作为练习让你写下你最感兴趣的那些。
如果您对数组进行排序并使用for循环,那么您将获得几乎所需的输出:
China
Cycling first
Swimming second
Indonesia
Swimming third
New Zealand
Cycling second
Swimming first
码
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
int main(int argc, char **argv ) {
char *a[][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++;
}
char * temp;
char * temp1;
for(int j=1;j<6;j++)
{
for(i=0; i<5; i++)
{
if(a[0][i]>a[0][i+1])
{
temp=a[0][i];
a[0][i]=a[0][i+1];
a[0][i+1]=temp;
temp1 = a[1][i];
a[1][i] = a[1][i+1];
a[1][i+1]=temp1;
}
}
}
char * country ="";
char * sport = "";
for (int i=1; i<=6; i++) {
if (strcmp(country, a[i][2])) printf("%s \n", a[i][2]);
if (strcmp(country, a[i][2]) || strcmp(sport, a[i][0])) {
country = a[i][2];
sport = a[i][0];
printf("\t%s %s", a[i][0], a[i][3]);
printf("\n ");
}
}
return 0;
}
这可能会给你一些想法。该函数需要深度以考虑列数(1,2 ...)。如果这些列匹配,则递增计数。否则打印计数并将计数重置为1. col[]
是列的排序顺序。这假设行0是列标题而不是数据。
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++;//number of considered columns that are the same
}
else {
break;//stop on the first difference
}
}
}
if ( same == depth) {
count++;//all considered columns are the same, add to count
}
else {
if ( i > 1) {
printf ( "%*d\n", widest - wide, count);//print the alligned count on last printed column but not on first iteration
}
count = 1;
if ( same == 0 && i > 1) {
printf ( "\n");//print extra newline when no columns are the same, after first iteration
}
}
if ( count == 1) {//print the columns
for (j = 0; j < ncols; j++) {
if ( ( same - j) > 0 && ( strcmp (str[i][order[j] - 1], str[i - 1][order[j] - 1]) == 0)) {
continue;//skip columns that are the same
}
if ( j < depth) {//the columns considered by depth
wide = strlen ( str[i][order[j] - 1]);
width = wide + j * 4;//for leading spaces
printf("%*s", width, str[i][order[j] - 1]);//print aligned column
if ( j < depth - 1) {
printf ( "\n");//print a newline except for last col so count can be printed later
}
}
}
}
}
printf ( "%*d\n", widest - wide, count);//print count on last row
}