String-Array alphabetisch sortieren?!



  • Falls du es doch selber machen musst:
    Eine (1) temp-Variable reicht. Das muss kein Array sein.

    Für den Vergleich schreibst du eine Funktion. Nimm dir ein Beispiel an strcmp (Oder nimm es gleich)

    Dann ist dein Vergleich statt (bib[n+1].Name[0] <= bib[n].Name[0]) nur (strcmp(bib[n+1].Name[0], bib[n].Name[0]) < 0)
    Kann auch > 0 sein, musst du mal drüber nachdenken

    Wenn du mehrere Elemente der struct vergleichen willst, musst du deine Funktion erweitern. Aber benutze in dieser dann strcmp



  • Ich weiß, dass Bubblesort Mist ist.
    Das passiert eben, wenn man vielleicht den falschen Dozenten hat?!

    Ich hab es jetzt mit einem qsort-Code umgesetzt.
    Es funktioniert soweit bei dem Beispiel. Ich versuche es jetzt mal bei meinem komplexeren Beispiel anzuwenden.

    //
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #pragma pack(1)
    #define PUFFER 50
    
    struct Satz {
        char Name[PUFFER];}__attribute__ ((packed));
    
    int compare( void const * lhs, void const * rhs )
    {
        struct Satz * left  = ((struct Satz *) lhs);
        struct Satz * right = ((struct Satz *) rhs);
    
        int result = strcmp( left->Name, right->Name );
        if( result )
            return result;
    
        return 0;
    }
    
    int main(int argc, const char * argv[]){
    
         struct Satz bib[6];
    
        int elemente=5, i=0;
    
        strcpy(bib[1].Name, "TU Chemnitz");
        strcpy(bib[2].Name, "TU Berlin");
        strcpy(bib[3].Name, "TU Bern");
        strcpy(bib[4].Name, "Akademie Gera");
        strcpy(bib[5].Name, "Uni Leipzig");
    
        printf("Unsortiert:\n");
        i=1;
        while(i<6){
            printf("Eintrag Nr: %d\n", i);
            printf("Besteller: %s\n",bib[i].Name);
            printf("\n");
            i++;
        }
    
     qsort( bib, elemente, sizeof( struct Satz ), compare );
    
        printf("Sortiert:\n");
        i=1;
        while(i<6){
            printf("Eintrag Nr: %d\n", i);
            printf("Besteller: %s\n",bib[i].Name);
            printf("\n");
            i++;
        }
    
            return(0);
        }
    


  • qsort greift auf bib[0] zu, welches undefinierten Inhalt besitzt; deshalb ist dein Programm Müll.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define PUFFER 50
    
    struct Satz {
      char Name[PUFFER];
    };
    
    int main(){
    
      struct Satz bib[5];
    
      int i;
    
      strcpy(bib[0].Name, "TU Chemnitz");
      strcpy(bib[1].Name, "TU Berlin");
      strcpy(bib[2].Name, "TU Bern");
      strcpy(bib[3].Name, "Akademie Gera");
      strcpy(bib[4].Name, "Uni Leipzig");
    
      qsort(bib, sizeof bib / sizeof*bib, sizeof*bib, strcmp);
    
      i = 0;
      while (i<5){
        printf("Eintrag Nr: %d\n", i);
        printf("Besteller: %s\n", bib[i].Name);
        printf("\n");
        i++;
      }
    
      return 0;
    }
    

    http://ideone.com/9jMxPg



  • Funktioniert so einwandfrei. Davor gab es aber auch eine korrekte Ausgabe?
    Egal.

    Danke schon mal!

    Wenn ich aber mehr, als nur die Variable Namen habe?!
    Zum Beispiel steht jetzt in der Struktur noch Vorname.



  • Bemme90 schrieb:

    Wenn ich aber mehr, als nur die Variable Namen habe?!
    Zum Beispiel steht jetzt in der Struktur noch Vorname.

    DirkB schrieb:

    Wenn du mehrere Elemente der struct vergleichen willst, musst du deine Funktion erweitern. Aber benutze in dieser dann strcmp

    Du musst, wenn beim erste Vergleich Gleichheit festgestellt wurde, einen zweiten machen.

    int result = strcmp( left->Name, right->Name );
         if( result )
            return result;
    // hier landest du bei Gleichheit
          result = strcmp( left->VorName, right->VorName );
    
          return result;
    }
    


  • Eine Sache hätte ich noch.

    Kann ich die Bezeichnung der Struktur irgendwie übergeben?

    Ich habe jetzt folgendes:

    int compare( void const * lhs, void const * rhs)
    {
        struct Satz * left  = ((struct Satz *) lhs);
        struct Satz * right = ((struct Satz *) rhs);
    
        int result = strcmp( left->Name, right->Name);
        if(result)
            return result;
    
        return 0;
    }
    

    Je nach Auswahl des Users startet eine eigene qsort.
    Mittlerweile 4 Stück.

    Ich hätte aber gerne nur eine qsort. Beim Aufruf soll die Bezeichnung der Struktur übergeben werden. Abhängig davon, ob der User den Vornamen, Nachnamen oder das Alter sortiert haben möchte.



  • Das geht standardkonform erst mit C11 und

    __STDC_WANT_LIB_EXT1__
    errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,int (*compar)(const void *x, const void *y,void *context),void *context);
    


  • Sieht das kompliziert aus.

    Ich hab keine Ahnung, aus welchen Bestandteilen deine Code-Zeile besteht.
    Auch nicht, an welcher Stelle etwas übergeben wird?!

    So sieht es jetzt bei mir aus:

    Main:

    qsort(temp, ElementeTemp, sizeof*temp, compareBesteler);
    

    Funktion:

    int compareBesteller( void const * lhs, void const * rhs)
    {
        struct Satz * left  = ((struct Satz *) lhs);
        struct Satz * right = ((struct Satz *) rhs);
    
        int result = strcmp( left->Besteller, right->Besteller);
        if(result)
            return result;
    
        return 0;
    }
    

    Anstatt "Besteller" soll es meine Variable drinstehen


  • Mod

    Wutz schrieb:

    Das geht standardkonform erst mit C11

    Auf welche Neuerung beziehst du dich?

    Bemme90 schrieb:

    Sieht das kompliziert aus.

    Ich hab keine Ahnung, aus welchen Bestandteilen deine Code-Zeile besteht.
    Auch nicht, an welcher Stelle etwas übergeben wird?!

    Das ist die Signatur einer Funktion aus der Bibliothek des Microsoft C-Compilers. Das ist fast die gleiche Signatur wie beim normalen qsort, aber die Vergleichsfunktion erlaubt die Übergabe eines weiteren Datenzeigers (der Kontext). Und die qsort_s-Funktion erlaubt die Übergabe eben dieses Zeigers, den sie dann an die Vergleichsfunktion übergeben wird.
    Diesen Zeiger könnte man beispielsweise auf einen Wert zeigen lassen, der das Offset des gewünschten Datenfeldes im struct angibt. Die Vergleichsfunktion arbeitet dann nicht mehr mit einem festen Member des structs, sondern mit struct + Offset.

    Solch ein Feature könnte man auch nachbauen, indem man den Kontext global macht. Ist aber nicht sehr schick.



  • Mit VisualStudio 2013 sieht ein Beispiel zu qsort mit zusätzlichem Parameter z.B. so aus:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #ifndef _MSC_VER
    #error nur mit MSVC
    #endif
    
    enum { NAME, VORNAME, ORT };
    typedef struct {
      char name[80], vorname[80], ort[80];
    } Person;
    
    int cmp(void*c, const void*a, const void*b)
    {
      const Person *x = a, *y = b;
      switch ((int)c){
      case NAME:    return strcmp(x->name, y->name);
      case VORNAME: return strcmp(x->vorname, y->vorname);
      case ORT:     return strcmp(x->ort, y->ort);
      }
    }
    
    int main()
    {
      Person person [] = { { "schmidt", "hugo", "berlin" }, { "meyer", "egon", "rom" }, { "lehmann", "werner", "paris" } };
      qsort_s(person, 3, sizeof *person, cmp, NAME);
      for (int i = 0; i < 3; ++i) printf("%s\t%s\t%s\n", person[i].name, person[i].vorname, person[i].ort);
      qsort_s(person, 3, sizeof *person, cmp, VORNAME);
      for (int i = 0; i < 3; ++i) printf("%s\t%s\t%s\n", person[i].name, person[i].vorname, person[i].ort);
      qsort_s(person, 3, sizeof(Person), cmp, ORT);
      for (int i = 0; i < 3; ++i) printf("%s\t%s\t%s\n", person[i].name, person[i].vorname, person[i].ort);
      return 0;
    }
    

    Die Ausgabe entsprechend:

    lehmann werner  paris
    meyer   egon    rom
    schmidt hugo    berlin
    meyer   egon    rom
    schmidt hugo    berlin
    lehmann werner  paris
    schmidt hugo    berlin
    lehmann werner  paris
    meyer   egon    rom
    

    Unsinnigerweise haben die MS-Leute die Parameter der compare-Funktion vertauscht ggü. dem C11 Standard, auch wieder Sutter-Müll.
    Aber immherhin haben sie überhaupt was im Angebot, die gcc-Leute lassen sich wieder mal lange bitten, selbst in 4.8.1 habe ich diese C11-Funktion nicht finden können.


Anmelden zum Antworten