Teilstrings sortieren



  • Hallo,

    ich möchte lediglich Teilstrings (ab Zeichen 5 18 Zeichen) sortieren. Welche Änderung muss ich im unten abgebildeten C-Programm vornehmen? Das ist lediglich ein Beispielcode.

    Gruß, Klaus

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    //Vergleichsfunktion für Quicksort und binäre Suche
    //vergleicht Zeichenketten
    int vergleich(const void *a, const void *b)
    {
        const char **kette1 = (const char **)a;
        const char **kette2 = (const char **)b;
    
    //wenn der erste Buchstabe der ersten Kette
    //kleiner ist als der erste der zweiten
    //-1 (kette1 kleiner als kette2)
    if(*(char *)kette1 < *(char *)kette2)
    {
    return -1;
    }
    //wenn der erste Buchstabe der ersten und zweiten
    //Kette gleich sind,
    //müssen die weiteren Buchstaben überprüft werden
    else if(*(char *)kette1 == *(char *)kette2)
    {
    //solange etwas in der Zeichenkette steht, überprüfen
    while(*(char *)kette1)
    {
    //nächstes Zeichen vergleichen
    kette1 ++;
    kette2 ++;
    //wenn das nächste Zeichen der ersten Kette
    //kleiner als nächste der zweiten Kette
    //-1 (kette1 kleiner als kette2
    if(*(char *)kette1 < *(char *)kette2)
    return -1;
    //immer noch gleich, weiter überprüfen
    else if(*(char *)kette1 == *(char *)kette2)
    {
    ;
    }
    //wenn das nächste Zeichen der ersten Kette
    //größer als das nächste der zweiten
    //1 (kette1 größer als kette2
    else
    return 1;
    }
    //alle Buchstaben überprüft und gleich
    //0 (kette1 == kette2)
    return 0;
    }
    //wenn der erste Buchstabe größer als der zweite ist
    //1 (kette1 größer als kette2)
    else
    return 1;
    }
    
    int main()
    {
    //ein Array mit 10 Einträgen
    //die Einträge sind Zeichenketten der Länge 20
    char array[10][20];
    //Zähler
    int i;
    
    //zehn Namen einlesen
    for(i = 0; i<10; i++)
    {
    printf("Gib einen Namen ein: ");
    scanf(" %s", &(array[i]));
    }
    //Liste zum ersten Mal ausgeben
    printf("\nListe vorher: \n");
    for(i = 0; i < 10; i++)
    printf("%i. %s\n", i+1, array[i]);
    
    //Liste sortieren
    qsort(array, 10, sizeof(char)*20, &vergleich);
    
    //Liste zum zweiten Mal ausgeben
    printf("\nListe nachher: \n");
    for(i = 0; i < 10; i++)
    printf("%d. %s\n", i+1, array[i]);
    return 0;
    }
    


  • Der Code ist unlesbar. Da fehlen die Einrückungen.
    Du kommst auch mit deinen * durcheinander.

    Zum Stringvergleich gibt es strcmp() .
    Zum Vergleich von einer begrenzten Anzahl von Zeichen strncmp()

    Wenn du ab dem 5. Zeichen vergleichen willst, musst du noch diesen Offset dazu addieren. Das 1. Zeichen hat den Offset 0.

    Z.B.: strncmp(a+4,b+4,18);



  • Danke Dirk, strncmp(*ia+4,*ib+4,18) habe ich jetzt im Einsatz. Allerdings
    muss ich die Parameter int *laenge_key, int *anfang_key aus extern TEST44
    verwenden. Wie bekomme ich diese Parameter in die vergleich-Funktion, die im qsort übergeben wird?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    //Vergleichsfunktion für Quicksort und binäre Suche
    //vergleicht Zeichenketten
    int vergleich(const void *a, const void *b)
    {
        const char **ia = (const char **)a;
        const char **ib = (const char **)b;
    // hier sollen die Werte von int *laenge_key, int *anfang_key aus extern TEST44 hin (s.u.)
        return strncmp(*ia+4,*ib+4,18);
    } 
    
    extern TEST44(int *anzahl_saetze, int *laenge_key, int *anfang_key, int *laenge_satz, char *beginnadresse_tabelle)
    {
    int i;
    
    //Liste zum ersten Mal ausgeben
    printf("\nListe vorher: \n");
    for(i = 0; i < *(anzahl_saetze); i++)
    	printf("%s\n", *(beginnadresse_tabelle+i));
    
    //Liste sortieren
    qsort(( char * ) beginnadresse_tabelle, *(anzahl_saetze), sizeof(char)**(laenge_satz), &vergleich);
    
    //Liste zum zweiten Mal ausgeben
    printf("\nListe nachher: \n");
    for(i = 0; i < *(anzahl_saetze); i++)
    	printf("%s\n", *(beginnadresse_tabelle+i));
    }
    


  • klaus888 schrieb:

    Wie bekomme ich diese Parameter in die vergleich-Funktion, die im qsort übergeben wird?

    Globale Variablen (sehr schlecht) oder eine eigene Quicksort-Funktion die an vergleich() die Paramter übergibt.

    Warum hast du so viele Zeiger?
    Und was zur Hölle ist das:

    const char **ia = (const char **)a;
        const char **ib = (const char **)b;
    

    ?



  • Hab lange kein C mehr gemacht. Es geht bei uns in der Firma darum, dass aus COBOL die 5 Parameter

    anzahl_saetze (die sortiert werden sollen)
    laenge_key (Sortierbegriff, z.B. 18 Stellen lang)
    anfang_key (Sortierbegriff, z.B. ab 5. Stelle)
    laenge_satz
    *beginnadresse_tabelle als Zeiger (Tabelle kann bis zu 15.000 Elemente haben)

    übergeben werden. Anschließend soll in C eine Sortierung erfolgen und die
    sortierten Elemente wieder an COBOL zurückgegeben werden.

    Die vergleich-Funktion hab ich einfach übernommen (siehe URL unten), keine Ahnung, warum man so viele * braucht, aber der Vergleich läuft.
    http://www.anyexample.com/programming/c/qsort__sorting_array_of_strings__integers_and_structs.xml

    Wie gebe ich eigentlich den sortierten Array wieder an COBOL zurück?

    //Liste zum zweiten Mal ausgeben
    printf("\nListe nachher: \n");
    for(i = 0; i < *(anzahl_saetze); i++)
        printf("%s\n", *(beginnadresse_tabelle+i));
    
    // Rückgabe an COBOL ???
    
    return ???
    }
    


  • klaus888 schrieb:

    Wie gebe ich eigentlich den sortierten Array wieder an COBOL zurück?

    Wie übergibst du denn das Array?

    Arrays werden in C als Referenz übergeben, d.h du arbeitest in den Funktionen an dem Original. Somit brauchst du es nicht zurückgeben.



  • Das Problem der Übergabe von Zusatzparametern bei qsort solltest du erstmal zurückstellen, du scheinst ganz andere Verständnisprobleme zu haben.
    Wie deine COBOL-Seite die Daten liefert und wieder zurückerhält, kann ich dir natürlich nicht sagen, das musst du schon selbst wissen, aber so könnte es prinzipiell gehen:

    #define MEINELAENGE 18
    
    int vergleich(const void *a, const void *b)
    {
      const char *x = *(const char **)a;
      const char *y = *(const char **)b;
      return memcmp(x,y,MEINELAENGE);
    }
    
    /* extern ist ein Schlüsselwort zur Deklaration, du verwendest es bei einer Definition, das ist Unsinn */
    int TEST44(int *anzahl_saetze, int *laenge_key, int *anfang_key, int *laenge_satz, char **tab)
    {
    int i;
    assert( *laenge_key == MEINELAENGE );
    
    printf("\nListe vorher: \n");
    for(i = 0; i < *anzahl_saetze; i++)
      fwrite(tab[i],MEINELAENGE,1,stdout),puts("");
    
    qsort( tab, *anzahl_saetze, *laenge_satz, vergleich);
    
    printf("\nListe nachher: \n");
    for(i = 0; i < *anzahl_saetze; i++)
      fwrite(tab[i],MEINELAENGE,1,stdout),puts("");
    }
    

    Funktioniert auch bei Quasi-Strings ohne '\0' Endekennung.



  • Wenn du nur die beiden Funktionen (Test44 und vergleich) in einem Quelltext hast, kannst du auch mit static Variablen arbeiten.

    static int g_anzahl_key, g_laenge_key;
    
    int vergleich(const void *a, const void *b)
    ... 
      hier kannst du mit g_anzahl_key, g_laenge_key arbeiten
    }
    
    /* extern ist ein Schlüsselwort zur Deklaration, du verwendest es bei einer Definition, das ist Unsinn */
    int TEST44(int *anzahl_saetze, int *laenge_key, int *anfang_key, int *laenge_satz, char **tab)
    {
      g_anzahl_key = *anzahl_saetze;
      g_laenge_key = *laenge_key;
      ...
      qsort(...
      ....
    }
    

    ⚠ Es sind globale Variablen mit all ihren Nebeneffekten ⚠



  • Danke für die wertvollen Tipps. Hat super funktioniert.


Anmelden zum Antworten