【问题标题】:Column Value Reporting String Array C列值报告字符串数组 C
【发布时间】:2017-01-18 21:31:40
【问题描述】:

我制作了这个示例二维字符串数组

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;
}

有什么方法可以实现这种分层报告?我需要为此实现某种特殊算法吗?

【问题讨论】:

    标签: c arrays string algorithm


    【解决方案1】:

    如果您对数组进行排序并使用 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;
    }
    

    【讨论】:

      【解决方案2】:

      我知道您提到过您对这些数据进行了手动排序,但除非您愿意采用其他数据结构(例如字符串图,而不是字符串数组),否则如果没有动态排序,您将一事无成... 请耐心等待,我会带你快速方式:

      让我们重新发明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]);
      }
      

      这仍然主要按运动排序,但如有必要,还会考虑比较中的其他列,这会将来自同一国家和运动的所有女性归为一组,这样您就可以轻松消除重复项,例如...

      对于四列,按列的顺序共有十六种排列。我会把它作为练习留给你写你最感兴趣的。

      【讨论】:

      • 您可能也(最终)对命名您的结构成员感兴趣,例如struct entry { sport sport; gender gender; etc... }
      【解决方案3】:

      这可能会给你一些想法。该函数需要一个深度来考虑要考虑的列数(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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-18
        • 1970-01-01
        • 1970-01-01
        • 2012-05-24
        • 2020-12-01
        • 1970-01-01
        • 2016-10-20
        • 1970-01-01
        相关资源
        最近更新 更多