Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Klasse für rationale Zahlen (Brüche)

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
27.12.2009, 16:15 Uhr
~qwertzu
Gast


Hallo!
Ich bin gerade dabei eine Klasse zu programmieren, die mit rationalen Zahlen rechnen soll. Sie soll mit den Grundrechenarten, Minus als Vorzeichen und Klammern klarkommen. Konstruktoren haben wir noch nicht behandelt, deshalb ist die Eingabe der Werte noch etwas kompliziert dargestellt:


C++:
#include <iostream>
#include <iomanip>
using namespace std ;



class Ratio {
      public:
             void ein(int z,int n);
             void aus();
             void gleitkomma();
            
             Ratio operator*(Ratio &r);
             Ratio operator/(Ratio &r);
             Ratio operator+(Ratio &r);
             Ratio operator-();
             Ratio operator-(Ratio &r);
            
      private:
              int zaehler;
              int nenner;
              void kuerzen();
};


void Ratio::ein(int z,int n) {
     zaehler=z;
     nenner=n;
}

void Ratio::kuerzen() {
     int a;
     if (abs(zaehler)>abs(nenner)) { a=abs(nenner)+1; } else { a=abs(zaehler)+1; }
     do {
     a--;
     } while ((zaehler%a!=0) || (nenner%a!=0));
    
     zaehler=zaehler/a;
     nenner=nenner/a;
                              
}

void Ratio::aus() {
     kuerzen();
     cout << zaehler << "/" << nenner << endl;
}

void Ratio::gleitkomma() {
     cout << (float)zaehler/(float)nenner << endl;    
}


Ratio Ratio::operator*(Ratio &r) {
      Ratio erg;
      erg.ein(zaehler*r.zaehler,nenner*r.nenner);    
      return(erg);
}

Ratio Ratio::operator/(Ratio &r) {
      Ratio erg;
      erg.ein(zaehler*r.nenner,nenner*r.zaehler);    
      return(erg);
}


Ratio Ratio::operator+(Ratio &r) {
      int n=nenner*r.nenner;
      Ratio erg;
      erg.ein(zaehler*n/nenner+r.zaehler*n/r.nenner,n);    
      return(erg);
}


Ratio Ratio::operator-() {
      Ratio erg;
      erg.ein(-zaehler,nenner);
      return(erg);
      }

    
Ratio Ratio::operator-(Ratio &r) {
      int n=nenner*r.nenner;
      Ratio erg;
      erg.ein(zaehler*n/nenner-r.zaehler*n/r.nenner,n);    
      return(erg);
}





int main()
{
    Ratio r1,r2,r3,r4,r5,erg,erg2;
    r1.ein(2,25);
    r2.ein(7,5);
    r3.ein(2,5);
    r4.ein(1,4);
    r5.ein(1,3);

    erg=r1*(r2+r3);
    erg.aus();
    erg.gleitkomma();

  
    system("Pause");
    return(0);
}



Nachdem ich das Problem mit einem Minus als Vorzeichen gelöst habe, ist jetzt noch das Problem der Klammern offen.
Wie kann ich der Klasse klar machen, dass sie zuerst die Klammer berechnen soll und dann die Multiplikation?
Zurzeit habe ich noch folgende Fehlermeldung:

rational.cc: In function `int main()':
rational.cc:103: error: no match for 'operator*' in 'r1 * (&r2)->Ratio::operator+(((Ratio&(&r3)))'
rational.cc:55: note: candidates are: Ratio Ratio::operator*(Ratio&

Über Infos zu diesem Problem würde ich mich freuen,

Thomas
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
27.12.2009, 16:16 Uhr
~qwertzu
Gast


So, Fehlercode wird falsch dargestellt, deshalb 2.Versuch:

rational.cc: In function `int main()':
rational.cc:103: error: no match for 'operator*' in 'r1 * (&r2)->Ratio::operator+(((Ratio&)(&r3)))'
rational.cc:55: note: candidates are: Ratio Ratio::operator*(Ratio&)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
27.12.2009, 16:47 Uhr
0xdeadbeef
Gott
(Operator)


Temporäre Objekte können nur an konstante Referenzen gebunden werden, du musst als Parameter also Ratio const & statt Ratio& übergeben und die Methoden const deklarieren:

C++:
class Ratio {
  // ...
  Ratio operator+(Ratio const&) const;
  // ...
};

// ...

Ratio Ratio::operator+(Ratio const &r) const {
  // ...
}



Übrigens, ein paar Designtips: Lass ein lieber einen Konstruktor sein, also

C++:
class Ratio {
  // ...
  Ratio(int z, int n);
  // ...
};

// ...

Ratio::Ratio(int z, int n)
  : zaehler(z), nenner(n)
{
  kuerzen();
}


Dann kannst du nämlich deine Brüche als

C++:
Ratio einhalb(1, 2);


instantiieren.

Außerdem solltest du dir vielleicht überlegen, die Operatoren als freistehende Funktionen zu implementieren, das wird dann übersichtlicher, wenn du Ratio-Objekte mit anderen Typen verrechnen willst (beispielsweise int).

Und schlussendlich, wenn du schon dabei bist, könntest du die Zuweisungsoperatoren definieren, um die Rechenoperatoren dann mit ihnen zu implementieren. Etwa so:

C++:
// .hpp

class Ratio {
public:
  Ratio(int z, int n = 1);

  Ratio const &operator+=(Ratio const &);
  Ratio const &operator-=(Ratio const &);
  Ratio const &operator*=(Ratio const &);
  Ratio const &operator/=(Ratio const &);

private:
  int zaehler;
  int nenner;

  void kuerzen();
};

Ratio const operator+(Ratio const &lhs, Ratio const &rhs);
Ratio const operator-(Ratio const &lhs, Ratio const &rhs);
Ratio const operator*(Ratio const &lhs, Ratio const &rhs);
Ratio const operator/(Ratio const &lhs, Ratio const &rhs);

// .cpp

Ratio const &operator+=(Ratio const &r) {
  zaehler = zaehler * r.nenner + r.zaehler * nenner;
  nenner *= r.nenner;

  kuerzen();

  return *this;
}

Ratio const operator+(Ratio const &lhs, Ratio const &rhs) {
  Ratio r(lhs);
  r += rhs;
  return r;
}

// Analog alle anderen Rechenoperatoren


Außerdem würde ich die Methode aus flexibler gestalten als

C++:
std::ostream &operator<<(std::ostream &out, Ratio const &r) {
  return out << r.zaehler() << '/' << r.nenner();
}


In der Variante braucht Ratio dann halt zwei Zugriffsfunktionen int zaehler() const und int nenner() const, alternativ kannst du den Operator auch zum Freund der Klasse erklären. Schlussendlich würde ich gleitkomma() ersetzen durch etwa

C++:
class Ratio {
  // ...
  double to_double() const;
  // ...
};

double Ratio::to_double() const {
  return static_cast<double>(zaehler) / nenner;
}


...denn der Wert könnte auch zum Rechnen, nicht nur zur Ausgabe interessant sein.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 27.12.2009 um 16:52 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: