Aufgaben Problem, warum falsch?



  • Hallo, ich muss mich leider mit der Sprache C beschäftigen, obwohl ich eigentlich immer mit Turbo Pascal gearbeitet habe. Ich habe auf alle fälle folgenden Quelltext geschrieben, aber irgendwie werden die funktionen nicht ausgeführt. Wo liegt der fehler und wie behebe ich ihn?

    Hier der Quelltext:

    #include <stdlib.h>
    #include <stdio.h>
    
    double a,b,c,x_min,x_max,x_b,us,y_c,g_flaeche;
    
    double y_wert  () {
    
        double x_a,y_a,y_b;
    
        x_a=x_b;
        x_b=x_b+us;
        y_a=a*(x_a*x_a)+b*x_a+c;
        y_b=a*(x_b*x_b)+b*x_b+c;    
        y_c=(y_a+y_b)/2;
    
    }
    
    double flaeche () {
    
        double z_flaeche;
    
        z_flaeche=y_c*us;
        g_flaeche=g_flaeche+z_flaeche;
    
    }
    void main(void) {
    
        double zaehler,u;
    
        zaehler=0;
        x_b=0;
    
        printf ("Geben Sie fuer die Funktion y=ax*x+bx+c die Werte a, b, und c ein. So wie die Anzahl der nummerischen Intervalle und den X Start und Endwert.\n");
        scanf ("%f%f%f%f%f%f",&a,&b,&c,&u,&x_min,&x_max);
        x_b=x_min;
        us=(x_max-x_min)/u;
    
        do
            {zaehler=zaehler+1;
            y_wert;
            flaeche;}
        while (zaehler=u);
    
        printf ("n Flaeche = %f", g_flaeche);
    
    }
    


  • y_wert und flaeche
    sind nicht pointercrash()- kompatibel, weil die Klammern fehlen. Mal so dahinschwadroniert. 😉
    Zudem ist Dein Code reichlich unschön, kipp' ihn weg und behalte im Hinterkopf: It's not the language, it's the brain that's insane 😃

    Edit: Nee, war so nich klar genug?



  • Und die return Werte der Funktionen fehlen auch....



  • Du solltest immer auch posten, was denn genau nicht funktioniert bzw. welche Fehlermeldung du bekommst. In dem Fall wirst du das Programm ja nicht einmal kompilieren können, da deine Funktionen, wie bereits erwähnt, mit einem Rückgabe-Wert definiert sind (z.B. Funktion double y_wert), den du aber nicht per return-Anweisung zurückgibst. Meine Schulerfahrung mit Turbo-Pascal ist zwar schon eine ganze Weile her, aber ich bin sicher, das ist da auch nicht erlaubt.

    Übrigens...

    ...kannst du einer Variable bei der Definition auch direkt einen Wert zuweisen (double zaehler=0).

    ...brauchst du x_b nicht 0 zuzuweisen, wenn du 3 Zeilen weiter sowieso einen anderen Wert zuweist.

    ...ist der Vergleichsoperator in C das doppelte Gleichheitszeichen! Ein Vergleich musst du also "zaehler**==**u" notieren, nicht "zaehler=u". Letzteres ist eine Zuweisung, was bei dir als Schleifenbedingung besonders böse ist.

    ...solltest du sicherstellen, dass u!=0 ist, um eine Division durch 0 zu vermeiden.

    ...ist es unsinnig, in deiner do-while-Schleife Zeilen wie "y_wert;" und "flaeche;" zu notieren. Das ist zwar syntaktisch erlaubt (wenn mich nicht alles täuscht), hat aber absolut keine Auswirkungen.

    EDIT: Ach ja, und arbeite an deiner Textformatierung. Die geschweiften Klammern sind Bestandteil dieser Sprache und verdienen entsprechende Aufmerksamkeit, auch wenn ein Pascaller das vielleicht nicht wahrhaben will. 😉



  • NeoMay schrieb:

    Und die return Werte der Funktionen fehlen auch....

    Naja, er hat ja fast alles global definiert, kann man ja im Prinzip auch machen, ist aber so häßlich wie gefährlich. Ich war gestern etwas schnodderig, etwas konstruktiver nochmal:

    Bitte die globalen Variablen umschichten, wohin sie gehören: Als lokale Deklarationen in die Unterfunktion bzw. als Parameter in den Funktionsheader.
    Also

    double y_wert(double us, double y_c ...
    

    Zähler bitte nicht als double anlegen, damit können Vergleiche unerwartet fehlschlagen. Zudem führen Inkrementoperatoren

    int zaehler;
    // ...
    zaehler++;
    

    meist zu schnellerem Code.

    Wenn Du wirklich double brauchst, bitte entsprechend initialisieren, also z.B.

    x_b = 0.0;
    

    Ich weiß, die meisten Compiler erledigen das immanent, aber sauberer ist das so.

    Im Übrigen nimm' Dir einfach zu Herzen, was _matze gepostet hat. 😉



  • Vielen dank für eure Hilfe. Ich werde nachher mal versuchen alles umzusetzen und mich dann nochmal melden ob es funktioniert.



  • _matze schrieb:

    In dem Fall wirst du das Programm ja nicht einmal kompilieren können, da deine Funktionen, wie bereits erwähnt, mit einem Rückgabe-Wert definiert sind (z.B. Funktion double y_wert), den du aber nicht per return-Anweisung zurückgibst. Meine Schulerfahrung mit Turbo-Pascal ist zwar schon eine ganze Weile her, aber ich bin sicher, das ist da auch nicht erlaubt.

    Das war der Unterschied zwischen Procedure und Function. Procedures sind quasi void- functions in C und für Funktionen legt Pascal intern ein Symbol (mit dem Funktionsnamen) an, in das Du einen Rückgabewert schreiben kannst ... oder auch nicht. Hat mW bestenfalls zur Warning geführt, wenn man undefinierte Werte zurückgab.
    Umgekehrt kann man zwar einer Procedure keinen Rückgabewert aufdrängen, aber Functions müssen nicht zwangsweise einen Return Value bekommen.
    Daher stammt wohl auch die Unsitte, Procedures auf Referenzen von globalen Variablen werkeln zu lassen. Das geht am Schnellsten bei kleinen Progrämmchen und führt geradewegs in den Abgrund, wenn's komplexer wird. 😃



  • pointercrash() schrieb:

    _matze schrieb:

    In dem Fall wirst du das Programm ja nicht einmal kompilieren können, da deine Funktionen, wie bereits erwähnt, mit einem Rückgabe-Wert definiert sind (z.B. Funktion double y_wert), den du aber nicht per return-Anweisung zurückgibst. Meine Schulerfahrung mit Turbo-Pascal ist zwar schon eine ganze Weile her, aber ich bin sicher, das ist da auch nicht erlaubt.

    Das war der Unterschied zwischen Procedure und Function. Procedures sind quasi void- functions in C und für Funktionen legt Pascal intern ein Symbol (mit dem Funktionsnamen) an, in das Du einen Rückgabewert schreiben kannst ... oder auch nicht. Hat mW bestenfalls zur Warning geführt, wenn man undefinierte Werte zurückgab.
    Umgekehrt kann man zwar einer Procedure keinen Rückgabewert aufdrängen, aber Functions müssen nicht zwangsweise einen Return Value bekommen.
    Daher stammt wohl auch die Unsitte, Procedures auf Referenzen von globalen Variablen werkeln zu lassen. Das geht am Schnellsten bei kleinen Progrämmchen und führt geradewegs in den Abgrund, wenn's komplexer wird. 😃

    Ja, das Konzept ist mir bekannt. Ein wenig Pascal-Luft habe ich früher ja auch mal geschnuppert, und diese Unterteilung gab's ja auch in BASIC (Subs und Functions) und auch in alten Clipper-Versionen. Dass ene Funktion nicht unbedingt einen Wert zurückgeben muss, ist auch klar. In Verbindung mit einer im Programm vorhandenen Zuweisung ist das aber übel. Ich könnte mir vorstellen, dass in einem solchen Fall vielleicht ein Standardwert (z.B. 0 bei numerischen Typen) zurückgegeben wird, oder?



  • _matze schrieb:

    ... Dass eine Funktion nicht unbedingt einen Wert zurückgeben muss, ist auch klar. In Verbindung mit einer im Programm vorhandenen Zuweisung ist das aber übel. Ich könnte mir vorstellen, dass in einem solchen Fall vielleicht ein Standardwert (z.B. 0 bei numerischen Typen) zurückgegeben wird, oder?

    Huh, unser Pascal- Kurs war damals an einem VAX- Terminal und da wurde halt zurückgegeben, was drin war, keine Warning. Also Speicher wurde bei Funktionsaufruf reserviert und bei Funktionsende auf den Returnstack geschmissen, egal, was da drinstand. An Warnings kann ich mich erinnern so um TP6 / Delphi 1.0 herum, aber nur trübe.
    Ich hab' wohl auch schon länger nichts mehr auf der Schiene gemacht ... 🙂



  • So ich hab das jetzt mal verändert um zu testen ob überhaupt das funktioniert was ich will. Jetzt ist meine Frage wie kann ich die beiden Stellen die ich im Quelltext makiert habe in eine Funktion auslagern, so dass es auch funktioniert. Irgendwie hab ich nämlich noch nicht verstanden wie man das macht mit dem Wert zurückgeben.

    #include <stdlib.h>
    #include <stdio.h>
    
    void main(void) 
    {
            double a,b,c,x_min,x_max,x_b,us,y_c,g_flaeche,z_flaeche,u,x_a,y_b,y_a;    
            int zaehler;
            int abfrage;
        	anfang:
    
        	printf ("Geben Sie fuer die Funktion y=ax*x+bx+c die Werte a, b, und c ein. So wie die Anzahl der nummerischen Intervalle und den X Start und Endwert.\n");
        	scanf ("%f%f%f%f%f%f",&a,&b,&c,&u,&x_min,&x_max);
        	x_b=x_min;
        	us=(x_max-x_min)/u;
    
        	do
            {
    		zaehler++;
    
            	x_a=x_b;
        	        x_b=x_b+us;
                    y_a=a*(x_a*x_a)+b*x_a+c;
        	        y_b=a*(x_b*x_b)+b*x_b+c;    
        	        y_c=(y_a+y_b)/2;
    
                    z_flaeche=y_c*us;
        	        g_flaeche=g_flaeche+z_flaeche;
    
    		}
    
        	while (zaehler==u);
    
        	printf ("n Flaeche = %f", g_flaeche );
    
            printf ("Moechten sie noch eine Berechnung durchfuehren? 1 fuer ja und 2 fuer nein. \n");
            scanf ("%f", &abfrage);
    
            if (abfrage==1) goto anfang;
    }
    

    das soll in die funktion y_wert ausgelagert werden

    x_a=x_b;
        	        x_b=x_b+us;
                    y_a=a*(x_a*x_a)+b*x_a+c;
        	        y_b=a*(x_b*x_b)+b*x_b+c;    
        	        y_c=(y_a+y_b)/2;
    

    und das in die funktion flaeche

    z_flaeche=y_c*us;
        	        g_flaeche=g_flaeche+z_flaeche;
    


  • Der Ansatz von oben war schon gar nicht so schlecht, Du hast nur einen klassischen Fehler eines Pascaluebersiedlers gemacht:

    y_wert;
    flaeche;
    

    Das sind in C keine Funktionsaufrufe. Auch wenn Du keine Parameter uebergeben willst, brauchst Du mindestens Klammern:

    double y= y_wert();
    


  • Auf Anhieb fällt mir auf, daß Du "zaehler" nicht initialisiert hast, also

    int zaehler = 0;
    

    Und statte Deine Funktionen doch mit Parametern aus, damit Du keine globalen Abhängigkeiten bekommst. Weiter so 👍 🙂


Anmelden zum Antworten