2017-06-18 3 views
1

C Sprache: Ich möchte fragen, wie man eine Zeichenfolge alphabetisch mit Großbuchstaben vor äquivalenten Kleinbuchstaben sortiert. Beispiel: Eingang: baBadxD Ausgang: aaBbDdxSortierfolge alphabetisch mit Großbuchstaben vor Kleinbuchstaben in C

+1

Ich schlage vor, mit [ 'qsort'] (https://msdn.microsoft.com/en-us/library/zes7xw0h.aspx). –

+1

like [this] (http://ideone.com/QEgiN0) – BLUEPIXY

+0

Gibt es eine Möglichkeit, dass die Zeichenfolge etwas anderes als das Alphabet enthält? – BLUEPIXY

Antwort

1

können Sie die qsort Funktion mit einer entsprechenden Vergleichsfunktion verwenden. Eine solche Funktion muss sorgfältig erstellt werden, um eine transitive Ordnungsfunktion zu implementieren. Eine gemeinsame Anstrengung von Vlad, Jonathan und ich führen auf diese einfache und portable Implementierung:

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

int cmpletters(const void *p1, const void *p2) { 
    unsigned char c1, c2, u1, u2; 
    c1 = *(const unsigned char *)p1; 
    c2 = *(const unsigned char *)p2; 
    if (c1 == c2) 
     return 0; 
    u1 = toupper(c1); 
    u2 = toupper(c2); 
    if (u1 != u2) 
     return (u1 > u2) ? 1 : -1; 
    return isupper(c1) ? -1 : 1; 
} 

int main(void) { 
    char buf[] = "baBadxD"; 

    printf("before: %s\n", buf); 
    qsort(buf, strlen(buf), 1, cmpletters); 
    printf("sorted: %s\n", buf); 
    return 0; 
} 

Beachten Sie, dass dieser Algorithmus kann auch mit einer Verweistabelle implementiert werden, es sei denn, der Typ char sehr groß ist.

+0

Das scheint wie eine komplizierte Vergleichsfunktion. –

+0

@ JonathanLeffler: Ja, Vlad hat einen einfacheren geschrieben. Der einzige Vorteil von diesem ist, alle Buchstaben vor allen anderen Symbolen zu gruppieren.Aber selbst dafür ist es zu kompliziert. – chqrlie

+0

@ JonathanLeffler: Ich habe deine Funktion vereinfacht und es funktioniert ohne die Annahme "A" <'a''. – chqrlie

0

Erforderlich ist, die Vergleichsfunktion sorgfältig zu schreiben und die C-Standard-Sortierfunktion qsort zu verwenden, die in der Kopfzeile <stdlib.h> deklariert ist.

Hier ist ein Demonstrationsprogramm.

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

int cmp_char(const void *lhs, const void *rhs) 
{ 
    unsigned char c1 = *(const unsigned char *)lhs; 
    unsigned char c2 = *(const unsigned char *)rhs; 

    if (c1 == c2) 
    { 
     return 0; 
    } 
    else if ((toupper(c1) < toupper(c2)) || 
     (toupper(c1) == toupper(c2) && isupper(c1) && islower(c2))) 
    { 
     return -1; 
    } 
    else 
    { 
     return 1; 
    } 
} 

int main(void) 
{ 
    char s[] = "baBadxD"; 

    puts(s); 

    qsort(s, strlen(s), sizeof(char), cmp_char); 

    puts(s); 
} 

Die Programmausgabe ist

baBadxD 
aaBbDdx 
+0

Schön und einfach! Ich würde das optionale 'return 0;' am Ende von 'main()' für die vollständige Portabilität hinzufügen. upvoted. – chqrlie

3

Die notwendige Vergleichsfunktion ist nicht sehr komplex. Sie können den Charakter konvertieren und vergleichen. Wenn sie ungleich sind, verwenden Sie das (x > y) - (x < y) Idiom für die case-konvertierten Werte, um den Wert zurückzugeben. Wenn sie gleich sind, verwenden Sie das gleiche Idiom, um die nicht konvertierten Zeichen zu vergleichen.

Der Code geht davon aus, dass Großbuchstaben im Kleinbuchstabensatz vor Kleinbuchstaben stehen. Es verwendet eine Assertion, um sicherzustellen, dass - es könnte ein static_assert() sein, um einen Kompilierungsfehler zu erzeugen, anstatt ein Laufzeitfehler zu sein. Wenn Sie sich um akzentuierte Zeichen kümmern müssen, benötigen Sie komplexere Vergleiche, um sicherzustellen, dass áàäâå usw. zusammen gruppiert sind.

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

static int comparator(const void *v1, const void *v2) 
{ 
    unsigned char c1 = *(unsigned char *)v1; 
    unsigned char c2 = *(unsigned char *)v2; 
    unsigned char u1 = toupper(c1); 
    unsigned char u2 = toupper(c2); 
    if (u1 != u2) 
     return (u1 > u2) - (u1 < u2); 
    return (c1 > c2) - (c1 < c2); 
} 

int main(void) 
{ 
    assert('A' < 'a'); 
    char sample[] = "baBadxD"; 

    printf("Unsorted [%s]\n", sample); 
    qsort(sample, strlen(sample), sizeof(char), comparator); 
    printf("Sorted [%s]\n", sample); 

    char buffer[4096]; 
    while (fgets(buffer, sizeof(buffer), stdin) != 0) 
    { 
     buffer[strcspn(buffer, "\n")] = '\0'; 
     printf("Unsorted [%s]\n", buffer); 
     qsort(buffer, strlen(buffer), sizeof(char), comparator); 
     printf("Sorted [%s]\n", buffer); 
    } 
    return 0; 
} 

Der Testcode sortiert die Datenprobe in der Frage gegeben, und dann weitere Zeilen von Daten liest und sortiert jede von denen. Bei einem zufälligen Textgenerator, einige Beispielausgabe ist:

Unsorted [baBadxD] 
Sorted [aaBbDdx] 
Unsorted [PvpxixCDvgnkLHQLlBvsJzgQLDmBxUeIhyUMvDiVpjCYvOshnaEvupb] 
Sorted [aBBbCCDDDEeggHhhIiiJjkLLLlMmnnOPpppQQssUUuVvvvvvvxxxYyz] 
Unsorted [rvnsnRcQGUGDyydxrvIhYkQemsqfNtafIZlVQqHvDxkLnxdQouwBrv] 
Sorted [aBcDDddeffGGHhIIkkLlmNnnnoQQQQqqRrrrsstUuVvvvvwxxxYyyZ] 
Unsorted [XZPIDAxazwWQZhxuCVotQPzTHsCQULaEiSPLAQUlnqrBiz] 
Sorted [AAaaBCCDEHhIiiLLlnoPPPQQQQqrSsTtUUuVWwXxxZZzzz] 
Unsorted [NoAsbAzTWivuxSHjBKnGeDxgmWdwNESTZmZauGvmdchoGjMAAEufcZneoWWWN] 
Sorted [AAAAaBbccDddEEeefGGGgHhijjKMmmmNNNnnoooSSsTTuuuvvWWWWWwxxZZZz] 
Unsorted [zcmMqAkXYXrmObgDsloVxVLfmXclNGBmDfrtVEcgHVZlRaycjbnYbSQkS] 
Sorted [AaBbbbccccDDEffGggHjkkLlllMmmmmNnOoQqRrrSSstVVVVXXXxYYyZz] 
Unsorted [DHvDBHSsTgAjBaZGCXniiBqzSNkNqgeKStXzDDswSfCcJnJJSAKsmhz] 
Sorted [AAaBBBCCcDDDDefGggHHhiiJJJjKKkmNNnnqqSSSSSsssTtvwXXZzzz] 
Unsorted [MGKtMuBlwdXTjysBPDhHntdGvsjRPOWlGvKTCTs] 
Sorted [BBCDddGGGHhjjKKllMMnOPPRsssTTTttuvvWwXy] 
Unsorted [ChNiqW] 
Sorted [ChiNqW] 
+0

In der Tat viel einfacher, aber nimmt "A" <"a" und Buchstaben sind in alphabetischer Reihenfolge in den Zeichensatz. Einen weniger Test damit: 'if (u1! = U2) zurück (u1> u2)? 1: -1; ' – chqrlie

+0

Ich denke, alle bisher gezeigten Komparatoren gehen davon aus, dass das' A' vor anderen Buchstaben sortiert ist. Ich habe festgestellt, dass akzentuierte Zeichen für diesen Code ein Problem darstellen. Ja, der Code kann vereinfacht werden, wie Sie es vorschlagen. –

+0

ASCII und die ISO-Latin-X-Zeichensätze folgen dieser Regel ("A" <'a'') aber MacRoman nicht für einige Akzentzeichen und EBCDIC nicht einmal für normale römische Zeichen. – chqrlie

Verwandte Themen