Frage zu Zeichenketten und Schleifen



  • Hallo,

    bin in Sachen Programmieren noch ziemlich unerfahren und besuche seit zwei Wochen eine Vorlesung zur Programmierung mit C. In einer Übung sollen wir ein Programm schreiben, mit dessen Hilfe ein Integral mittels Simpson-Regel berechnet werden soll. In der "einfachen" Ausführung, d.h. mit vorgegebener Funktion, habe ich's auch hinbekommen. Nun wollte ich das Programm dahingehend modifizieren, dem User Wahlmöglichkeiten hinsichtlich der Funktion zu geben. Da stoße ich aber auf folgendes Problem: Offenbar wird die Definition von y[i] nicht in die nachfolgende Schleife übernommen. Hat jemand eine Idee, wie man so etwas lösen kann? Vielen Dank im Voraus für die Hilfe!

    /* Programm zur numerischen Integration mithilfe der Simpson-Regel*/
    
    #include <stdio.h>
    #include <math.h>
    
    #define ACC 100
    
    double simpson(double *x, double *y, int n);
    double dx;
    
    int main ()
    
    {
        double x[ACC], y[ACC];
        double xu, xo;
        int n = ACC, i, WAHL;
    
        printf("Bitte Funktion wählen:\n\n");
        printf("(1) f(x) = x\n");
        printf("(2) f(x) = x^2\n");
        printf("(3) f(x) = x^3\n");
        printf("(4) f(x) = sin (x)\n");
        printf("(5) f(x) = cos (x)\n");
    
        scanf("%i", &WAHL);
    
        if (WAHL == 1)
            y[i] = x[i];
    
        else if (WAHL == 2)
             y[i] = x[i] * x[i];
    
        else if (WAHL == 3)
            y[i] = x[i] * x[i] * x[i];
    
        else if (WAHL == 4)
            y[i] = sin(x[i]);
    
        else if (WAHL == 4)
            y[i] = cos(x[i]);
        else
            printf ("\nUngültige Wahl");
    
        printf("Bitte untere Grenze eingeben:\t");
        scanf("%lf", &xu);
    
        printf ("Bitte obere Grenze eingeben:\t");
        scanf("%lf", &xo);
    
        dx = (xo - xu) / (n-1);
    
        for (i = 0; i <= n -1; i = i + 1)
    
        {
    
            x[i] = xu + dx * i;
            y[i]; // Hier stand in der ursprünglichen Fassung die zu integrierende Funktion
        }
    
        printf("Die Fläche beträgt %10.5lf\n", simpson(x, y, n));
    
    }
    
    double simpson(double *x, double *y, int n)
    
    {
        int i=0;
        double A=0;
        for (i = 1; i <= n - 1; i = i + 2)
    
        {
    
            A = A + 4 * y[i];
    
        }
    
        for (i = 2; i <= n -2; i = i + 2)
    
        {
    
            A = A + 2 * y[i];
    
        }
    
        A = (A + y[0] + y[n])* (dx/3.);
    
        return A;
    }
    


  • - Zeile 40 ist falsch
    - globale Variablen sind Müll (dx gehört als Parameter an die Funktion simpson)
    - Zeile 28...43 gehört IN die for-Schleife



  • Du verwendest x in der Simpson Funktion nicht.
    Dein Programm enthält weit mehr Fehler als nur y[i], und es würde nichts bringen jetzt jeden einzelnen zu nennen, dadurch würdest du mit deinen jetzigen Kenntnissen
    nur noch mehr einbauen. Das was du vorhast ist ja anscheinend nicht gefordert also lies erst mal ein Tutorial/Buch.



  • Danke für den Hinweis! Mit den Funktionen in der For-Schleife funktioniert es. Kurze Frage zu den globalen Variablen. Warum sind die Müll? Ich brauche ja das dx sowohl in der main-Funktion als auch in der simpson-Funktion.

    @bitmapper: Hmm, aber in seiner jetzigen Form funktioniert's.

    #include <stdio.h>
    #include <math.h>
    
    #define ACC 100
    
    double simpson(double *x, double *y, int n);
    double dx;
    
    int main ()
    
    {
        double x[ACC], y[ACC];
        double xu, xo;
        int n = ACC, i, WAHL;
    
        printf("Bitte untere Grenze eingeben:\t");
        scanf("%lf", &xu);
    
        printf ("Bitte obere Grenze eingeben:\t");
        scanf("%lf", &xo);
    
        dx = (xo - xu) / (n-1);
    
        printf("\nBitte Funktion wählen:\n\n");
        printf("(1) f(x) = x\n");
        printf("(2) f(x) = x^2\n");
        printf("(3) f(x) = x^3\n");
        printf("(4) f(x) = sin (x)\n");
        printf("(5) f(x) = cos (x)\n\n");
    
        printf("Ihre Eingabe: ");
        scanf("%i", &WAHL);
    
        for (i = 0; i <= n -1; i = i + 1)
    
        {
            x[i] = xu + dx * i;
    
            if (WAHL == 1)
            {
                y[i] = x[i];
            }
    
            else if (WAHL == 2)
            {
                y[i] = x[i] * x[i];
            }
    
            else if (WAHL == 3)
            {
                y[i] = x[i] * x[i] * x[i];
            }
    
            else if (WAHL == 4)
            {
                y[i] = sin(x[i]);
            }
    
            else if (WAHL == 5)
            {
                y[i] = sin(x[i]);
            }
    
            else;
        };
    
        if (WAHL == 1 || WAHL == 2 || WAHL == 3 || WAHL == 4 || WAHL == 5)
            printf("\nDie Fläche beträgt: %10.5lf\n\n", simpson(x, y, n));
    
        else
            printf("\nUngültige Wahl!\n\n");
    
    }
    
    double simpson(double *x, double *y, int n)
    
    {
        int i=0;
        double A=0;
        for (i = 1; i <= n - 1; i = i + 2)
    
        {
    
            A = A + 4 * y[i];
    
        }
    
        for (i = 2; i <= n -2; i = i + 2)
    
        {
    
            A = A + 2 * y[i];
    
        }
    
        A = (A + y[0] + y[n])* (dx/3.);
    
        return A;
    }
    

  • Mod

    christian-kl schrieb:

    Warum sind die Müll?

    Wenn du sie weiter benutzt, wirst du in kürzester Zeit anfangen, sogenannten Spagetticode zu schreiben. Absolut unentwirrbare Programme, bei denen du selber schon während des Programmierens nicht mehr durchblickst. Die dann entsprechend nicht funktionieren und die Fehler sind unauffindbar.

    Du denkst jetzt wahrscheinlich, dass du die große Ausnahme bist und immer schön vorsichtig sein wirst. Denkt jeder. Und jeder, der es trotzdem macht, fällt damit auf die Fresse. Aber da solche Appelle an die Vernunft erfahrungsgemäß nicht ziehen, hier noch das Alternativargument für angehende Hacker: Es ist auch langsamer. Der Compiler wird nämlich die gleichen Schwierigkeiten beim Nachvollziehen des Codes haben und kann daher weniger optimieren.



  • Aber nur weil das erwartete Ergebnis rauskommt, heißt es nicht, dass der Code fehlerfrei ist. Mein compiler bemängelt z.B immer noch das unused x und das:

    else;
    

    Ausserdem fehlt ein return in der main Funktion und äöü werden über die Konsole nicht richtig ausgegeben.
    Dagegen hilft Warnungen ernstnehmen bzw. erstmal einschalten



  • Danke! Habe die Fehler ausgebessert und konnte auch auf die globale Variable verzichten. Habe auch noch zwei weitere Verfahren zur Berechnung des Integrals eingebunden.

    Eine letzte Frage: Die Genauigkeit gebe ich ja derzeit per Präprozessor-Befehl vor. Gibt es eine Möglichkeit, dies auch per Benutzereingabe zu steuern? Immerhin muss dieser Wert ja dann sowohl für die Größe der Zeichenkette als auch für die Definition von n herangezogen werden.

    #include <stdio.h>
    #include <math.h>
    
    #define ACC 100
    
    double simpson(double *x, double *y, int n);
    double trapez(double *x, double *y, int n);
    double rechteck(double *x, double *y, int n);
    
    int main ()
    
    {
        double x[ACC], y[ACC];
        double xu, xo, dx;
        int n = ACC, i, WAHL;
    
        printf("Programm zur numerischen Integration\n");
        printf("\nBitte Funktion waehlen:\n\n");
        printf("(1) f(x) = x\n");
        printf("(2) f(x) = x^2\n");
        printf("(3) f(x) = x^3\n");
        printf("(4) f(x) = sin (x)\n");
        printf("(5) f(x) = cos (x)\n");
        printf("(6) f(x) = exp (x)\n");
        printf("(7) f(x) = log (x)\n\n");
    
        printf("Ihre Eingabe: ");
        scanf("%i", &WAHL);
    
        printf("\nBitte untere Grenze eingeben:\t");
        scanf("%lf", &xu);
    
        printf ("Bitte obere Grenze eingeben:\t");
        scanf("%lf", &xo);
    
        dx = (xo - xu) / (n-1);
    
        for (i = 0; i <= n -1; i = i + 1)
    
        {
            x[i] = xu + dx * i;
    
            if (WAHL == 1)
            {
                y[i] = x[i];
            }
    
            else if (WAHL == 2)
            {
                y[i] = x[i] * x[i];
            }
    
            else if (WAHL == 3)
            {
                y[i] = x[i] * x[i] * x[i];
            }
    
            else if (WAHL == 4)
            {
                y[i] = sin(x[i]);
            }
    
            else if (WAHL == 5)
            {
                y[i] = sin(x[i]);
            }
    
            else if (WAHL == 6)
            {
                y[i] = exp(x[i]);
            }
    
            else if (WAHL == 7)
            {
                y[i] = log(x[i]);
            }
    
        };
    
        if (WAHL == 1 || WAHL == 2 || WAHL == 3 || WAHL == 4 || WAHL == 5 || WAHL == 6 || WAHL == 7)
    
        {
            printf("\nFlaeche nach Simpson-Regel:\t\t%10.5lf\n", simpson(x, y, n));
            printf("Flaeche nach Trapez-Regel:\t\t%10.5lf\n", trapez(x, y, n));
            printf("Flaeche nach Rechteck-Regel:\t%10.5lf\n\n", rechteck(x, y, n));
        }
    
        else
            printf("\nUngültige Wahl!\n\n");
    
        return 0;
    
    }
    
    double simpson(double *x, double *y, int n)
    
    {
        int i=0;
        double A=0;
        for (i = 0; i <= n -2; i = i + 2)
    
        {
    
            A = A + (y[0] / (n-2) + (4. * y[i+1] + 2. * y[i+2] + y[ACC] / (n-2)) * (x[i+1] - x[i]) / 3.);
    
        }
    
        return A;
    }
    
    double trapez(double *x, double *y, int n)
    
    {
        int i=0;
        double B=0;
        for (i = 0; i <= n -2; i++)
    
        {
    
            B = B + ( y[i] + y[i+1])/2. * (x[i+1] - x[i]);
    
        }
    
        return B;
    }
    
    double rechteck(double *x, double *y, int n)
    
    {
        int i=0;
        double C=0;
        for (i = 0; i <= n -2; i++)
    
        {
    
            C = C + y[i] * (x[i+1] - x[i]);
    
        }
    
        return C;
    }
    


  • Ja, mit malloc oder VLA.
    Allerdings ist malloc vorzuziehen.

    if (WAHL == 1 || WAHL == 2 || WAHL == 3 || WAHL == 4 || WAHL == 5 || WAHL == 6 || WAHL == 7)
    

    Das kannst du schreiben als:

    if (WAHL > 0 && WAHL < 8)
    

  • Mod

    Bitmapper schrieb:

    Ja, mit malloc oder VLA.
    Allerdings ist malloc vorzuziehen

    Oder noch besser: Nachdenken, ob man nicht auch ganz ohne dieses Array auskommt.



  • Danke! Hab's jetzt auch zunächst mal so hinbekommen. Inwieweit man auf das Array verzichten kann, ist mir noch nicht so klar. Aber ich hab auch noch ein paar Kapitel im Erlenkötter vor mir. 😉


  • Mod

    christian-kl schrieb:

    Inwieweit man auf das Array verzichten kann, ist mir noch nicht so klar.

    Warum die Werte im Voraus berechnen? Das kann doch die Integrationsfunktion übernehmen.


Log in to reply