Berechnung Länge einer Kettenlinie m Punkte n Dimensionen



  • hallo,

    ich soll ein Programm schreiben, das die Länge einer Kettenlinie mit m Punkten und n Dimensionen berechnet. m und n werden eingegeben, die Speicherverwaltung der Struktur soll dynamisch sein.

    Mein Programm stürzt aber leider immer wieder ab, ich schätze, ich mache was mit der Speicherverwaltung falsch. hat einer von euch eine idee?

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    double *ptr;
    
    struct point { //Struktur point mit dynamischer Anzahl von double-Werten
        double* ptr;
    };
    
    struct point *p; //dynamische Anzahl an Punkten p aus struct point
    
    double abstand (struct point* p , int n, int m) {
        double d [m-1]; //array zum Speichern der jeweiligen Abstände zwischen je             zwei Punkten
        double D = 0, summe = 0; //D = späteres Ergebnis, Quadratwurzel aus der Summe des obigen arrays
        int abst = 0, dim = 0, j = 0;
    
        for (;abst < m-1; abst++) { //solange abst kleiner als die Anzahl der Abstände
            for (dim = 0; dim < n; dim++) {
               summe = summe + (p[abst+1].ptr [dim] - p[abst].ptr [dim]) *  (p[abst+1].ptr [dim] - p[abst].ptr [dim]);
           } //wird der Hilfsvariable summe der Wert der alten Summe + der Differenz  des Quadrates der derzeitigen Koordinate zweier Punkte zugewiesen
        d [abst] = summe; //abschließend wird diese summe in einem array-Element    gespeichert und 0 gesetzt
        summe = 0;
       }
    
       for (j = 0; j < m-1; j++) {
          D = D + d[j]; //solange noch ein Abstand vorhanden, werden diese alle aufaddiert
       }
    
       D = sqrt (D); //abschließend wird die Quadratwurzel daraus gezogen
    
       return D; //und das Ergebnis zurückgegeben
    }
    
    int main () {
    
        int n = 0, m = 0, i = 0, k=0;
        char c = 'j';
    
        printf ("Berechnung Laenge D einer Kettenlinie zwischen m Punkten im n- dimensionalen Raum\n\n");
    
       while (c== 'j') {
    
          printf ("n = ");
          fflush (stdin);
          scanf ("%d", &n); //Einlesen der Dimension
    
          ptr = (double*) malloc (n*(sizeof(double))); //Reservieren Speicherplatz für die n Dimensionen
    
         printf ("m = ");
         fflush (stdin);
         scanf ("%d", &m); //Einlesen Anzahl Punkte
    
         p = (struct point*) malloc (m * (sizeof(struct point))); //Reservieren des   Speicherplatzes für die m Punkte
    
         for (; k<m; k++) { //solange k kleiner ist als die Anzahl der Punkte
            printf ("p%d", k); //Wird dem punkt p k
            printf ("\n");
            for (i=0; i < n; i++) { // solange i kleiner als die Dimension ist
                printf ("%d. Koordinate: ", i+1); //jeweilige Koordinate
                fflush (stdin);
                scanf ("%lf", &p[k].ptr[i]); //der Koordinate i des Punktes k wird ein Wert zugewiesen
                printf ("\n");
            }
    
          }
        k = 0; //Rücksetzen von k
    
        printf ("Abstand: %lf", abstand (p, n, m)); //Berechung Abstand zwischen den  Punkten in abstand
        printf ("\n\n");
        free (ptr); //Freigabe Speicherplatz
        free (p);
    
        printf ("\n\nNochmal? (j/n)");
        fflush (stdin);
        scanf ("%c", &c);
        }
    
    }
    


  • Bitte editier dein Post nochmal und setze den Code in Code-Tags:
    Code markieren und auf den C-Button unter dem 😡 klicken.

    Im Augenblick ist das unlesbar. 😞



  • Sorry, habs grad auch selber erst gesehen und ist schon verbessert 🙂



  • Hey, das ging ja schnell.
    Sogar vor meinem Mecker-Post 👍
    Dann können wir mal schauen.



  • Vermutung:
    Du willst m structs haben. Jeder Pointer in den structs sollen auf n double Variablen zeigen.
    Dann hast du m*n double Variablen

    Im Augenblick hast du m structs und einmal ein Bereich mit n double (ptr).

    Dieses ptr ist aber noch nicht einmal mit irgendeiner struct verknüpft.

    Hast du noch mehr vor, oder warum hast du eine struct?
    Und beseitige mal die globalen Variablen. Die brauchst du nicht.



  • das ganze ist eine übung zum thema strukturen, deshalb verwende ich struct.

    Deine Vermutung ist richtig, ich brauche sozusagen m Punkte mit jeweils n double-Koordinaten!



  • Das Thema fragt nach einem Algorithmus für eine konkrete Rechenaufgabe und gehört meiner Meinung nach woanders hin.



  • Dann musst du erst den Bereich für die m struct besorgen.
    Und dann in der Schleife für jede struct nochmal n double.
    Und diesen Bereich musst du dann auch dem ptr in der struct zuweisen.

    Eigentlich mach man sowas mit Doppelzeigern.

    Bisschen Merkwürdig für eine struct-Übung. 😕
    Üblicher ist da sowas ähnliches wie eine Datenbank.



  • schos22 schrieb:

    hallo,
    ...
    Mein Programm stürzt aber leider immer wieder ab, ich schätze, ich mache was mit der Speicherverwaltung falsch. ...

    Hi

    Ja, das machst du.
    In der Zeile 48 reservierst du Speicher, davon bekommt aber der Strukturmember (Zeile 😎 nichts mit.



  • So funktioniert es jetzt, was haltet ihr von der Lösung? Bitte bezogen auf meine Aufgabenstellung, ich soll ja eine Struktur verwenden.

    Vielen Dank schon mal für Eure Hilfe!

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    
    struct point {
        double*ptr;
    };
    
    double abstand (struct point* p , int n, int m) {
        double d [m-1]; //array zum Speichern der jeweiligen Abstände zwischen je zwei Punkten
        double D = 0, summe = 0; //D = späteres Ergebnis, Quadratwurzel aus der Summe des obigen arrays
        int abst = 0, dim = 0, j = 0;
    
        for (;abst < m-1; abst++) { //solange abst kleiner als die Anzahl der Abstände
            for (dim = 0; dim < n; dim++) {
                summe = summe + (p[abst+1].ptr [dim] - p[abst].ptr [dim]) * (p[abst+1].ptr [dim] - p[abst].ptr [dim]);
            } //wird der Hilfsvariable summe der Wert der alten Summe + der Differenz des Quadrates der derzeitigen Koordinate zweier Punkte zugewiesen
            d [abst] = summe; //abschließend wird diese summe in einem array-Element gespeichert und 0 gesetzt
            summe = 0;
        }
    
        for (j = 0; j < m-1; j++) {
            D = D + d[j]; //solange noch ein Abstand vorhanden, werden diese alle aufaddiert
        }
    
        D = sqrt (D); //abschließend wird die Quadratwurzel daraus gezogen
    
        return D; //und das Ergebnis zurückgegeben
    }
    
    int main () {
    
        int n = 0, m = 0, i = 0, k=0;
        char c = 'j';
        struct point *p;
    
        printf ("Berechnung Laenge D einer Kettenlinie zwischen m Punkten im n-dimensionalen Raum\n\n");
    
        while (c== 'j') {
    
            printf ("n = ");
            fflush (stdin);
            scanf ("%d", &n); //Einlesen der Dimension
    
            printf ("m = ");
            fflush (stdin);
            scanf ("%d", &m); //Einlesen Anzahl Punkte
    
            p = (struct point*) malloc (m*(sizeof(struct point)));
    
            for (; k<m; k++) { //solange k kleiner ist als die Anzahl der Punkte
                p[k].ptr = (double*) malloc (n*(sizeof(double)));
                printf ("p%d", k); //Wird dem punkt p k
                printf  ("\n");
                for (i=0; i < n; i++) { // solange i kleiner als die Dimension ist
                    printf ("%d. Koordinate: ", i+1); //jeweilige Koordinate
                    fflush (stdin);
                    scanf ("%lf", &p[k].ptr[i]); //der Koordinate i des Punktes k wird ein Wert zugewiesen
                    printf ("\n");
                }
    
            }
            k = 0;
            printf ("Abstand: %lf", abstand (p, n, m)); //Berechung Abstand zwischen den Punkten in abstand
            printf ("\n\n");
            //Freigabe Speicherplatz
            for (; k<m; k++) {
                free (p[k].ptr);
            }
            free (p);
            k=0;
    
            printf ("\n\nNochmal? (j/n)");
            fflush (stdin);
            scanf ("%c", &c);
        }
    
    }
    


  • + lesbarkeit

    - c99 code, unterstützen die wenigsten compiler
    - fflush (stdin), kein Standard, funktioniert nicht überall
    - unnötige casts im code
    - bei fehlerhafter eingabe per scanf programmabsturz
    - rückgabewerte von sscanf, malloc werden nicht ausgewertet und behandelt -> potentielle fehlerquelle



  • - Member/Variablen mit den Namen "ptr", "d", "D" etc. sind nicht selbsterklärend
    - Ich glaube "abst" würde man intuitiv als "Abstand" lesen, dabei ist hier der Index der gerade betrachteten Punkte gemeint.
    - sqrt(a+b) != sqrt(a)+sqrt(b)
    - Dass du das 2D-Feld über einzelne Allozierungen zusammensetzt halte ich für suboptimal. Du hast n+1 Allozierungen bei n Punkten. Allozierungen sind zeitaufwändig, außerdem besteht die chance, dass die Koordinaten im Speicher weiter "auseinander" zu liegen kommen, so dass der Prozessorcache aus dem Tritt kommt. Zudem füllt das Feld mit den Zeigern auch Teile des Caches. Ich halte es für angebrachter, die Punkte in einem großen Feld mit n*m Elementen vorzuhalten.



  • 1. Leider hängt mein Kompiler schon an Zeile 11 mit der dynamischen Array-Deklaration wie in Pascal. Welcher Kompiler wird eigentlich benutzt?

    2. Ist dieses Array, wenn es denn funktioniert, eigentlich notwendig. Später werden doch nur die Elemente aufsummiert. Das kann man doch gleich in der Schleife von 15-18 machen. Damit entfällt auch meine erste Frage.

    3. Ungewöhnlich ist die Trennung der Initialisierung von Schleifenvariablen und der eigentlichen for-Schleife und mit großem Abstand. Hat das einen tiefen Grund?

    k=0;
    for (;k<...
    

    statt

    for (k=0;k<...
    

Anmelden zum Antworten