在C编程中按字符排序

时间:2015-10-23 03:29:57

标签: c string sorting character

我想问一下,如何通过它的Character来对一些字符串进行排序。 例如:“Baba”,“Cece”,“Caca”,“Zaza”,“Lala”

我想把它变成这样的 巴巴 擦擦 测测 拉拉 扎扎

如何对这些单词进行排序? 我们比较每个单词的ASCII数字吗? 如果它是一个数字我们可以交换它(使用插入排序等) 我们也可以使用相同的方法吗?

3 个答案:

答案 0 :(得分:1)

您是否在询问如何对字符串集合进行排序?或者如何在一个字符串中对字符进行排序?

在一个ASCII字符串中,它很容易。字符串只是一个字节数组,因此您可以使用任何用于对整数数组进行排序的算法对其进行排序。 C的char类型是一个单字节整数类型,可以进行比较,加法,减法等。(它可以是有符号或无符号的:依赖于实现。)

使用utf8,单个字符可以占用多个字节(char s)进行编码,因此对字节进行排序会破坏事物。

多年前,我为anagram-dictionary生成器的字符串写了这个简单的就地选择排序函数:

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;
   }

}

给定单词的所有字谜具有相同的字符,逐字符是这些字符的规范表示。因此,您可以创建一个anagram-dictionary,存储/usr/share/dict/words中每个单词的逐个字符表示形式以及原始单词。

您可以轻松地修改此函数以从头到尾进行排序,并查找尾随'\0'(NUL)字节,而不需要显式长度。

答案 1 :(得分:1)

对字符串中的字符进行排序(对字符串进行排序)

在评论之后,您可以按照与C中任何其他type排序相同的方式对字符串进行排序。您可以使用标准库提供的qsort函数,也可以使用自己的函数功能(例如冒泡排序,堆排序等)。

使用qsort时,您唯一的任务就是编写compare函数以传递给qsort函数,该函数告诉qsort如何对数据进行排序。 qsort的基本声明是:

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

qsort有4个参数:(1)指向要排序的列表/数组的指针,(2)要排序的元素数,(3)类型大小每个元素(例如sizeof int),以及(4)最后一个指向比较函数的指针。注意:您的compare函数需要2个通用指针(void类型)作为输入。

对于字符排序,您可以正确识别出您将按ascii值排序。因此,你所有的比较函数需要做的是返回两个字符中的一个:(a)一个大于另一个,或者(b)它们是相等的。

这里compare函数的一个例子是:

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

    return 0;
}

通常,新C程序员唯一困难的部分是弄清楚如何将参数的void类型转换为您需要的类型进行比较。

compare函数中,由于您传递了指向void类型的指针,因此您需要将其强制转换为类型,然后才能取消引用它以获取值在指针地址。在这里,只需将void *转换为char *即可。然后,在进行比较之前,需要使用'*'取消引用它。 (例如*(char *)a的最终演员/解除引用)。简单介绍一下:

#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;
}

<强>编译

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

使用/输出

$ ./bin/str_sort_char

 Enter a string: aghibw

 word   : aghibw
 sorted : abghiw

排序字符串数组

上面关于按char排序的所有解释,也适用于排序字符串数组。这也可以很好地了解您使用qsort的方法。上面,在第一个示例中,当我们使用qsort接近时,我们必须回答以下问题:&#34;我在排序type是什么?&#34; 以上我们在一个以空值终止的字符数组(或char)中对每个string进行排序。

如何引用字符串?通过指向字符串中起始字符的指针。所以在这里,我们不是在字符数组中对每个char进行排序,而是在字符串数组中对strings 进行排序(或正确< em>一个指向char * 类型的指针数组。就qsort而言,唯一的区别是compare函数(和输入...)。我们需要对字符串进行排序,因此compare函数必须提供一种比较字符串的方法。在C中,标准字符串比较函数是strcmp(或strncmp来限制比较的字符数)。

例如,使用strcmp对字符串数组进行排序,您可以使用类似的内容:

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

如果您查看compare_strings中的比较,您只需返回strcmp函数的结果。基本上,只更改比较函数(和输入),然后可以使用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;
}

<强>输出

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

答案 2 :(得分:0)

你可以从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;
}