简体   繁体   English

在C编程中按字符对字符串排序

[英]sort String by Character in C Programming

I'd like to ask, how to sort some group of string by it's Character. 我想问一下,如何通过“字符”对一组字符串进行排序。 For instance : "Baba", "Cece" , "Caca" , "Zaza" , "Lala" 例如:“ Baba”,“ Cece”,“ Caca”,“ Zaza”,“ Lala”


i'd like to sort it become like this Baba Caca Cece Lala Zaza 我想把它变成这样的Baba Caca Cece Lala Zaza

how to sort those words? 这些单词怎么排序? do we compare it's ASCII Number each word? 我们是否比较每个单词的ASCII码? if it's a number we can just swap it(using insertion sort and so on) do we can also use the same method? 如果它是一个数字,我们可以交换它(使用插入排序等),是否也可以使用相同的方法?

Are you asking how to sort a collection of strings? 您在问如何对字符串集合进行排序吗? Or how to sort the characters within one string? 或如何一个字符串中的字符排序?

Within a single ASCII string, it's dead easy. 在单个ASCII字符串中,这非常简单。 A string is just an array of bytes, so you sort it using any of the same algorithms you'd use to sort an array of integers. 字符串只是字节数组,因此您可以使用与对整数数组进行排序相同的算法对它进行排序。 C's char type is a one-byte integer type that can be compared, added, subtracted, etc. (It can be signed or unsigned: implementation-dependent.) C的char类型是一个一字节的整数类型,可以进行比较,加,减等。(可以带符号或无符号:与实现有关。)

With utf8, a single character can take multiple bytes ( char s) to encode, so sorting the bytes will break things. 使用utf8,单个字符可以占用多个字节( char )进行编码,因此对这些字节进行排序会造成麻烦。

I wrote this trivial in-place selection-sort function for strings for an anagram-dictionary generator many years ago: 多年前,我为字谜字典生成器编写了这个琐碎的就地选择排序函数,用于字符串:

void sort_chars(char *string, int len) // selection sort because words are short
{
   char *end_p, *search, *max_p; // *end_p == last char before '\0'
   char max_val;

   for(end_p = string + len - 1; end_p > string ; end_p--){
      for(search = max_p = string, max_val = *max_p ; search <= end_p ; search++){
         if(*search > max_val){ max_p = search; max_val = *max_p; }
      }
      // max_p now points to largest element, so swap
      *max_p = *end_p;
      *end_p = max_val;
   }

}

All anagrams of a given word have the same characters, and sorted-by-character is a canonical representation of those characters. 给定单词的所有字谜都具有相同的字符,并且按字符排序是这些字符的规范表示。 So you can make an anagram-dictionary storing the sort-by-character representation of every word in /usr/share/dict/words , along with the original word. 因此,您可以制作一个字谜词典,将/usr/share/dict/words中每个单词的按字符排序表示形式与原始单词一起存储。

You could easily modify this function to sort from start to end, and look for a trailing '\\0' (NUL) byte instead of needing an explicit length. 您可以轻松地修改此函数,使其从头到尾进行排序,并寻找尾随的'\\0' (NUL)字节,而不需要显式的长度。

Sorting chars in a String (sorting strings below) 对字符串中的字符进行排序(下面对字符串进行排序)

Following from the comment, you can sort a string the very same way you sort any other type in C. You either use the qsort function provided by the standard library, or you use your own function (eg bubble sort, heap sort, etc..) 从注释开始,您可以使用与在C中对任何其他type进行排序相同的方式对字符串进行排序。您可以使用标准库提供的qsort函数,也可以使用自己的函数(例如冒泡排序,堆排序等)。 )

When using qsort your only task is to write a compare function to pass to the qsort function that tells qsort how to sort your data. 使用qsort您唯一的任务是编写一个compare函数以传递给qsort函数,该函数告诉qsort如何对数据进行排序。 The basic declaration for qsort is: qsort的基本声明是:

void qsort (void *base, size_t nmemb, size_t size,
           int (*compar)(const void *, const void *));

