2015-10-23 45 views
0

我想問一下,如何通過它的字符對一些字符串組進行排序。 例如:「巴巴」,「測測」,「擦擦」,「扎扎」,「拉拉」在C編程中按字符排序字符串


我想對它進行排序變成這個樣子 巴巴 擦擦 測測 拉拉 扎扎

如何排序這些單詞? 我們比較它的ASCII碼每個單詞嗎? 如果它是一個數字我們可以交換它(使用插入排序等) 我們也可以使用相同的方法嗎?

+0

每個字符('char')的值在0-127之間(基本ASCII值),並且可以相應地排序。一般來說,像'qsort'這樣簡單的排序路由可以毫不費力地使用。對於短字符串,您可以使用幾乎任何您選擇的排序例程,但效率不會受到太大損失,但對於較長的字符串(1000個字符),快速排序,堆排序或與mergesort的組合提供最佳性能。 (請參閱[** Ascii表值**](http://www.asciitable.com/) –

+0

[如何按字母順序對字符串數組進行排序(區分大小寫,非標準排序規則)](http:// stackoverflow .com/questions/12646734/how-to-sort-an-array-of-string-alphabetically-case-sensitive-nonstandard-colla) – dietbacon

+0

@dietbacon:我想另一個問題是這個問題的一個更復雜的版本,但這個問題基本上是「以最基本的方式幫助我使用'qsort'」 – ShadowRanger

回答

1

你問如何排序字符串的集合?或者如何在之內排列字符一個字符串?

在單個ASCII字符串中,它很容易。一個字符串只是一個字節數組,所以你可以使用任何你用來對整數數組進行排序的相同算法對它進行排序。 C的char類型是可以進行比較,增加,減少等的單字節整數類型(它可以是有符號或無符號:取決於實現)。 s)進行編碼,因此對字節進行排序將會破壞事物。

多年前我寫了這個平凡的就地選擇排序功能字符串字謎詞典發生器:

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字典,用於存儲/usr/share/dict/words中每個單詞的字符表示以及原始單詞。

您可以輕鬆修改此函數以從頭到尾進行排序,並查找尾隨的'\0'(NUL)字節,而不需要明確的長度。

+0

我在問如何對字符串集合進行排序 –

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接近時,我們必須回答這個問題:「我在排序什麼type?」以上我們將每個char排序在一個以空字符結尾的字符數組(或string)中。

如何引用字符串?通過指向字符串中開始字符的指針。所以在這裏,而不是在陣列字符的排序各char,我們將在一個字符串數組排序strings(或正確指針數組鍵入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 
+0

在你的'compare_char'函數中,你可以返回'* a - * b'。如果它們相等,那麼它將爲零,所以特殊外殼只會讓編譯器更難以優化'if'。 –

+0

Peter,我不確定我是否理解你在說什麼?不能僅僅返回'* a - * b'而不需要引用'void'。我知道你是s aying'return *(char *)a - *(char *)b;'可以簡單地''返回* a - * b;'? –

+0

不,你仍然需要演員,但是你可以鬆開'if'。 (你可以編寫這個函數來獲取'const char *'參數,然後強制轉換函數指針,但這並不是我以前說過的。)int compare_char(const void * a,const void * b){return *(char *)a - *(char *)b; }'在所有情況下應該返回與您的版本相同的值。 –

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