如何在C语言中按升序对字符串数组进行排序

4

问题

我写了一个类似于https://beginnersbook.com/2015/02/c-program-to-sort-set-of-strings-in-alphabetical-order/的排序程序,但是我的程序不起作用。 我认为两个程序是一样的,但我的程序给我输出垃圾结果。

此外,我想知道在另一个程序中,例如计数设置为5,应该从0开始取6个输入,但它只获得了5个,怎么回事?

我的程序

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

int main() {

char str[4][10],temp[10];
int i,j;
printf("Enter strings one by one : \n");
for(i=0;i<5;i++)
    scanf("%s",str[i]);

for(i=0;i<5;i++)
    for(j=i+1;j<5;j++)
        if(strcmp(str[i],str[j])>0){
            strcpy(temp,str[i]);
            strcpy(str[i],str[j]);
            strcpy(str[j],temp);
        }

printf("\nSorted List : ");
for(i=0;i<5;i++)
    printf("\n%s",str[i]);
printf("\n\n");

return 0;

}

1
你正在将六个字符串存储在只有足够空间容纳四个字符串的数组中,并且没有检查这些字符串的长度(必须小于9个字符)。难怪它不起作用。 - r3mainer
你有一个包含4个元素的数组,但是你想要往里面放6个元素。建议使用'char str[6][10],temp[10];'来获得更好的体验。 - tevemadar
4个元素?我认为数组从0开始,所以应该是5个元素的数组(重新编辑以存储5个)。 - anmoloo7
1
你的想法是错误的:[4]数组有四个元素,有效索引为0,1,2和3。请参考我的先前建议。你的算法可能能够工作,但会破坏变量并导致程序崩溃。这正是为什么C语言被认为是“危险”的原因。 - tevemadar
谢谢你,tevemadar。现在我只想知道其他程序是如何仅将5个元素存储在输入5中的计数器中,因为从0到5意味着要执行6次循环,但循环仅执行5次以进行输入。 - anmoloo7
6个回答

12

使用qsort()函数。

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

int pstrcmp( const void* a, const void* b )
{
  return strcmp( *(const char**)a, *(const char**)b );
}

int main()
{
  const char* xs[] =
  {
    "Korra",
    "Zhu Li",
    "Asami",
    "Mako",
    "Bolin",
    "Tenzin",
    "Varrick",
  };
  const size_t N = sizeof(xs) / sizeof(xs[0]);

  puts( "(unsorted)" );
  for (int n = 0; n < N; n++)
    puts( xs[ n ] );

  // Do the thing!
  qsort( xs, N, sizeof(xs[0]), pstrcmp );

  puts( "\n(sorted)" );
  for (int n = 0; n < N; n++)
    puts( xs[ n ] );
}
请不要使用冒泡排序。在 C 语言中,除了特殊需求外,您真的不需要编写自己的排序算法。

2

这是一个可以对输入的字符串进行排序并打印输出的程序。虽然回答有点晚,但以防其他人有类似的问题。

// This program will sort strings into either ascending or descending order
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE            1000
#define EQUAL               0
#define ASCENDING           0
#define DESCENDING          1

// Function prototypes
void swap_str(char str1[], char str2[]);
void sort_strings(char str[MAX_SIZE][MAX_SIZE], int len, int order_type);
void print_2d_array(char str[MAX_SIZE][MAX_SIZE], int len);

int main(void) {

    int order_type;
    char str[MAX_SIZE][MAX_SIZE];

    // User selecting the order type
    printf("-----------[Order Type]-----------\n");
    printf("Sort your strings in ascending or descending order?\n");
    printf("0 = Ascending | 1 = descending\n");

    scanf("%d", &order_type);
    if (order_type != ASCENDING && order_type != DESCENDING) {
        printf("Please enter 0 or 1\n");
        exit(1);
    }

    // User inputting their strings
    printf("---------[Enter Strings]----------\n");
    printf("Enter Strings one by one.\n");
    printf("Max Strings: %d | Max String Len: %d\n", MAX_SIZE, MAX_SIZE);

    int i = 0;
    while ((i < MAX_SIZE) && (scanf("%s", str[i]) == 1)) i++;
    if (i == MAX_SIZE) printf("You reached the maximum strings allowed\n"); 

    // Program output of the sorted strings    
    printf("---------[Sorted Strings]---------\n");
    sort_strings(str, i, ASCENDING);
    print_2d_array(str, i);

    return 0;
}

// Swaps two strings (assuming memory allocation is already correct)
void swap_str(char str1[], char str2[]) {

    char temp[MAX_SIZE];

    strcpy(temp, str1);
    strcpy(str1, str2);
    strcpy(str2, temp);

}

// Will sort a 2D array in either descending or ascending order,
// depending on the flag you give it
void sort_strings(char str[MAX_SIZE][MAX_SIZE], int len, int order_type) {

    int i = 0;
    while (i < len) {

        int j = 0;
        while (j < len) {

            if ((order_type == ASCENDING) &&
                (strcmp(str[i], str[j]) < EQUAL)) {

                swap_str(str[i], str[j]);
            } else if ((order_type == DESCENDING) &&
                (strcmp(str[i], str[j]) > EQUAL)) {

                swap_str(str[i], str[j]);
            }

            j++;
        }

        i++;
    }

}

