【问题标题】:How to sort ranking list with correct names output in C?如何用C中输出的正确名称对排名列表进行排序?
【发布时间】:2014-03-05 16:23:24
【问题描述】:

我正在尝试制作一个简单的人员 ID 及其姓名的排名列表。该列表按 Id 升序排序。

我输入的输入是:

Enter: Id Name (5 time)
9 Ace
5 Bob
6 Cindy
7 Dean
2 Erik

我期望得到的输出是

Sorted id is...
2        Erik
5        Bob
6        Cindy
7        Dean
9        Ace

我目前得到的结果是

Sorted id is...
2        ABCDErik
5        BCDErik
6        CDErik
7        DErik
9        Erik

下面是我目前正在使用的代码。这是一个冒泡排序函数:

int sorting(int n, int *array)
{
    int temp;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < (n - i - 1); j++)
        {
            if (array[j] > array[j + 1])
            {
                temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

还有我的主程序:

int main()
{
    int i, j, temp;
    int num = 5;
    int *id = (int *) malloc(sizeof(int) * 5);
    char *name = malloc(sizeof(char) * 10);

    printf("Enter: Id Name (5 time) \n");
    for (i = 0; i < num; i++)
    {
        scanf("%d %s", &id[i], &name[i]);
    }

    sorting(num, id);

    printf("Sorted id is...\n");

    for (i = 0; i < num; i++)
    {
        printf("%d \t %s \n", id[i], &name[i]);
    }

    free(id);
    free(name);
    return 0;
}

有没有办法让正确的名称与它的 id “链接”?

【问题讨论】:

    标签: c arrays list sorting


    【解决方案1】:

    您的数据存储方式错误。当您分配内存以在其中存储字符串时,您必须根据字符串长度正确计算内存大小。

    还有一个char * 是指向一个字符串的指针,字符串数组应该变成char * []

    #define STRINGCOUNT 20
    #define STRINGLEN 100
    
    int maxlen= ... calculated somehow
    int stringcnt= ... calculated somehow
    
    char *stringarray[STRINGCOUNT];
    for (i=0; i<STRINGCOUNT; i++)
       stringarray[i] = malloc(maxlen);
    

    另一种方法是静态分配数据:

    char stringarray[STRINGCOUNT][STRINGLEN]
    

    第三种方法是动态分配所有内容。请注意,使用字符串指针数组和动态分配,每个字符串可能被分配不同的长度。

    char **stringarray=calloc(stringcnt,sizeof(char *));
    for (i=0; i<stringcnt; i++)
       stringarray[i] = malloc(maxlen);
    // or
       stringarray[i] = strdup(somestring);
    

    您还必须记住,C 字符串以 0 字符结尾,因此要存储 Bob,您至少需要 4 个字节。

    您目前所做的是分配 10 个字节的缓冲区,然后他们将所有从不同位置开始的字符串放在那里。

    关于链接数据,C 语言中的概念称为struct。在您的情况下,定义将是

    struct {
       int rank;
       char *name;
    } items;
    

    结构也可以静态或动态分配,但您必须知道名称元素是指向字符串的指针,如果未显式初始化,它将不会指向已分配的内存并且不能使用。

    【讨论】:

    • stringcount 和 MAXLEN 是固定数字还是可变的?
    • 对于 malloc,您可以使用可变缓冲区大小,其他两个应该是固定大小,尽管 gcc 允许在堆栈上动态分配数组,就像您在代码中所做的那样。
    • 奇怪了,名字现在可以正常显示了,但是没有排序。
    • @LordRixuel:名字没有排序,因为你从来没有对它们进行排序。您需要将数字和名称都传递给排序函数,并且需要交换两个数组中的行以保持一切正常组织。还有其他方法可以做到这一点。一种是使用结构数组,每个结构都包含一个 ID 和一个名称。另一个是最初为每行 0..N-1 创建一个数组orderingordering[n] = n。然后交换此数组中的行,比较 id[ordering[x]]id[ordering[y]]。然后您可以使用排序(置换)ordering 数组按顺序打印数据。
    【解决方案2】:

    连接两个数组是索引。 所以通过传递索引和比较序列来排序。

    #include <stdio.h>
    #include <stdlib.h>
    
    void sorting(int n, int *array, int *indexs){
        int temp;
        for (int i = 0; i < n -1 ; ++i){
            for (int j = i + 1; j < n; ++j){
                if (array[indexs[i]] > array[indexs[j]]){
                    temp = indexs[i];
                    indexs[i] = indexs[j];
                    indexs[j] = temp;
                }
            }
        }
    }
    
    int main(){
        int i, j, temp;
        int num = 5;
        int *id = (int *) malloc(num * sizeof(int));
        int *indexs = malloc(num * sizeof(int));
        char **name = malloc(num * sizeof(char*));
        for(i = 0 ; i < num ; ++i){
            name[i] = malloc(sizeof(char) * 10);
            indexs[i] = i;
        }
    
        printf("Enter: Id Name (5 time) \n");
        for (i = 0; i < num; i++)
            scanf("%d %9s", &id[i], name[i]);
    
        sorting(num, id, indexs);
    
        printf("Sorted id is...\n");
    
        for (i = 0; i < num; i++){
            printf("%d \t %s \n", id[indexs[i]], name[indexs[i]]);
            free(name[indexs[i]]);
        }
        free(id);
        free(name);
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      将名称与 ID 链接起来的简单方法是使用结构并分配该结构的数组。你可以像这样修改你的程序:

      typedef struct name_id_pair {
        int id;
        char name[10];
      } name_id_pair_t;
      
      
      
      int sorting(int n, name_id_pair_t *array)
      {
       int i, j;
      name_id_pair_t temp;
      for (i = 0; i < n; i++)
      {
          for (j = 0; j < (n - i - 1); j++)
          {
              if (array[j].id > array[j + 1].id)
              {
                  temp = array[j];
                  array[j] = array[j + 1];
                  array[j + 1] = temp;
              }
          }
      }
      }
      
      int main()
      {
      int i, j;
      int num = 5;
      name_id_pair_t *arr = (name_id_pair_t *) malloc(sizeof(name_id_pair_t) * 5);
      
      printf("Enter: Id Name (5 time) \n");
      for (i = 0; i < num; i++)
      {
          scanf("%d %s", &arr[i].id, &arr[i].name);
      }
      
      sorting(num, arr);
      
      printf("Sorted id is...\n");
      
      for (i = 0; i < num; i++)
      {
          printf("%d \t %s \n", arr[i].id, arr[i].name);
      }
      
      free(arr);
      
      return 0;
      }
      

      【讨论】:

        【解决方案4】:

        您永远不会为多个名称分配内存。

            char *name = malloc(sizeof(char) * 10);
        

        这分配了十个字符,有足够的空间容纳一个短名称,仅此而已。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-08
          • 1970-01-01
          • 1970-01-01
          • 2018-08-19
          • 1970-01-01
          • 2015-07-30
          相关资源
          最近更新 更多