Sortieren eines Adressbereichs (qsort)



  • Hallo,

    ein Adressbereich soll aus einem COBOL-Programm durch Aufruf eines C-Programms sortiert werden.

    Leider kommt momentan die folgende Fehlermeldung:

    Execution error : file 'XXX'
    error code: 114, pc=0, call=1, seg=0
    114 Attempt to access item beyond bounds of memory (Signal 11)

    Kann mir jmd. das C-Programm verbessern? Beim qsort ist ein Fehler (entweder beim Aufruf oder in der Sortierfunktion vergleich). Wie kann man Adressbereiche mit qsort sortieren?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int g_laenge_key, g_anfang_key; 
    
    // 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;
        return strncmp(*ia+g_anfang_key,*ib+g_anfang_key,g_laenge_key);
    } 
    
    extern void TEST44
    (
    int *anzahl_saetze, 			// Anzahl Sätze
    int *laenge_key, 			// Länge Sortierbegriff
    int *anfang_key, 			// Beginn Sortierbegriff
    int *laenge_satz, 			// Länge Satz
    char *beginnadresse_tabelle		// Beginnadresse Tabelle
    )
    
    {
    int i;
    g_laenge_key = *laenge_key; 
    g_anfang_key = *anfang_key; 
    
    /*
    // Liste zum ersten Mal ausgeben
    printf("\nListe vorher: \n");
    for(i = 0; i < *5; i++)
    	printf("%p\n", *(beginnadresse_tabelle+i));
    */
    
    // Liste sortieren
    qsort(( char * ) beginnadresse_tabelle, *(anzahl_saetze), sizeof(*laenge_satz), vergleich); 
    
    /*
    // Liste zum zweiten Mal ausgeben
    printf("\nListe nachher: \n");
    for(i = 0; i < *5; i++)
    	printf("%p\n", *(beginnadresse_tabelle+i));
    */
    }
    


  • wie sieht deine tabelle aus? du brauchst ein array.



  • Wie ist denn deine Tabelle im Speicher aufgebaut?
    Erst ein key, dann der Datensatz usw. oder nur keys, die jeweils einen Zeiger auf den Datensatz darstellen?
    Sind die Daten C-Strings ( '\0' terminiert )?



  • Kann man aus COBOL überhaupt Funktionen aus C aufrufen und wie sehen da Funktionsaufrufe aus? Diese müssen schon der C-Konvention genügen!



  • berniebutt schrieb:

    Kann man aus COBOL überhaupt Funktionen aus C aufrufen und wie sehen da Funktionsaufrufe aus? Diese müssen schon der C-Konvention genügen!

    Déjà-vu, es hat schon mal geklappt: Teilstrings sortieren



  • sizeof(*laenge_satz)?!

    Wie sehen die übergebenen Parameter denn in COBOL-Picturing aus?



  • Die übergebenen Parameter in COBOL-Picturing:

    V-TEST44-ANZAHL-TAB            PIC S9(8) BINARY SYNC.  
    V-TEST44-LG-KEY            PIC S9(8) BINARY SYNC.  
    V-TEST44-ANFANG-KEY            PIC S9(8) BINARY SYNC.  
    V-TEST44-LG-SATZ            PIC S9(8) BINARY SYNC.  
    DRNR-SC-ST-1 PIC X(1)
    

    Und der Aufruf des C-Programms in COBOL:

    068800 W99-CALL-TEST44 SECTION.                                         SE41 400
    069800 W9900.                                                           SE41 400
                DISPLAY 'X41E - DRNR-01 vorher:' DRNR1-SATZ (1)
                DISPLAY 'X41E - DRNR-02 vorher:' DRNR1-SATZ (2)
                SET DRNR1-LG-VAR-WERT TO TRUE .
    132700     MOVE DRNR1-ZL-VAR-MAX TO      V-TEST44-ANZAHL-TAB      
               MOVE 18 TO                   V-TEST44-LG-KEY 
               MOVE 5 TO             V-TEST44-ANFANG-KEY  
               MOVE DRNR1-LG-VAR TO  V-TEST44-LG-SATZ 
    488600     CALL 'TEST44'       USING    
    132700                        V-TEST44-ANZAHL-TAB      
                                  V-TEST44-LG-KEY 
                                  V-TEST44-ANFANG-KEY  
                                  V-TEST44-LG-SATZ 
    488700                        DRNR-SC-ST-1 (1)  .
                DISPLAY 'X41E - DRNR-01 nachher:' DRNR1-SATZ (1)
                DISPLAY 'X41E - DRNR-02 nachher:' DRNR1-SATZ (2).
    070100 W9999.                                                           SE41 400
    070200     EXIT.                                                        SE41 400
    

    Die Tabelle sieht wie folgt aus (Ausschnitt):

    DRNR PM -NA FQ-NR AANR ATAA ATEL KTAN FORM SORT MM ABW MM-POSE LOGO DRUCKART POSE-SAM-FRIST KOPIEN DURCHSCHRIFT PPAT
    0135 #0135 00 0224 0 0 ## 0135 04 000 0 0 0 00 00 0 0
    0139 #0139 00 0601 0 5 0139 02 000 0 0 0 00 00 0 0
    0139 #0139 00 0603 6 5 0139 02 000 0 0 0 00 00 0 0
    0146 #0146 00 0820 1 1 0146 03 000 0 0 0 00 00 0 0
    0146 #0146 00 0810 0 1 0146 15 000 0 0 0 00 00 0 0
    0146 #0146 00 0820 0 1 0146 15 000 0 0 0 00 00 0 0
    0205 #0205 00 0601 0 3 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0601 0 4 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0601 0 5 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 0 3 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 0 4 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 0 5 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 2 3 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 2 4 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 2 5 0205 16 000 0 0 0 00 00 0 0
    0205 #0205 00 0603 6 3 0205 16 000 0 0 0 00 00 0 0

    In der Tabelle ist dann ab Stelle 5, 18 Stellen lang zu sortieren und das
    mit max. 15.000 Elementen. Weiß jmd., welche Änderung im qsort zu machen sind bzw. in der Funktion vergleich?



  • #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int g_laenge_key, g_laenge_satz;
    
    // Vergleichsfunktion für Quicksort und binäre Suche
    // vergleicht Zeichenketten
    int vergleich(const void *a, const void *b)
    {
        const char *x = a;
        const char *y = b;
        return memcmp(x+g_laenge_key,y+g_laenge_key,g_laenge_satz);
    }
    
    /* das extern ist hier falsch, sollte export oder was passendes aus dem Compilerangebot sein */
    extern void TEST44
    (
    int *anzahl_saetze,             // Anzahl Sätze
    int *laenge_key,             // Länge Sortierbegriff
    int *anfang_key,             // Beginn Sortierbegriff
    int *laenge_satz,             // Länge Satz
    char *beginnadresse_tabelle        // Beginnadresse Tabelle
    )
    
    {
    int i;
    g_laenge_key = *laenge_key;
    g_laenge_satz = *laenge_satz;
    
    // Liste zum ersten Mal ausgeben
    printf("\nListe vorher: \n");
    for(i = 0; i < anzahl_saetze; i++)
        fwrite(beginnadresse_tabelle+i*(g_laenge_key+g_laenge_satz)+g_laenge_key,g_laenge_satz,1,stdout),puts("");
    
    // Liste sortieren
    qsort(beginnadresse_tabelle, *anzahl_saetze,g_laenge_key+g_laenge_satz, vergleich);
    
    // Liste zum zweiten Mal ausgeben
    printf("\nListe nachher: \n");
    for(i = 0; i < anzahl_saetze; i++)
        fwrite(beginnadresse_tabelle+i*(g_laenge_key+g_laenge_satz)+g_laenge_key,g_laenge_satz,1,stdout),puts("");
    }
    

    Geht davon aus, dass jedes "Tabellen"-Element genau g_laenge_key+g_laenge_satz Zeichen/Bytes lang ist und dass nach genau g_laenge_satz Zeichen/Bytes "aufsteigend" sortiert wird. (in deinem Kommentar steht aber, dass nach key sortiert wird?!)
    Versuche erstmal, die Testausgaben richtig hinzubekommen, das qsort kann dann später kommen.



  • Danke Wutz.

    Zu deiner Frage: Ja, es wird nach Key sortiert. laenge_satz beinhaltet den
    kompletten Satz. Ab Stelle 5 (anfang_key) werden dann die 18 nachfolgenden Stellen (laenge_key) sortiert. Bsp.: 0135#013500022400## 013504000000000000
    => sortiert werden soll nach #013500022400

    Das mit dem extern für den externen Aufruf von C-Programmen ist korrekt.

    Evtl. Problem: anzahl_saetze ist variabel (max. 15.000). Klappt die Sortierung evtl. deshalb nicht?

    Mein aktuelles Programm sieht jetzt so aus:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static int g_laenge_key, g_anfang_key;
    static int g_laenge_satz;
    
    // 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;
        return memcmp(ia+g_anfang_key,ib+g_anfang_key,g_laenge_key);
    } 
    
    extern void TEST44
    (
    int *anzahl_saetze, 			// Anzahl Sätze
    int *laenge_key, 			// Länge Sortierbegriff
    int *anfang_key, 			// Beginn Sortierbegriff
    int *laenge_satz, 			// Länge Satz
    char *beginnadresse_tabelle
    )
    
    {
    int i;
    g_laenge_key = *laenge_key; 
    g_anfang_key = *anfang_key; 
    g_laenge_satz = *laenge_satz;
    
    printf("\nAnzahl Sätze: %d\n", *anzahl_saetze);
    printf("\nLänge Sortierbegriff: %d\n", *laenge_key);
    printf("\nBeginn Sortierbegriff: %d\n", *anfang_key);
    printf("\nLänge Satz: %d\n", *laenge_satz);
    
    printf("\nTest_15_40\n");
    
    // Liste zum ersten Mal ausgeben 
    printf("\nListe vorher: \n"); 
    for(i = 0; i < 5; i++) 
    	fwrite(beginnadresse_tabelle+i*(g_laenge_satz),g_laenge_satz,1,stdout),puts("");
    
    // Liste sortieren
    qsort(beginnadresse_tabelle, *(anzahl_saetze), sizeof(*laenge_satz), vergleich);
    
    // Liste zum zweiten Mal ausgeben 
    printf("\nListe nachher: \n"); 
    for(i = 0; i < 5; i++) 
    	fwrite(beginnadresse_tabelle+i*(g_laenge_satz),g_laenge_satz,1,stdout),puts("");
    }
    

    Ausgabe ist allerdings:

    X41E - DRNR-01 vorher:0135#013500022400## 013504000000000000
    X41E - DRNR-02 vorher:0139#013900060105## 013902000000000000

    Anzahl Sätze: 15000

    Länge Sortierbegriff: 18

    Beginn Sortierbegriff: 5

    Länge Satz: 67

    Test_15_40

    Liste vorher:
    0135#013500022400## 013504000000000000
    0139#013900060105## 013902000000000000
    0139#013900060365## 013902000000000000
    0146#014600081001## 014615000000000000
    0146#014600082001## 014615000000000000

    Liste nachher:
    00

    0

    X41E - DRNR-01 nachher:00
    X41E - DRNR-02 nachher:



  • Nein, extern ist hier nicht richtig.
    Du hast nicht verstanden, was extern ist. extern mit einer Definition verbunden wie bei dir ist Unsinn und JW-Pfusch Niveau.
    Auch den qsort Aufruf hast du geändert, dann brauchst du dich nicht zu wundern, wenn es nicht läuft.
    Gehe davon aus, dass qsort fehlerfrei implementiert ist, auch 15000 Sätze sind neben dem Zeitfaktor kein Problem.



  • sorry wutz, du hast natürlich recht. Bin halt noch nicht bei 1.500 Forenbeiträgen 😃 Nachdem ich den qsort Aufruf und die vergleich-Funktion exakt so umgesetzt habe (wie in deinem Beitrag) funktioniert die Sortierung 3. Parameter abgeändert und (const char 😉 in der vergleich-Funktion weggelassen. Und auch das mit dem extern (nur zu verwenden bei einer Deklaration) stimmt. Meine Vorlage war falsch 🙂


Anmelden zum Antworten