【问题标题】:How to sort char array by 1) length and 2) alphabetic order?如何按 1)长度和 2)字母顺序对 char 数组进行排序?
【发布时间】:2021-01-26 20:04:41
【问题描述】:

我正在学习 C 编程并正在完成一项学校作业。询问老师或同龄人的可能性有限(由于电晕爆发和在家中的距离),我正在与您联系。非常感谢您的帮助。

我的挑战:编写一个程序,使用不同的函数对 11 个文本字符串按长度和字母顺序进行排序。告诉用户程序的限制是什么。

Desired output, for instance:
bc
bcb
bcebc
cbbcac
dbccac
(...)

首先,用户必须输入 11 个文本字符串。我已经用以下代码解决了这个问题:

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

#define NUMBER_OF_STRINGS 11


int main (void)

char textstrings[NUMBER_OF_STRINGS][15];
int i;

(...) 

printf("Enter 11 textstrings, one by one:\n");
for(i=0;i<NUMBER_OF_STRINGS-1;i++)
   {
   printf("Enter string %d: ", i + 1);
   gets(textstrings[i]);
   }

现在我们在“textstrings[i]”中得到了我们的字符串,它们必须被排序和打印。我认为最好看的方法是为每个排序条件设置单独的函数。例如。 “长度”的单独函数,然后是“字母顺序”的另一个函数。我知道我应该使用“strlen”来比较长度,使用“strcmp”来比较字母顺序。

我也明白,按多个条件排序的策略是为每个返回比较函数的适当返回类型的条件编写比较表达式,并按照所需的排序顺序对它们进行评估,例如第一个长度,然后是字母。

这就是我迷路的地方......

但是,我确实理解按长度排序的逻辑可能如下所示:

char* temp;
int step
int length=20; //Not allowing text longer than 20 characters.

for(step=0;step<length-1;step++)
for(i=0;i<length-step-1;i++)
  {
  if(strlen(textstrings[i])>strlen(textstrings[i+1]))
   {
   temp=textstrings[i];
   textstrings[i]=textstrings[i+1];
   textstrings[i+1]=temp;
   }

而且我也知道按字母顺序排序可能是这样的:

int k, m

for(k=0;k<=NUMBER_OF_STRINGS-1;k++)
{
  for(m=k+1;m<=NUMBER_OF_STRINGS-1;m++)
     if(strmcp(textstrings[k], textstrings[m])>0)
     swap(textstrings[k], textstrings[m]);
}

       where a swap function would look like:

      void swap (char *s1, char *s2)
      {
      char tmp[20];
      strcopy(temp,s1);
      strcopy(s1,s2);
      strcopy(s2,temp);
      }

但是,我不知道如何编写比较表达式,也不明白可以在主函数中保留哪些代码,以及哪些单独的函数是合适的。一个理想的答案将包括一个示例代码来展示如何解决这个任务,因为我不仅仅是迷路了!

谢谢!

【问题讨论】:

  • 您正在尝试的称为“冒泡排序”,是最慢和最简单的排序方式。如果您搜索冒泡排序 C 代码,您应该会找到大量示例。
  • 永远不要使用gets()。请改用fgets()。对于排序,我推荐使用qsort()

标签: arrays c sorting string-length alphabetical-sort


【解决方案1】:

在 C 中对数组进行排序时,您的朋友是 qsort。您只需要实现一个比较函数,然后调用qsort

例如:

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

#define NUMBER_OF_STRINGS 11

int cmplen(const void *p1, const void *p2)
{
    size_t len1 = strlen((const char *) p1);
    size_t len2 = strlen((const char *) p2);
    if (len1 < len2) return -1;
    if (len1 > len2) return  1;
    return 0;
}

int main(int argc, char const *argv[])
{
    char textstrings[NUMBER_OF_STRINGS][15] = {"abcd", "dcg", "htj", "jkler", "qwerty", "zxcvbnm", "a", "aa", "pppp", "lkjh", "ld"};
    qsort(textstrings, NUMBER_OF_STRINGS, sizeof textstrings[0], cmplen);
    for (size_t i = 0; i < NUMBER_OF_STRINGS; ++i) puts(textstrings[i]);
    return 0;
}

输出

a
aa
ld
dcg
htj
abcd
pppp
lkjh
jkler
qwerty
zxcvbnm

如果您想同时按长度和长度优先级最高的字母排序,您可以将比较功能更改为

int cmplen(const void *p1, const void *p2)
{
    size_t len1 = strlen((const char *) p1);
    size_t len2 = strlen((const char *) p2);
    if (len1 < len2) return -1;
    if (len1 > len2) return  1;
    return strcmp((const char *) p1, (const char *) p2);
}

输出

a
aa
ld
dcg
htj
abcd
lkjh
pppp
jkler
qwerty
zxcvbnm

现在输出按长度排序,对于相同的长度,它按字母排序(请注意,“pppp”和“lkjh”与之前仅按长度排序的代码相比交换了位置)。

顺便说一句:不要使用gets 来获取输入。这是不安全的。改为查看fgets

【讨论】:

  • 优秀的答案。我唯一的反对意见是return 0 完全没有必要,但我注意到有些人喜欢这样做。
  • @klutt 谢谢。我从来没有真正考虑过。手册页(我正在使用)明确状态“相等时返回零”所以我总是这样做。如果比较函数不为“相等”元素返回零,您如何确定没有“会混淆”的qsort 实现。
  • 您的字符串在大小组中仅按字母顺序排列,因为它们在输入中是如此。如果您将 textstrings 数组中的“abcd”更改为“zbcd”,zbcd 将出现在 pppp 之前的输出中。你需要改变'return 0;'在 cmplen 中返回 'strcmp( (const char*)p1, (const char*)p2);'你也忘了包括 string.h
  • @dmuir 我认为您误读了这个问题。该问题要求两个不同的功能,即a)按长度排序和b)按字母排序。这不是a)首先然后b)。该答案涵盖 a) 并将 b) 留给 OP。
  • @43864273 我不清楚。我的意思是 return 0main 函数中不是必需的。在cmplen 中,这是完全必要的。
猜你喜欢
  • 2020-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
  • 2021-12-19
  • 2021-04-05
  • 1970-01-01
相关资源
最近更新 更多