按字母顺序排序字符串列表(C语言)

3
好的,这是我的问题。一个老师需要随机选择一名学生(来自她手中的学生)获得最终成绩和特殊奖励,为此她将N张纸编号从1到N,并随机选择一个数字K;获奖的学生是学生列表中的第K个学生。问题在于老师不知道哪个数字对应哪个学生,因为她丢失了包含此信息的纸张。她所知道的是:所有学生的姓名,以及它们的编号,从1到N,按字母顺序分配。

因此,我需要获取作为输入给出的姓名集合,按字母顺序排序,然后提供赢得特别奖励的学生的姓名,但我遇到了麻烦。我编写的程序会对除第一个之外的所有名称进行排序。

此外,当我在Code :: Blocks上运行项目时,会显示以下警告:

  • (第16行)ISO C90禁止数组变量长度 's' [-Wvla]
  • (第13行)ISO C90禁止混合声明和代码[-Wpedantic]

请告诉我我在这里做错了什么,如果有更好的方法可以对名称进行排序,而无需指定名称数量。

注意:当N和K等于零时,程序应停止读取输入。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    int n, k, i, j=0, aux, numMenorNome;
    char str[]="zzzzzzzzzzzzzzzzzzzz", str2[]="zwyxzzzzzzzzzzzzzzzz";

    do
    {
       scanf("%d%d", &n, &k);
       struct student
       {
           char nome[21]; /*name*/
           char nomes_ordenados[21]; /*array to put the names already sorted*/
       } s[n];

       for (i=0; i<n; i++)
       {
           scanf(" %s", s[i].nome);
       }

       for (i=0; i<n; i++)
       {
           aux = strcmp(str, s[i].nome); /*compares the string that would be the last in the alphabetical order ("zzzzzzzzzzzzzzzzzzzz") with the given names*/
           if(aux>0)
           {
               strcpy(str, s[i].nome); /*it gives me the name that comes first in alphabetical order */
               numMenorNome = i;  /* identification number of the name that was obtained */
           }
           if (i==(n-1))
           {
               strcpy(s[j].nomes_ordenados,str); 
               printf("%s\n", s[j].nomes_ordenados);
               strcpy(str, "zzzzzzzzzzzzzzzzzzzz"); 
               strcpy(s[numMenorNome].nome, str2); 
               j++;
               i=0; /* restarts the loop in order to obtain the second name in alphabetical order, the third name, the fourth name and so on */
               if(j==n)
                    break;
           }
       }
       printf("%s\n\n", s[k-1].nomes_ordenados);

    } while (n!=0&&k!=0);
    return 0;
}

scanf("%d%d", &n, &k); 对我来说似乎是错误的。程序怎么知道 n 的结尾和 k 的开头在哪里呢?而且你应该有更一致的缩进/括号风格;否则你会让想要帮助你的人阅读起来更加困难。 - sergiol
1
你收到的两个警告是因为你需要在C99或更高版本(C11)标准下编译你的代码。 - ShadowRanger
1
旁注:您可以使用qsort吗?因为有了qsort来排序名称,这个问题就简单多了,所以您可以直接索引找到第K个学生。您还可以跳过整个“在结构体中使用两个不同名称没有任何好处”的花招,只需存储一个char*数组(变长或动态分配),对该数组进行排序(strcmp已经存在作为排序函数),然后就完成了。 - ShadowRanger
@sergiol 没问题,大多数格式说明符默认在读取值之前跳过空格,因此只需在它们之间放置一些空格即可。 - phuclv
2个回答

6

对一个字符串数组进行排序非常简单。只需使用 qsort 函数和现有的比较函数 (如 strcmp)。

示例:

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

#define NAMES 5
#define NAME_LEN 10

void print_names(char names[][NAME_LEN])
{
    int i;
    for(i=0; i<NAMES; ++i)
    {
        printf("%s\n", names[i]);
    }
}

int main(void) {
    char names[NAMES][NAME_LEN] = { "xxx", "uuu", "ccc", "aaa", "bbb" };

    print_names(names);
    printf("---------------------------------\n");

    qsort(names, NAMES, NAME_LEN, strcmp);

    print_names(names);

    return 0;
}

1

您也可以使用冒泡排序算法!

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

int main(void) {
    char *names[] = { "xxx", "uuu", "ccc", "aaa", "bbb" };
    char *tmp;
    int i = 0, j;
    for(i; names[i]; i++) {
        for(j = 0; names[j]; j++) {
            if(strcmp(names[i], names[j]) < 0) {
                tmp = names[i];
                names[i] = names[j];
                names[j] = tmp;
            }
        }
    }
    for(i = 0; names[i]; i++) printf("%s\n", names[i]);
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接