// Will print out all the strings 2d array
void print_2d_array(char str[MAX_SIZE][MAX_SIZE], int len) {

    int i = 0;
    while (i < len) {
        printf("%s\n", str[i]);
        i++;
    }
}

例子(升序):

-----------[Order Type]-----------
Sort your strings in ascending or descending order?
0 = Ascending | 1 = descending
0
---------[Enter Strings]----------
Enter Strings one by one.
Max Strings: 1000 | Max String Len: 1000
Mango
Watermelon
Apple
Banana
Orange
// I pressed CTRL+D here (Linux) or CTRL+Z then enter (on Windows). Essentially triggering EOF. If you typed the MAX_SIZE it would automatically stop.
---------[Sorted Strings]---------
Apple
Banana
Mango
Orange
Watermelon

请将该网站用作一般的计算机科学问答网站,而不是作为一个作业解决网站。不要提供直接的解决方案,而是引导他们找到错误之处。 - Madhusoodan P

1

它应该从0开始获取6个输入,但只获取了5个,为什么?

这个循环

for(i=0;i<5;i++)
    scanf("%s",str[i]);

执行循环,i 的值为 0、1、2、3、4,循环 5 次。
如果需要循环 6 次,请执行:
for(i=0;i<=5;i++)
          ^
          Notice

或者

for(i=0;i<6;i++)
          ^
          Notice

也请注意这一行。
char str[6][10],temp[10];
         ^
         Notice

这样你就可以为6个字符串保留内存。


不是我的程序,而是在https://beginnersbook.com/2015/02/c-program-to-sort-set-of-strings-in-alphabetical-order/找到的程序,当使用for(i=0;i<=count;i++)并输入5作为计数时,它只接受了5个输入。 - anmoloo7
我认为这是因为gets函数,但是gets函数是如何实现只取5个字符的呢? - anmoloo7

0

我有一个我制作的示例:

#include <stdio.h>
#include <string.h>
void main()
{
  char str[100],ch;
  int i,j,l;

       printf("\n\nSort a string array in ascending order :\n");
       printf("--------------------------------------------\n");  
       printf("Input the string : ");
       fgets(str, sizeof str, stdin);
  l=strlen(str);
  /* sorting process */
  for(i=1;i<l;i++)
    for(j=0;j<l-i;j++)
    if(str[j]>str[j+1])
    {
      ch=str[j];
      str[j] = str[j+1];
      str[j+1]=ch;
    }
   printf("After sorting the string appears like : \n");
   printf("%s\n\n",str);
  }

这段代码将对字符数组(一个字符串)进行排序,但问题是要对字符串数组进行排序。 - Barmak Shemirani

0

这不是一个答案,而是对你所引用的代码的一些批评:

#include<stdio.h>
#include<string.h>
int main(){
  int i,j,count;
  char str[25][25],temp[25];
  puts("How many strings u are going to enter?: ");
  scanf("%d",&count);                                        // (1)

  puts("Enter Strings one by one: ");
  for(i=0;i<=count;i++)                                      // (2)
    gets(str[i]);
  for(i=0;i<=count;i++)
    for(j=i+1;j<=count;j++){
      if(strcmp(str[i],str[j])>0){
        strcpy(temp,str[i]);
        strcpy(str[i],str[j]);
        strcpy(str[j],temp);
     }
  }
  printf("Order of Sorted Strings:");                        // (3)
  for(i=0;i<=count;i++)
    puts(str[i]);

  return 0;
}

批评如下:

(1) scanf("%d",&count); 读取一个数字到count中,然后返回。它不会消耗换行符(!)

(2) 这个循环不会打印任何东西,只是读取。但是如果你加上

  for(i=0;i<=count;i++){
    printf("%d:",i);
    gets(str[i]);
  }

相反,你会突然看到它要求输入名字0...5,自动跳过0。这就是换行符被消耗的地方,它读取了一个空字符串。如果你在初始问题中放入5 anmoloo7而不是5,也可以让它出现。

(3) 在打印输出中,名称出现在标题Order of Sorted Strings下面。但是在那个printf中没有换行符。事实上,空字符串比任何其他字符串都“小”,因此它排在列表的最前面,并首先打印出来。如果你在初始数字后附加一个名称的“技巧”,输出将会有所不同,会有6个名称,其中一个直接附加到标题上。

另外还有一件事,你可能也从编译器中得到: gets是一个致命的函数,忘记它的存在并使用其他答案中出现的fgets与stdin一起使用。


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

#define STRING_MAX_WIDTH 255

void sort_strings(char str_arr[][STRING_MAX_WIDTH],int len){
    char temp[STRING_MAX_WIDTH];
    for(int i=0;i<len-1;i++){
        if(strcmp(&str_arr[i][0],&str_arr[i+1][0])>0){
            strcpy(temp, str_arr[i+1]);
            strcpy(str_arr[i+1],str_arr[i]);
            strcpy(str_arr[i],temp);
            sort_strings(str_arr, len);
        }
    
    }
}

int main(){
   char str_arr[][STRING_MAX_WIDTH] = {"Test", "Fine", "Verb", "Ven", "Zoo Keeper", "Annie"};
   int len = sizeof(str_arr)/STRING_MAX_WIDTH;
   sort_strings(str_arr, len);
   for(int i=0;i<len;i++){
        printf("%s\r\n", str_arr[i]);
    }
}

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