P.roblem s.olved :)



  • gut das hab ich grad auch rausgekommen, danke für die hilfe.
    aber ich muss doch zwei intervalle damit verarbeiten oder ist das nun ein denkfehler meinerseits ?

    Intervall operator+(const Intervall& i1);
    

    geht

    und

    Intervall operator+(const Intervall& i1, const Intervall& i2);
    

    will er nicht..
    oder brauch ich das garnicht und nehme gleich i3 ?
    und definiere i3 = i1 + i2 ?



  • Lies bitte den Artikel, das sind wirklich Grundlagen. Bist du auch sicher, dass es klug ist, für Intervallvereinigung das Plus zu verwenden? Implementierst du das kommutativ? Denke einfach an den verwirrten Anwender, der sich mit der Bedeutung zurechtfinden muss (und wenn das nur du selbst bist).



  • c.groupe schrieb:

    Intervall operator+(const Intervall& i1);
    

    geht

    und

    Intervall operator+(const Intervall& i1, const Intervall& i2);
    

    will er nicht..

    Das kommt darauf an, wo du das hinschreibst...
    Entweder ist operator+ ein Klassenmember, dann

    class Intervall {
      public:
      Intervall operator+(const Intervall& other);
    };
    

    Oder eben global:

    class Intervall
    {
      // Methoden
    };
    
    Intervall operator+( const Intervall& i1, const Intervall& i2);
    

    Aber lies dir doch endlich den Artikel durch...



  • okay der artikel ist echt nicht schlecht ..

    also das ist schonmal meine header datei:

    /*
     * Interval.h
     *
     *  Created on: 15.09.2009
     *      Author: c.groupe
     */
    
    #ifndef INTERVAL_H_
    #define INTERVAL_H_
    
    class Intervall
    {
    	double a,e;
    	int wert[5];
    
    	public:
    		Intervall (double a, double e);
    		int isEmpty();
    		int contains(double wert);
    		const Intervall Intervall::plus(Intervall const& i2) const;
    		const Intervall Intervall::minus(Intervall const& i2) const;
    
    };
    
    #endif /* INTERVAL_H_ */
    

    in der Intervall.cpp
    hab ichs nun so eingebunden..

    const Intervall operator+(Intervall const& i1, Intervall const& i2)
    {
    	return i1.plus(i2);
    }
    
    const Intervall operator-(Intervall const& i1, Interval const& i2)
    {
    	return i2.minus(i2);
    }
    

  • Mod

    Hast ein paar Fehler, sieht aber prinzipiell nach einem guten Ansatz aus.

    Erstmal Kritik:

    #include "Intervall.h"
    #include <iostream.h>  // iostream.h ist kein Standardheader
    using namespace std;
    
    Intervall::Intervall(double a, double e)
    {
    /* Zwei Fehler: 
       1) Programmiertechnisch: isEmpty benutzt this->a und this->e, diese werden aber erst hier gesetzt
       2) Progrmmlopgik: Das Intervall [0,0] ist nicht leer, sondern enthält die 0
    */
        if (isEmpty != 0)
        {
            this ->a = a;
            this ->e = e;
    
        }
        else
        {
            cerr << "Leeres Intervall";
            this ->a = 0;
            this ->e = 0;
        }
    
    }
    
    int Intervall::isEmpty()  // const correctness nicht beachtet
    {
        if (a > e)
        {
    /* Hier überschreitet die Methode ihre vorgesehenen Kompetenzen. Sie soll 
    nichts ausgeben, sondern nur wahr oder falsch zurückgeben. Ansonsten richtig, 
    wenn auch ziemlich lang ausgeschrieben.
    */
            cout << "Intervall enthält keine Werte: -> leeres Intervall";
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    int Intervall::contains(double wert)  // const correctness nicht beachtet
    {
    /* gleiche Kritik wie bei isEmpty */
    
        if ((wert >= a) && (wert < e))
        {
            return 1;
            cout << "Wert liegt innerhalb des Intervalls";
        }
        else
        {
            return 0;
            cout << "Wert liegt außerhalb des Intervalls";
        }
    }
    

    Ein Verbesserungvorschlag:

    #include "Intervall.h"
    
    Intervall::Intervall(const double &a, const double &e): a(a), e(e)
    {
    /* Initialisierungslisten sind hier die bessere Lösung. Es interessiert in den 
    anderen Programmteilen ja gar nicht, ob a oder e größer ist. Falls trotzdem 
    eine Prüfung stattfinden soll, kann man nun auch this->a und this->e verwenden,
    da sie schon initialisiert wurden. Sinnvoll wäre es zum Beispiel für das leere 
    Intervall a sehr groß und e sehr klein zu setzen. */
    }
    
    bool Intervall::isEmpty() const   // bool ist hier angemessener als int.
    {
    return (a >= e);
    /* So kurz kann man sich fassen. Kleine verbesserung: a darf nun auch gleich e sein (Intervall enthält nur 1 Element)
    */
    }
    
    bool Intervall::contains(const double & wert) const
    {
    return ((wert >= a) && (wert < e));
    /* Siehe oben */
    }
    

    Was die Operatorüberladung angeht: Deiner Deklaration im Header nach zu schließen, weißt du nicht, was es mit Operatorüberladung auf sich hat. Das musst du dir angucken, um das weitere zu verstehen. Da in der Aufgabenstellung nur die Implementierung von Operator + verlangt wird, gebe ich dir als Beispiel mal den Operator minus. Ich werde aber hier nicht Operatorüberladung vollständig diskutieren, da musst du dir mal eine gute Beschreibung suchen (zum Beispiel den Artikel im Thread "Neue Artikel zu C++ im Magazin")

    const Intervall Intervall::operator-(const Intervall &i, const Intervall &j){
    /* Nun ist es doch wichtig, ob die Intervalle eventuell leer sind. Das hätte 
    wohl doch besser im Konstruktor abgefangen werden müssen. Da ich das nicht 
    gemacht habe, habe ich nun mehr Mühe. Du kannst das süäter sicherlich besser :-)
    */
    if (i.isEmpty()) return Intervall(j.a,j.e);
    if (j.isEmpty()) return Intervall(i.a,i.e);
    /* Ok, alle Sonderfälle erledigt, jetzt geht es richtig los: */
    double max_a = (i.a > j.a) ? i.a : j.a;
    double min_e = (i.e < j.e) ? i.e : j.e;
    return Intervall(max_a,min_e);
    }
    


  • sry, dass ich jz wieder HAs mach, aber die lange Weile... 😉

    ungetestet (und unvollständig):

    Intervall -> 2 Werte. Kommawerte -> double oder float

    struct interval
    {
    private:
       float lower_bound;
       float upper_bound;
    };
    

    beim Instanzieren (-> Konstruktor) werden 2 Parameter angegeben (-> interval(float left, float right)). wenn der rechte kleiner ist, als der linke soll ein leeres interval angelegt werden:

    struct interval
    {
    private:
      float lower_bound;
      float upper_bound;
    public:
      interval(float lower, float upper)
      :  lower_bound(lower),
         upper_bound(upper)
      {
        if(lower_bound > upper_bound)
          upper_bound = lower_bound;
      }
    };
    

    Die Methode isEmpty gibt zurück, ob ein Intervall keine Werte beinhalten kann(ob es ein leeres Intervall ist):

    struct interval
    {
    private:
      float lower_bound;
      float upper_bound;
    public:
      interval(float lower, float upper)
      :  lower_bound(lower),
         upper_bound(upper)
      {
        if(lower_bound > upper_bound)
          upper_bound = lower_bound;
      }
    
      bool isEmpty() const //verändert nichts am objekt
      {
        return lower_bound > upper_bound;
      }
    };
    

    oh - das haben wir im konstruktor schon mal verwendet:

    struct interval
    {
    private:
      float lower_bound;
      float upper_bound;
    public:
      interval(float lower, float upper)
      :  lower_bound(lower),
         upper_bound(upper)
      {
        if(isEmpty())
          upper_bound = lower_bound;
      }
    
      bool isEmpty() const //verändert nichts am objekt
      {
        return lower_bound > upper_bound;
      }
    };
    

    Die Methode contains kontrolliert, ob ein gegebener Wert (->contains(float value)). rückgabewert ist true oder false -> bool contains(float value)
    auch contains verändert wieder nichts an unserem objekt:

    struct interval
    {
    private:
      float lower_bound;
      float upper_bound;
    public:
      interval(float lower, float upper)
      :  lower_bound(lower),
         upper_bound(upper)
      {
        if(isEmpty())
          upper_bound = lower_bound;
      }
    
      bool isEmpty() const //verändert nichts am objekt
      {
        return lower_bound > upper_bound;
      }
    
      bool contains(float value) const
      {
        return (lower_bound <= value) && (value <= upper_bound);
      }
    };
    

    etc...

    bb



  • unskilled schrieb:

    tu mir ma pls den gefallen und schreib die aufgabenstellung hier hin - aus *.jpg`s kann ich nich ganz so gut copy&pasten^^
    und dann beschreib ma pls, was für dich ein leeres intervall ist und dann noch mal, was du im konstruktor machen willst - da fehlt mindestens noch ein paar Klammern hinter isEmpty - was btw den rückgabewert bool haben sollte, wenn ichs richtig gelesen habe.
    dein ctor hat so und so undefiniertes verhalten zur folge...

    bb

    habs selbst nur als jpg daher wirds wohl nicht, aber wenns nicht geht ist auch nicht schlimm.



  • wow ihr seit ja echt spitze, ich muss mir das aber nun weiter mal in ruhe anschauen, kann es echt nicht so schnell nachvollziehen, also nicht sauer sein, wenn ich nicht gleich antworte. dennoch vielen dank schonmal an alle..



  • nun hab ich noch ne frage beim inizialisieren..

    warum kann ich die operatoren nur so initialisieren, dass 0 oder 1 argument übergeben wird ?

    also so

    const Intervall Intervall::minus(Intervall const &j) const;
    

    und nicht so

    const Intervall Intervall::operator-(const Intervall &i, const Intervall &j);
    


  • operatoren nur so initialisieren, dass 0 oder 1 argument

    1. definieren
    2. lies den ******* artikel! aber tip: es gibt nur 2 seiten und *this ist die eine...

    bb

    edit:
    hier, fertiglösung:

    #include <algorithm>
    
    template<typename T>
    struct interval
    {
    private:
    	T lower_bound;
    	T upper_bound;
    public:
    	interval(const T &lower, const T &upper)
    	:	lower_bound(lower),
    		upper_bound(upper)
    	{
    		if(isEmpty())
    			upper_bound = lower_bound;
    	}
    
    	bool isEmpty() const //"Die Methode isEmpty gibt an, ob ein Intervall keine Werte enthalten kann"
    	{	//[x, x] kann nicht keine Werte enthalten, da x dazu gehört
    		return lower_bound > upper_bound;
    	}
    
    	bool contains(const T &value) const
    	{
    		return (value <= lower_bound) && (value <= upper_bound);
    	}
    
    	interval operator+ (const interval &other) const
    	{
    		T lower = std::min(lower_bound, other.lower_bound);
    		T upper = std::max(upper_bound, other.upper_bound);
    		return interval(lower, upper);
    	}
    
    	interval opertor- (const interval &other) const
    	{
    		T lower = std::max(lower_bound, other.lower_bound);
    		T upper = std::min(upper_bound, other.upper_bound);
    		return interval(lower, upper);
    	}
    };
    

    allein für die Formulierung des Verhaltens der isEmpty()-Fkt gehört der Aufgabensteller verprügelt - hat mich mehr Zeit gekostet, darüber nachzudenken, was ein leeres abgeschlossenes Intervall sein sollte als den Rest zu tippen...


  • Mod

    c.groupe schrieb:

    nun hab ich noch ne frage beim inizialisieren..

    warum kann ich die operatoren nur so initialisieren, dass 0 oder 1 argument übergeben wird ?

    also so

    const Intervall Intervall::minus(Intervall const &j) const;
    

    und nicht so

    const Intervall Intervall::operator-(const Intervall &i, const Intervall &j);
    

    Ups, da hatte ich einen kleinen Schreibfehler bei meinem Beispiel. Wenn man einen binären Operator als Klassenmethode implementiert, kann er nur ein Argument nehmen, die linke Seite ist dann "this". Will man die Variante mit zwei Argumenten verwenden, muss man den Operator als freie Funktion überladen. Die Pros und Contras beider Methoden kannst du in guten Texten zum Thema nachlesen.



  • ist ja gut 😉 ..

    gut werde ich dann machen, wird also meine bett lektüre!
    wünsche allen eine gute nacht, und bis nacher 😉



  • Kurze anmerkung:

    unskilled schrieb:

    bool contains(const T &value) const
        {
            return (value <= lower_bound) && (value <= upper_bound);
        }
    

    müsste es da nicht eher

    return (value   >=   lower_bound) && (value <= upper_bound);
    

    heißen, da ja geprüft werden soll, ob der Wert im Intervall ist ....

    Gruß Simon



  • Und die Zeilen 14-15 müssen in unskilled code auch noch weg 😉

    Nexus schrieb:

    Bist du auch sicher, dass es klug ist, für Intervallvereinigung das Plus zu verwenden? Implementierst du das kommutativ?

    Vereinigung ist kommutativ. Trotzdem ist es natürlich etwas merkwürdig dafür operator+ verwenden zu wollen..



  • unskilled schrieb:

    #include <algorithm>
    
    template<typename T>
    struct interval
    {
    private:
    	T lower_bound;
    	T upper_bound;
    public:
    	interval(const T &lower, const T &upper)
    	:	lower_bound(lower),
    		upper_bound(upper)
    	{
    		if(isEmpty())
    			upper_bound = lower_bound;
    	}
    
    	bool isEmpty() const //"Die Methode isEmpty gibt an, ob ein Intervall keine Werte enthalten kann"
    	{	//[x, x] kann nicht keine Werte enthalten, da x dazu gehört
    		return lower_bound > upper_bound;
    	}
    :
    :
    

    Das upper_bound = lower_bound; führt dazu, dass isEmpty() false liefert. Es scheint, als kann es keine Intervalle geben, die "empty" sind.

    Der Aufgabensteller gehört dafür verprügelt, dass er für Vereinigung und Durchschnitt operator+ und operator- benutzen will. 🙂



  • //[x, x] kann nicht keine Werte enthalten, da x dazu gehört
    

    Ich liebe doppelte Verneinungen ... wie waere es mit: [x,x] ist nicht leer, da x enthalten ist.

    Ich empfinde den Operator + nicht als Fehlgriff. Ist halt 'ne Algebra auf Paare von reelen Zahlen.



  • So ich hab mir das durchgelesen aber verstehe es immer noch nicht,
    es ist keine hausaufgabe oder sonst was ich lerne einfach nur für ne c++ klausur 😉 ..

    /*
     * Interval.h
     *
     *  Created on: 15.09.2009
     *      Author: c.groupe
     */
    
    #ifndef INTERVAL_H_
    #define INTERVAL_H_
    
    class Intervall
    {
    
    	public:
    		double a,e;
    		Intervall(const double &a, const double &e);
    		bool isEmpty() const;
    		bool contains(const double & wert) const;
    		const Intervall Intervall::plus(Intervall const &j) const;
    		const Intervall Intervall::minus(Intervall const &j) const;
    };
    
    #endif /* INTERVAL_H_ */
    
    /*
     * Intervall.cpp
     *
     *  Created on: 15.09.2009
     *      Author: c.groupe
     */
    
    #include "Intervall.h"
    #include <iostream.h>
    using namespace std;
    
    Intervall::Intervall(const double &a, const double &e): a(a), e(e)
    {
    	if (e > a)
    	{
    		this ->a = a;
    		this ->e = e;
    	}
    	else
    	{
    	cerr << "Leeres Intervall";
    	this ->a = 100;
    	this ->e = 0;
    	}
    }
    
    bool Intervall::isEmpty() const
    {
    	return (a >= e);
    }
    
    bool Intervall::contains(const double & wert) const
    {
    	return ((wert >= a) && (wert < e));
    }
    
    const Intervall operator+(const Intervall &i, const Intervall &j)
    {
    
    	if (i.isEmpty()) return Intervall(j.a,j.e);
    	if (j.isEmpty()) return Intervall(i.a,i.e);
    
    	double min_a = (i.a < j.a) ? i.a : j.a;
    	double max_e = (i.e > j.e) ? i.e : j.e;
    	return 	Intervall(min_a,max_e);
    }
    
    const Intervall operator-(const Intervall &i, const Intervall &j)
    {
    	if (i.isEmpty()) return Intervall(j.a,j.e);
    	if (j.isEmpty()) return Intervall(i.a,i.e);
    
    	double max_a = (i.a > j.a) ? i.a : j.a;
    	double min_e = (i.e < j.e) ? i.e : j.e;
    	return Intervall(max_a,min_e);
    }
    
    /*
     * main.cpp
     *
     *  Created on: 16.09.2009
     *      Author: c.groupe
     */
    
    #include "Intervall.h"
    #include <iostream.h>
    using namespace std;
    
    int main()
    {
        Intervall i(0,5), j(6,20);
    }
    

    edit:
    es werden keine fehler mehr angezeigt, aber es ist sichern noch nicht ganz richtig, bin gerade am überlegen, wie ich es am besten testen kann.


  • Mod

    c.groupe schrieb:

    edit:
    es werden keine fehler mehr angezeigt, aber es ist sichern noch nicht ganz richtig, bin gerade am überlegen, wie ich es am besten testen kann.

    Die Frage ist leicht zu beantworten: Mit einem Debugger! Das beste Mittel um Fehler in der Programmlogik zu finden.



  • SeppJ schrieb:

    c.groupe schrieb:

    edit:
    es werden keine fehler mehr angezeigt, aber es ist sichern noch nicht ganz richtig, bin gerade am überlegen, wie ich es am besten testen kann.

    Die Frage ist leicht zu beantworten: Mit einem Debugger! Das beste Mittel um Fehler in der Programmlogik zu finden.

    Genau. Für das Visual Studio gibt's zu dem Thema übrigens einen guten Artikel:

    http://magazin.c-plusplus.net/artikel/Debuggen mit VCPlusPlus6
    (bezieht sich zwar auf's VS6, das meiste kann man aber einfach auf neuere Versionen anwenden)



  • @varginator
    jopp

    @life
    ne, das is aufgabenstellung - nur ist das eben nicht anders zu machen, da isEmpty so komisch definiert wurde...

    @c.groupe:
    du hast viele fehler gemacht, die dir schon mal jmd berichtigt hatte...
    außerdem hast du das mit der initialisierungsliste nicht ganz verstanden, wie mir scheint
    und das geheimnisprinzip (was in der aufgabenstellung so gar iwo erwähnt wurde) hast du komplett ignoriert...
    du könntest auch mal sprechende variablennamen nutzen
    auch hatte ich nix von einer ausgabe im ctor gelesen...

    op+ verstehe ich anders - es ist egal, ob das intervall leer ist oder nicht. aber wie gesagt: die aufgabenstellung ist extrem schwammig, also hier könntest du noch recht haben, allerdings kannst du das erste const mal wegmachen, das ist sinnlos^^

    const Intervall operator+(const Intervall &i, const Intervall &j)
    {
    
        if (i.isEmpty()) return Intervall(j.a,j.e);
        if (j.isEmpty()) return Intervall(i.a,i.e);
    
        double min_a = (i.a < j.a) ? i.a : j.a;
        double max_e = (i.e > j.e) ? i.e : j.e;
        return     Intervall(min_a,max_e);
    }
    

    das hier würde ich dagegen als falsch ansehen...
    leeres intervall - nicht leeres intervall = nicht leeres intervall?
    eher nicht... wieso versucht du überhaupt, diese fälle abzufangen?
    es reicht absolut so, wie ich es oben gemacht habe...

    const Intervall operator-(const Intervall &i, const Intervall &j)
    {
        if (i.isEmpty()) return Intervall(j.a,j.e);
        if (j.isEmpty()) return Intervall(i.a,i.e);
    
        double max_a = (i.a > j.a) ? i.a : j.a;
        double min_e = (i.e < j.e) ? i.e : j.e;
        return Intervall(max_a,min_e);
    }
    

    op+ und op- zu benutzen find ich btw nicht so extrem schlimm - schlimmer ist der rest 😉

    bb


Anmelden zum Antworten