qsort takes 4 arguments: (1) a pointer to the list/array to be sorted, (2) the number of elements to sort, (3) the type size of each element (eg sizeof int ), and (4) lastly a pointer to your compare function. qsort接受4个参数:(1)指向要排序的列表/数组的指针,(2)要排序的元素数,(3)每个元素的类型大小 (例如sizeof int ),以及(4)最后一个a指向您的比较函数的指针。 Note: your compare function takes 2 generic pointers ( void type) as its input. 注意:您的compare函数采用2个通用指针( void类型)作为输入。

For sorting characters, you correctly recognize you will sort by the ascii values. 对于字符排序,您正确地认识到您将按ascii值进行排序。 Therefore, all your compare function needs to do is return whether of the two characters: (a) one is greater than the other, or (b) they are equal. 因此,您的比较功能要做的就是返回两个字符中的一个:(a)一个大于另一个,或者(b)相等。

An example of the compare function here would be: compare功能的示例如下:

int compare_char (const void *a, const void *b) {
    if (*(char *)a != *(char *)b)
        return *(char *)a - *(char *)b;

    return 0;
}

Generally, the only difficult part for new C programers is figuring out how to cast the void type of the arguments to the type you need to compare. 通常,对于新C程序员而言,唯一困难的部分是弄清楚如何将参数的void类型转换需要比较的类型

In the compare function, since you are passed a pointer to type void , you need to cast it to your type before you can dereference it to get the value at the pointer address. compare函数中,由于向您传递了一个指向void类型的指针,因此您需要将其强制转换为您的类型,然后才能取消引用它以获取指针地址处的值。 Here casting the void * to char * is all you need. 您只需要在这里将void *char * Then you need to dereference it with '*' before you making the comparison. 然后,在进行比较之前,需要用'*'对其进行取消引用。 (for a final cast/dereference of eg *(char *)a ). (例如*(char *)a的最终强制转换/取消引用)。 Putting it all together in a short example: 在一个简短的示例中将它们放在一起:

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

#define MAXS 32

/* simple compare function for qsort, returns 
   less than 0 if char 'b' is larger than char 'a',
   a positiver number if 'a' is larger than 'b', and
   zero if they are equal (note: you can return 
   'b' - 'a' to sort in reverse order.)
*/
int compare_char (const void *a, const void *b) {
    if (*(char *)a != *(char *)b)
        return *(char *)a - *(char *)b;

    return 0;
}

int main (void) {

    char word[MAXS]   = {0};
    char sorted[MAXS] = {0};

    printf ("\n Enter a string: ");         /* read word from stdin   */
    if (!scanf ("%31[^\n]%*c", word)) {
        printf ("  [ctrl+d] received\n\n");
        return 1;
    }

    /* copy word to sorted before sort */
    strncpy (sorted, word, sizeof word);

    /* sort the chars in sorted[] */
    qsort (sorted, strlen (word), sizeof *word, compare_char);

    /* print results */
    printf ("\n word   : %s\n sorted : %s\n\n", word, sorted);

    return 0;
}

Compile 编译

$ gcc -Wall -Wextra -Ofast -o bin/str_sort_char str_sort_char.c

Use/Output 使用/输出

$ ./bin/str_sort_char

 Enter a string: aghibw

 word   : aghibw
 sorted : abghiw

Sorting The Array of Strings 对字符串数组进行排序

All the explanation above originally regarding sorting by char 's, also applies to sorting an array of strings. 上面所有有关按char排序的说明,也适用于对字符串数组进行排序。 This also provides a good look at the way you approach using qsort . 这也使您更好地了解使用qsort Above, in the first example, when we approached using qsort , we had to answer the question: "What type am I sorting?" 上面,在第一个示例中,当我们使用qsort ,我们必须回答以下问题: “我要排序哪种type ?” Above we were sorting each char in a null-terminated array of chars (or string ). 在上面,我们按照以null终止的chars (或string数组对每个char进行排序。

