Array und Pointer



  • Hallo sitze gerade vor einer Übung und habe ein Problem...

    Aufgabe:
    *Ermitteln Sie den maximalen Abstand zweier Punkte des Feldes, das Sie mit
    neuesPunktFeld() erzeugt haben. Prototyp der Prozedur:
    double maxAbstand(Punkt **, Punkt *, Punkt );
    Der erste Parameter ist für die Übergabe des Feldes, mit dem zweiten und dritten
    Parameter sollen die ermittelten Punkte zurückgegeben werden.

    Folgendes habe ich ausgearbeitet:

    ...
    cout << "\n*dynamische Punkt Feld Erzeugung*\n";
    	Punkt **arrPunkt = neuesPunktFeld(ARRAY_GROESSE);
    	for(int i=0; i<ARRAY_GROESSE; i++)
    	{
    		printPunkt( *(arrPunkt[i]) );
    	}
    
    	cout << "\n*Ermittelter maximaler Abstand zwischen 2 Punkten aus dem Feld*\n";
    	Punkt *tmp1, *tmp2;
    	cout << tmp1 << "\t" << tmp2 << endl;
    	cout << "Maximaler Abstand ist bei:" << endl;
    	cout << maxAbstand(arrPunkt, tmp1, tmp2) << endl;
    	cout << tmp1 << "\t" << tmp2 << endl;
    	printPunkt(*tmp1);
    	printPunkt(*tmp2);
    	return 0;
    }
    
    double maxAbstand(Punkt **arrPunkt, Punkt *p1, Punkt *p2)
    {
    	double nMax = 0;
    	double nTempCalc; 
    	//arrPunkt ist übergebenes Feld
    	//über p1 und p2 werden die Punkte zurückgegeben welche den größten abstand haben
    	//double abstand(Punkt p1, Punkt p2) 
    	for(int x=0; x<ARRAY_GROESSE; x++)
    	{
    		nTempCalc = abstand( *(arrPunkt[x]), *(arrPunkt[ARRAY_GROESSE-1-x]) );
    
    		if( nMax < nTempCalc) {
    			p1 = arrPunkt[x];
    			p2 = arrPunkt[ARRAY_GROESSE-x-1];
    			nMax = nTempCalc;
    		}
    	}
    
    	return nMax;
    }
    

    Problem:
    Der Inhalt der Punkt Pointer "tmp1" und "tmp2" ist nur Müll auch die Referenzierte Adresse ändert sich nicht von den beiden Variablen.

    Frage
    Muss ich für die Punkt Pointer Variablen tmp1 und tmp2 ein Extra speicher mit new anlegen? Eigentlich will ich die ja nur auf einen bereits vorhandenen Speicher referenzieren 😕



  • Mein aufrichtiges Beileid, dass du dich mit solch bescheuerten Übrungen von Leuten, die offensichtlich wenig C++ Erfahrung haben, beschäftigen musst.

    Wie dem auch sei, tmp1 und tmp2 sind bei dir zwei uninitialisierte Zeiger, mit denen du einfach arbeitest, als würden die schon irgendwohin zeigen, wo es POINT-Objekte gibt.

    Wie der code unter den Voraussetzungen auszusehen hat, kann ich Dir nicht sagen, weil ich die Aufgabenstellung nicht wirklich verstanden habe. Ich finde sie unpräzise. Vielleicht fehlt mir da auch etwas Kontext.



  • Evtl. zur Ergänzung

    typedef struct {
    	double x;
    	double y;
    } Punkt;
    
    double abstand(Punkt p1, Punkt p2) 
    {
    	return sqrt( (p2.y-p1.y)*(p2.y-p1.y) + (p2.x-p1.x)*(p2.x-p1.x) );
    }
    

    Tja, finde sie auch nicht ganz Toll aber das Semester hat erst begonnen und das ist nun die erste Aufgabe...



  • Kannst du mal die Funktion neuesPunktFeld zeigen?

    BTW in C++ schreibt man

    struct Punkt {
        double x;
        double y;
    };
    

    Die Version mit typedef ist in C notwendig, wenn man den so definierten Datentyp Punkt nennen will statt immer ausführlich struct Punkt schreiben zu müssen, in C++ heißt der Typ von vornherein nur Punkt .



  • Aufruf der Funktion mit Hilfe des Adressoperators:

    Punkt tmp1, tmp2;
    cout << tmp1 << "\t" << tmp2 << endl;
    cout << "Maximaler Abstand ist bei:" << endl;
    cout << maxAbstand(arrPunkt, &tmp1, &tmp2) << endl;
    

    Besser wären jedoch Referenzen als Parameter (aber die Aufgabenstellung ist ja leider anders).


  • Mod

    Bashar schrieb:

    Die Version mit typedef ist in C notwendig, wenn man den so definierten Datentyp Punkt nennen will statt immer ausführlich struct Punkt schreiben zu müssen, in C++ heißt der Typ von vornherein nur Punkt .

    Apropos C und C++: Da das einzige an dem Code, was kein typisches* C ist, das cout ist, würde ich doch gerne vom Threadersteller erfahren, ob die couts vielleicht von ihm auf eigene Faust eingebaut wurden. Wenn das nämlich ein C-Kurs ist und die couts vom TE stammen, dann würde das so einiges erklären. Und man könnte auch produktiver helfen, als nur zu sagen, dass das ganz besch...eidenes C++ ist.

    *: Damit meine ich nicht "gut". Bloß typisch für C-Anfängerkurse.



  • Bashar schrieb:

    Kannst du mal die Funktion neuesPunktFeld zeigen?

    BTW in C++ schreibt man

    struct Punkt {
        double x;
        double y;
    };
    

    Die Version mit typedef ist in C notwendig, wenn man den so definierten Datentyp Punkt nennen will statt immer ausführlich struct Punkt schreiben zu müssen, in C++ heißt der Typ von vornherein nur Punkt .

    @Bashar
    Danke für den Tip mit der "typedef" wusste ich nicht 😃

    Punkt **neuesPunktFeld(int nDim)
    {
    	Punkt **arrPunkt = new Punkt*[nDim];
    	for(int i=0; i<nDim; i++) {
    		arrPunkt[i] = neuerPunkt();
    	}
    	return arrPunkt;
    }
    

    @Th6
    Leider, gibt es da wohl kein Spielraum für den Funktionsaufbau...aber trotzdem Danke



  • SeppJ schrieb:

    Bashar schrieb:

    Die Version mit typedef ist in C notwendig, wenn man den so definierten Datentyp Punkt nennen will statt immer ausführlich struct Punkt schreiben zu müssen, in C++ heißt der Typ von vornherein nur Punkt .

    Apropos C und C++: Da das einzige an dem Code, was kein typisches* C ist, das cout ist, würde ich doch gerne vom Threadersteller erfahren, ob die couts vielleicht von ihm auf eigene Faust eingebaut wurden. Wenn das nämlich ein C-Kurs ist und die couts vom TE stammen, dann würde das so einiges erklären. Und man könnte auch produktiver helfen, als nur zu sagen, dass das ganz besch...eidenes C++ ist.

    *: Damit meine ich nicht "gut". Bloß typisch für C-Anfängerkurse.

    Ne das ist ein C++ kurs, C hatten wir bereits und du hast recht ausser cout und <iostream> ist hier C++ sehr gering



  • Mit einer einfachen Schleife wirst du kaum alle Punkte miteinander vergleichen können.
    Denn du musst ja den
    1. mit dem 2. Punkt vergleichen
    1. mit dem 3.
    1. mit dem 4.
    ....
    1. mit dem ARRAY_GROESSE.
    2. mit dem 3.
    2. mit dem 4.
    ...
    2. mit dem ARRAY_GROESSE.
    ...
    ARRAY_GROESSE-1 mit dem ARRAY_GROESSE. Punkt vergleichen



  • DirkB schrieb:

    Mit einer einfachen Schleife wirst du kaum alle Punkte miteinander vergleichen können.
    Denn du musst ja den
    1. mit dem 2. Punkt vergleichen
    1. mit dem 3.
    1. mit dem 4.
    ....
    1. mit dem ARRAY_GROESSE.
    2. mit dem 3.
    2. mit dem 4.
    ...
    2. mit dem ARRAY_GROESSE.
    ...
    ARRAY_GROESSE-1 mit dem ARRAY_GROESSE. Punkt vergleichen

    Ja ist mir bewusst, habe die Funktion aber aufgrund des Problems nicht mehr weiter ausgebaut...Werde noch ein innere Schleife einbauen die von oben nach unten -1 zählt.



  • Ich habe das nun so gelöst, obwohl ich mit dieser Lösung nicht zufrieden bin, da ich einen neuen Speicher reserviere...

    ...
        Punkt *tmp1 = new Punkt;
    	Punkt *tmp2 = new Punkt;
    
    	cout << "Maximaler Abstand ist bei:" << endl;
    	cout << maxAbstand(arrPunkt, tmp1, tmp2) << endl;
    	printPunkt(*tmp1);
    	printPunkt(*tmp2);
    	return 0;
    }
    
    double maxAbstand(Punkt **arrPunkt, Punkt *p1, Punkt *p2)
    {
    	double nMax = 0;
    	double nTempCalc; 
    
    	for(int x=0; x<ARRAY_GROESSE; x++)
    	{
    		for(int y=ARRAY_GROESSE-1; y>0; y--)
    		{
    			nTempCalc = abstand( *(arrPunkt[x]), *(arrPunkt[y]) );
    
    			if( nMax < nTempCalc) {
    				*p1 = *arrPunkt[x];
    				*p2 = *arrPunkt[ARRAY_GROESSE-x-1];
    				nMax = nTempCalc;
    			}
    		}
    	}
    
    	return nMax;
    }
    


  • Th69 hatte dir doch schon eine bessere Lösung vorgeschlagen.


  • Mod

    Wozu new?

    Punkt tmp1, tmp2;
    
        cout << "Maximaler Abstand ist bei:" << endl;
        cout << maxAbstand(arrPunkt, &tmp1, &tmp2) << endl;
    

    Ist zwar immer noch grauenhaft, aber wenigstens ohne direktes Speicherloch.



  • Ich habe das nun so gelöst, obwohl ich mit dieser Lösung nicht zufrieden bin, da ich einen neuen Speicher reserviere...

    Wieso also reservierst du selbst Speicher? Die richtige Lösung wäre, eine automatische Stack-Variabe zu nehmen:

    Punkt tmp1;
        Punkt tmp2;
    

    Edit: Sei verdammt, SeppJ!



  • Sone schrieb:

    Ich habe das nun so gelöst, obwohl ich mit dieser Lösung nicht zufrieden bin, da ich einen neuen Speicher reserviere...

    Wieso also reservierst du selbst Speicher? Die richtige Lösung wäre, eine automatische Stack-Variabe zu nehmen:

    Punkt tmp1;
        Punkt tmp2;
    

    Edit: Sei verdammt, SeppJ!

    Stimmt auch wieder, bin irgendwie bei den ganzne Pointer und Adresse Variablen hängengeblieben...Danke 👍



  • @DKlay13:
    Nur mal so eine Frage bezüglich des Programmierstils:

    Ist zufälligerweise der Begriff Jürgen Wolf in deinem Bekanntenkreis gefallen?

    Übrigens: Sagt dir der Begriff Speicherloch was?

    PS:
    Ich bin überhaupt kein Freund von Zeigern auf Zeigern...



  • @Bitte ein Bit

    😕 ka wer das sein soll...sollte man Jürgen Wolf kennen? und was ist an meinem Programmierstill nicht in Ordnung?

    Memoryleaks sagt mir was, aber da das eine "Übung" habe ich mir keine gedanken gemacht über delete von Variablen...



  • DKlay13 schrieb:

    @Bitte ein Bit

    😕 ka wer das sein soll...sollte man Jürgen Wolf kennen? und was ist an meinem Programmierstill nicht in Ordnung?

    Nein, Jürgen Wolf sollte man nicht kennen. Der ist Autor von den schlechtesten C/C++* Lehrbüchern überhaupt.
    Und was deinen Programmierstil angeht:
    In C++ nutzt man beispielsweise Referenzen für pass-by-reference, nicht Pointer.
    Und Arrays übergibt man nach dem Iteratorenprinzip, ein Zeiger auf das erste Element und eins hinter das letzte Element, dann kann man folgende Schleifen schreiben:

    for (; begin != end; ++begin)
        // tu was mit *begin
    

    Dann muss man auch nicht viel ändern, um den Code für STL-Container (die man eh bevorzugen sollte) anzupassen.

    *Man, meine versteckten Witze werden immer besser. 🕶


  • Mod

    Und Arrays übergibt man nach dem Iteratorenprinzip, ein Zeiger auf das erste Element und eins hinter das letzte Element

    Um den Vorteil hier noch ein wenig deutlicher zu machen: Man muss nicht das komplette Array angeben, auch Untermengen sind möglich.

    Die Funktion (oder besser das Funktionstemplate) ist so nicht an den Containertyp oder den Iterator gebunden, und kann praktisch über alle Mengen iterieren. Extrem Flexibel.

    das erste Element und eins hinter das letzte Element

    Beiläufig werfe ich für den TE noch den Begriff rechtsoffenes Intervall ein.



  • Hmm ok das kannte ich zwar aber selten bis nie verwendet, aber wieso wird mein Programmierstill runtergemacht? Die Funktionprototypen sind ja nicht von mir gemacht sondern vorgegeben und evtl. ist das ja auch der Sinn der ganzen Übung 😃

    Trotzdem Danke an alle


Anmelden zum Antworten