Strukturen in Unterfunktionen Rechen



  • Also ich hab nen mir unerklärliches Problem in nem Unterprogramm.
    Das UP erhält 2 Strukturen die jeweils 2 double ints enthalten.
    Nun sollen die beiden Int addiert werden und zurückgegeben werden.
    Und soll anschliend ein ergebnis zurückgeben

    Mal ein Teil des Quelltextes:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "komplex.h"
    
    void eingabe (struct komplex);
    void ausgabe (struct komplex/*,char */);
    struct komplex add (struct komplex,struct komplex);
    
    void eingabe (struct komplex *k_zahl)
    	 {	 
    		 printf("Eingabe Realteil:\n");
    		 scanf("%d",&k_zahl->real);
    		 printf("Eingabe Imaginaerteil:\n");
             scanf("%d",&k_zahl->imag);
    
    }
    
    struct komplex add (struct komplex wert1, struct komplex wert2)
    {
        struct komplex erg;
        erg.real =  wert2.real + wert1.real;   
        erg.imag =  wert1.imag + wert2.imag;  
    
        return (erg);
    }
    
    void ausgabe (struct komplex *erg_rech,char rechop[20])
    {
    	printf("Ergebnis aus %s lautet\n",rechop);
    	printf("%d\n",&erg_rech->real);
    	printf("%d\n",&erg_rech->imag);
    }
    
    void main()
    {
        struct komplex *ptr_zahl1;
        struct komplex *ptr_zahl2;
        struct komplex *ptr_ergzahl;
        struct komplex k_zahl1;
        struct komplex k_zahl2;
        struct komplex ergzahl;
    
    	ptr_zahl1=(komplex*)malloc(sizeof(struct komplex));
        ptr_zahl2=(komplex*)malloc(sizeof(struct komplex));
        ptr_ergzahl=(komplex*)malloc(sizeof(struct komplex));
    
    	char operation[20];
    	int auswahl;
            ptr_zahl1 = &k_zahl1;
    	ptr_zahl2 = &k_zahl2;
    	ptr_ergzahl= &ergzahl;
    	eingabe(ptr_zahl1);	
    	eingabe(ptr_zahl2);
    
    	ergzahl=add(k_zahl1,k_zahl2);
    
    	}
    

    komplex-header:

    struct komplex
    {
    	double real;  /* realteil */
    	double imag;  /* imaginaerteil */
    };
    

    Problem ist die Addition wird nicht korrekt ausgeführt im Unterprogramm (add) nur warum?
    die ankommenden werte sind laut test korrekt nur wird die addtion nicht korrekt durchgeführt, sprich in erg. real und erg.imag steht nicht die summe der addition.
    Bin grad echt ratlos...

    ach ja



  • Was steht denn sonst in ergzahl? (eventuell solltest du mal das Programm im Debugger betrachten - oder wenigstens die eingegebenen Werte kontrollieren)

    Btw, double-Werte liest du als %lf ein bzw. gibst du als %f aus - %d steht für dezimale (int-)Werte.

    (und von den Speicherlecks will ich hier gar nicht reden)



  • es steht lustigerweise nicht die addition der beiden werte, sondern genau die hälfte also:

    ich willl erg = x + y und schreib das auch und der wert enthält erg = (x+y)/2
    obwohl ich das erste hingeschrieben habe...

    edit:
    Siehst du da hab ich gepennt habs glatt für nen int mit doppelter genauigkeit gehalten.

    eben alles durch lf und f ersetzt und sieh da der bug ist behoben.



  • Dragonslayer schrieb:

    eben alles durch lf und f ersetzt und sieh da der bug ist behoben.

    Da bleibt immer noch das Speicherleck deines Programms:

    ptr_zahl1=(komplex*)malloc(sizeof(struct komplex));
    ...
    ptr_zahl2 = &k_zahl2;
    

    Nach der letzten Anweisung hast du jeden Zugriff auf den von malloc() gelieferten Speicherbereich verloren (in "kleinen" Programmen nicht weiter dramatisch, aber auf die Dauer müllst du dir damit den Heap zu).

    Die drei ptr_... Variablen benötigst du hier überhaupt nicht, also kannst du sie auch ganz weglassen.



  • Naja die ptr Variablen brauch ich doch oder ?
    Weil ich darf an den Prototypen der Unterprogramme nichts ändern.

    Mit Speicherlecks meints du das freigeben des reservierten Speichers durch den "free(variable)" Befehl?
    Das hab ich mittlerweile soweit eingebautt.

    Ich habe jetzt nur noch einen merkwürdigen Bug und zwar das die Ausgabe 2 mal aufgerufen wird bei allen 4 Rechenoperationen:

    Hier mal das soweit Fertige Programm:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "komplex.h" // Header für Globale Struct Komplex Struktur
    
    void eingabe (struct komplex);
    void ausgabe (struct komplex,char[15]);
    struct komplex add (struct komplex,struct komplex);          
    void sub (struct komplex, struct komplex,struct komplex);
    struct komplex mul (struct komplex,struct komplex);           
    struct komplex div (struct komplex,struct komplex);           
    
    void eingabe (struct komplex *k_zahl)
    {		 
        printf("Eingabe Realteil:\n");
    	scanf("%lf",&k_zahl->real);
    	printf("Eingabe Imaginaerteil:\n");
        scanf("%lf",&k_zahl->imag);     
    }
    
    void ausgabe (struct komplex *erg_rech,char rechop[15])
    {
    	printf("Ergebnis aus %s lautet\n",rechop);
    	printf("%f\n",erg_rech->real);
    	printf("%fj\n",erg_rech->imag);
    }
    
    struct komplex add (struct komplex wert1, struct komplex wert2)
    {
    	struct komplex erg;
    	erg.real = 	wert2.real + wert1.real;   	  
    	erg.imag =  wert1.imag + wert2.imag; 
    	return (erg);
    }
    
    void sub (struct komplex wert1, struct komplex wert2,struct komplex *erg)  
    {
    
    	erg->real =  (wert1.real - wert2.real);   	  
    	erg->imag =  (wert1.imag - wert2.imag); 
    
    }
    
    struct komplex mul (struct komplex wert1, struct komplex wert2)
    {
    	struct komplex erg;
    
    	erg.real = (wert1.real * wert2.real);
    	erg.real = erg.real - (wert1.imag * wert2.imag);
    	erg.imag = (wert1.real * wert2.imag);
    	erg.imag = erg.imag + (wert1.imag * wert2.real);
    
        return(erg);
    }
    
    struct komplex div (struct komplex wert1, struct komplex wert2)
    {
        struct komplex erg;
    	double nenner;
    
        erg.real= (wert1.real * wert2.real) ;
    	erg.real= erg.real + (wert1.imag * wert2.imag);      //Zähler berechnung
    	erg.imag= (-wert1.real * wert2.imag);
    	erg.imag= erg.imag +(wert1.imag * wert2.real);      //Zähler berechnung
    
    	nenner= (wert2.real * wert2.real)+(wert2.imag * wert2.imag); //Nenner berechnung
    
    	erg.real= erg.real / nenner;    //Endergebniss
    	erg.imag= erg.imag / nenner;    //Endergebniss
    
        return(erg);
    }
    
    void main()
    {
        struct komplex *ptr_zahl1;  //Deklaration von Pointern und entsprechenden Strukturen
        struct komplex *ptr_zahl2;
        struct komplex *ptr_ergzahl;
    	struct komplex k_zahl1;
        struct komplex k_zahl2;
    	struct komplex ergzahl;
    
    	ptr_zahl1=(komplex*)malloc(sizeof(struct komplex)); 
        ptr_zahl2=(komplex*)malloc(sizeof(struct komplex));
        ptr_ergzahl=(komplex*)malloc(sizeof(struct komplex));
    
    	char operation[15];
    	int auswahl;
        ptr_zahl1 = &k_zahl1;
    	ptr_zahl2 = &k_zahl2;
    	ptr_ergzahl= &ergzahl;
    
    	do
    	{
    	    printf("Rechenoperation waehlen:\n");
    	    printf("1 = Addition\n2 = Subtraktion\n3 = Multiplikation\n4 = Division\n");
    	    scanf("%i",&auswahl);
    	    if(auswahl > 4 || auswahl < 1)
    		{
    		    printf("Wertebereich ueberschritten!\nErneute Eingabe taetigen!\n\n");
    		}
    	}while (auswahl > 4 || auswahl <1);
    
        eingabe(ptr_zahl1);	
    	eingabe(ptr_zahl2);
    
        switch(auswahl)
    	{
    	case 1:		   
    
    	      ergzahl=add(k_zahl1,k_zahl2);
    		  strcpy(operation,"Addition");
    		  ausgabe(ptr_ergzahl,operation);        
    		  break;
    
        case 2:
    		  sub(k_zahl1,k_zahl2,ptr_ergzahl);
              strcpy(operation,"Subtraktion");
              ausgabe(ptr_ergzahl,operation);
    		  break;
    
    	case 3:
    		  ergzahl= mul(k_zahl1,k_zahl2);
              strcpy(operation,"Multiplikation");
    		  ausgabe(ptr_ergzahl,operation);
    		  break;
    
    	case 4:
    		  ergzahl= div(k_zahl1,k_zahl2);
    		  strcpy(operation,"Division");
    		  ausgabe(ptr_ergzahl,operation);
              break;
    
        free(ptr_zahl1);
        free(ptr_zahl2);
    	free(ptr_ergzahl);
    	}
    

    Ich hab mich echt dumm und dämlich gesucht warum die Ausgabe doppelt auf dem Bildchirm erscheint.
    Achja und das die Sub Funktion andere Parameter hat ist beabsichtigt.



  • Glaub mir ruhig, du brauchst die Pointer-Variablen nicht - du kannst die Adressen der lokalen Variablen auch direkt an die Funktion übergeben:

    eingabe(&k_zahl1);
    

    und was dein Speicherproblem angeht:

    /*1. Speicher anfordern
    malloc() liefert die Adresse eines reserveirten Heap-Blockes zurück, die wird
    in ptr_zahl gespeichert.
    Bis hierher noch alles OK.
    ptr_zahl = malloc(sizeof(struct komplex));
    
    /*2. Zuweisung
    Diese Zuweisung überschreibt die Adresse, die du in (1) gespeichert hast. In
    ptr_zahl steht jetzt die Adresse der lokalen Variablen, an den in (1)
    angeforderten Speicherblock kommst DU von jetzt ab nicht mehr dran (Speicherleck).
    */
    ptr_zahl = &zahl;
    
    /*3. Freigabe
    Nach Anweisung (2) steht in ptr_zahl die Adresse der lokalen Variablen. Diese
    Adresse stammt nicht vom Heap-Manager, also hast du auch nicht das Recht, sie
    an diesen zurückzugeben - das Ergebnis ist undefiniert (im besten Fall crasht
    dein Programm).
    */
    free(ptr_zahl);
    

    PS: Ist es eigentlich Absicht, daß sub() einen anderen Prototyp verwendet als die übrigen Funktionen?



  • PS: Ist es eigentlich Absicht, daß sub() einen anderen Prototyp verwendet als die übrigen Funktionen?[/quote]

    Hab ich mich auch schon gefragt warum der Prototyp anders ist als die anderen 3.
    Prototypen wurden uns vom Prof vorgegeben.

    Also ich hab jetzt mal die ganzen Pointervariablen gekillt und tatsächlich die Ausgabe spinnt jetzt auch nicht mehrt.

    Muß ich also nirgedswo mit malloc Speicher reservieren?

    Versteh ich das richtig das es reicht um einen variable als Pointer zu übergeben einfach den cast-Operator & davor zusetzten.

    Hab das irgnedwie so mit diesen zusatz variablen verstanden...

    Aber läuft auf jedenfall jetzt...



  • Dragonslayer schrieb:

    PS: Ist es eigentlich Absicht, daß sub() einen anderen Prototyp verwendet als die übrigen Funktionen?

    Hab ich mich auch schon gefragt warum der Prototyp anders ist als die anderen 3.
    Prototypen wurden uns vom Prof vorgegeben.

    Dann solltest du die Frage mal an den Prof weitergeben 😉

    Muß ich also nirgedswo mit malloc Speicher reservieren?

    Für so ein Programm nicht.
    (es gibt schon Fälle, wo malloc() nützlich ist, aber das benötigt schon genauerer Kenntnisse, um keinen Mist damit zu produzieren)

    Versteh ich das richtig das es reicht um einen variable als Pointer zu übergeben einfach den cast-Operator & davor zusetzten.

    Das ist kein Cast-Operator, sondern ein Adress-Operator - und ja, der liefert einen Pointer auf die (lokale) Variable zurück.


Anmelden zum Antworten