How are strings referenced? 如何引用字符串? Through a pointer to the beginning character in the string. 通过指向字符串开头字符的指针。 So here, instead of sorting each char in an array of chars , we will be sorting strings in an array of strings (or properly an array of pointers to type char * ) As far is qsort is concerned, the only difference will be the compare function (and the input...). 因此,在这里,我们将对strings 数组中的字符串 (或适当地char *类型的指针 数组)中的字符串进行排序,而不是对chars数组中的每个char进行排序qsort而言,唯一的区别是compare功能(以及输入...)。 We need to sort strings, so the compare function must provide a way of comparing strings. 我们需要对字符串进行排序,因此compare函数必须提供一种比较字符串的方法。 In C, the standard string comparison function is strcmp (or strncmp to limit the number of characters compared). 在C语言中,标准的字符串比较功能是strcmp (或strncmp以限制比较的字符数)。

For instance, using strcmp to sort an array of strings, you would use something similar to: 例如,使用strcmp对字符串数组进行排序,将使用类似于以下内容的内容:

/* string compare function */
int compare_strings (const void *a, const void *b) {
    return strcmp(*(char **)a, *(char **)b);
}

If you look at the comparison within compare_strings , you are simply returning the result of the strcmp function. 如果查看compare_strings中的比较,您只是在返回strcmp函数的结果。 Basically, changing only the compare function (and the input), you can then use qsort to sort your array of strings, as follows: 基本上,仅更改比较函数(和输入),然后可以使用qsort对字符串数组进行排序,如下所示:

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

/* string compare function */
int compare_strings (const void *a, const void *b) {
    return strcmp(*(char **)a, *(char **)b);
}

int main (void) {

    char *strings[] = {"Baba", "Cece" , "Caca" , "Zaza" , "Lala"};
    size_t i;

    /* sort strings */
    qsort (strings, sizeof strings/sizeof *strings, 
           sizeof *strings, compare_strings);

    /* output sorted arrray of strings */
    for (i = 0; i < sizeof strings/sizeof *strings; i++)
        printf (" strings[%2zu] : %s\n", i, strings[i]);

    return 0;
}

Output 输出量

$ ./bin/qsort_strings_static
 strings[ 0] : Baba
 strings[ 1] : Caca
 strings[ 2] : Cece
 strings[ 3] : Lala
 strings[ 4] : Zaza

you can start off with 2 pointers and a loop,1 pointer pointing at string1 and the other pointing at string2 ,de-reference both and check to see whose character is greater,or if they are equal.and make the swap accordingly.Here is a code that implement this approach.This is a complete function that you can use. 您可以从2个指针和一个循环开始,1个指针指向string1,另一个指针指向string2,两者都取消引用,并检查其字符是否更大或它们是否相等。然后进行相应的交换。实现此方法的代码。这是您可以使用的完整功能。

#include <stdio.h>

int s_bubblesort(int argc,char **argv);


int main(void)
{
    char *str[] = { "zzz","zhz","ydc","acb","zzb","zua","abc","zuaaa","xzz" };

    s_bubblesort(9,str);

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

    char *words[] = {"Baba","Caca" , "Cece","Lala","Babaaaaaa", "L"};

    s_bubblesort(6,words);

    for( int n = 0 ; n < 6 ; n++ )
    {
        printf("%s\n",words[n]);
    }
}

int s_bubblesort(int argc,char **argv)
{
    int i , j = 0;

    char *p_1 , *p_2 , *tmp;

    while( j < argc )
    {
        for( i = 0 ; i < argc - j - 1 ; i++ )
        {
            p_1 = argv[i] , p_2 = argv[i+1];

            while( *p_1 && *p_2 )
            {
                if( *p_1 > *p_2 || ( ! *(p_2 + 1) && ( *p_1 == *p_2 ) ) )
                {
                    tmp = argv[i];

                    argv[i] = argv[i+1];

                    argv[i+1] = tmp;

                    break;
                }
                else if( *p_1 < *p_2 )
                {
                    break;
                }
                p_1++;
                p_2++;
            }
        }
        j++;
    }
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM