Autor Beitrag
Thund3rfury
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 21.09.13 11:08 
Guten Morgen,

ich hoffe ich finde hier hilfe, nachdem ich nicht auf die Lösung komme.

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bruch2
{
    public class Bruch
    {
        protected int m_izaehler;
        protected int m_inenner;

        public Bruch(int zaehler, int nenner)
        {
            m_izaehler = 0;
            m_inenner = 1;
        }
        public Bruch()
        {

        }
        public Bruch kuerze(int tmpz, int tmpn)
        {

            if (tmpz != 0)
            {
                int rest;
                int ggt = Math.Abs(tmpz);
                int divisor = Math.Abs(tmpn);
                do
                {
                    rest = ggt % divisor;
                    ggt = divisor;
                    divisor = rest;
                } while (rest > 0);
                tmpz = tmpz / ggt;
                tmpn = tmpn / ggt;
            }
            Bruch Hilfsbruch1 = new Bruch();
            Hilfsbruch1.set(tmpz, tmpn);
            //return new Bruch(set(tmpz, tmpn));
            return (Hilfsbruch1);

        }
        public Bruch multipliziere(Bruch other)
        {
            int tmpz;
            int tmpn;
            tmpz = this.m_izaehler * other.m_izaehler;
            tmpn = this.m_inenner * other.m_inenner;

            //return new Bruch(getZaehler(), getNenner());
            Bruch Hilfsbruch = new Bruch();
            Hilfsbruch = kuerze(tmpz, tmpn);

            return Hilfsbruch;
        }

        public Bruch get()
        {
            return (this);
        }

        public void set(int zaehler, int nenner)
        {
            if (nenner != 0)
            {
                m_izaehler = zaehler;
                m_inenner = nenner;
            }
        }
    }
    class Bruch2
    {
        static void Main(string[] args)
        {
            Bruch b1 = new Bruch();
            Bruch b2 = new Bruch();

            b1.set(12);
            b2.set(12);
        
            Bruch b3 = b1.multipliziere(b2);
            b3 = b1.get();
            System.Console.WriteLine(b3);
        }
    }
}


Mein Problem:
Die Get Methode -_-
Wie kann ich denn den ganzen Bruch wieder zurückgeben?
Ich hoffe mir kann jemand helfen :)

Liebe Grüße,
Felix

Moderiert von user profile iconTh69: Titel (leicht) geändert.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 21.09.13 11:32 
Zitat:
Die Get Methode -_-
Wie kann ich denn den ganzen Bruch wieder zurückgeben?


Was heißt das? Deine get Methode gibt sich selbst zurück und, da es ein Bruch Instanz ist, einen Bruch. Nach deiner Frage her macht die also genau das was du willst.
Da das aber Unsinn ist willst du vermutlich was anderes. Erklär das bitte genauer.

PS : Lass 'b3 = b1.get();' mal weg. So überschreibst du dir das Ergebnis das in b3 steckt wieder durch den Bruch in b1.


Zuletzt bearbeitet von Ralf Jansen am Sa 21.09.13 11:34, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 21.09.13 11:32 
Hallo und :welcome:

was genau erwartet du dir denn von der get-Methode?
Wenn es dir um die Ausgabe mittels der Console.WriteLine-Methode geht, dann mußt du dafür in der Bruch-Klasse die Methode ToString() überschreiben, z.B.:
ausblenden C#-Quelltext
1:
2:
3:
4:
public override string ToString()
{
  return "(" + m_izaehler + " / " + m_inenner + ")";
}
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Sa 21.09.13 11:34 
Hallo,
tut mir Leid dass du ein Problem hast. Zu einer präzisen Fehlerbeschreibung gehört aber:

1. Was sollte passieren? was passiert stattdessen?
2. Gibt es eine Fehlermeldung, oder tut der Code einfach "nichts"?
3. Hast du schon eine Ahnung woran es liegen könnte? (Diesen Punkt hast du erledigt)

Ich sehe da noch Verbesserungspotenzial in deiner Frage ;-)
Thund3rfury Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 21.09.13 11:42 
Hallo,

danke schonmal für die Antworten :)
Also der Lehrer meinte, wir müssen set und get benutzen, hat aber nichts dazu erklärt -_-
Das Problem liegt jetzt bei der Ausgabe.
Ich setze den Bruch mit der Set - Methode. Funktioniert super.
Berechne dann alles und Kürze dies. Funktioniert super.
Jetzt muss ich das Ergebnis ja irgendwie wieder in die Main Methode bekommen zur Ausgabe.
Da dachte ich, hol ich mir den Bruch mit der Get-Methode nach unten. Das Funktioniert leider nicht so wie ich will.

Viele Grüße,
Felix
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 21.09.13 11:48 
Das Ergebnis ist schon in b3 (kommt aus der multiplizieren Methode). Durch das überflüssige get hast du dir das nur wieder überschrieben.
Thund3rfury Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 21.09.13 11:52 
Alternativ hatte ich es so gemacht, das aber nicht gewollt war:

In der Bruch - Klasse:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
        public int getZaehler()
        {
            return this.m_izaehler;
        }

        public int getNenner()
        {
            return this.m_inenner;
        }

In der Main:
ausblenden C#-Quelltext
1:
2:
Bruch b3 = b1.multipliziere(b2);
System.Console.WriteLine("Multiplizieren: " + b3.getZaehler() + "/" + b3.getNenner());

Das ist ja einfach, da ich oben zwei int-Methoden hab, mit jeweils einem Rückgabewert.
Allerdings meinte der Lehrer, das wir dazu nur eine Get Methode benutzen sollen.
Genau da liegt das Problem, dass ich nicht weiß wie ich einen Bruch also 2 Zahlen returnen kann.
Ja das Ergebnis steht in b3, das is korrekt, habe ich auch gemerkt.
Aber da die Variablen oben protected sind, kann ich nicht über
ausblenden C#-Quelltext
1:
System.Console.WriteLine(b3.m_izaehler + "/" + b3.m_inenner) ausgeben					

Dazu brauche ich jetzt die get Methode. Mein Problem ich weiß nicht wie ich 2 Werte zurückgebe bzw. den Bruch.

Viel Grüße,
Felix
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 21.09.13 12:00 
Dann gib von der unbedingt gewünschten get Methode den zusammengesetzten string für die Ausgabe zurück. Also entsprechend der ToString Methode von user profile iconTh69. Wobei dann gesagt sein sollte die als ToString zu belassen sinnvoller ist. Aber es geht ja vermutlich darum das zu tun was der Lehrer will und nicht das was richtig ist.

Edit : Macht ein wenig Codekritik Sinn? Der funktioniert zwar enthält aber reichlich Balast und macht viele unnötige Dinge.
Thund3rfury Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 21.09.13 12:08 
Hallo und vielen Dank,
ja mit der toString Methode funktioniert es.
Und ich bitte um Codekritik, da ich mir das so zusammengeschrieben hab, sodass es funktioniert hat.
Ich bin um jede Hilfe dankbar, da ich es von Anfang an richtig machen möchte.

Viele Grüße,
Felix
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 21.09.13 12:43 
Zitat:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
public Bruch(int zaehler, int nenner)
{
    m_izaehler = 0;
    m_inenner = 1;
}

Der Constructor wird nicht benutzt und ist auch sinnlos. Wenn du den Feldern die übergebenen Parameter auch zuweist bekommt der Sinn.
Dann kannst du die überflüssigen "Bruch erzeugen und dann Set Methode aufrufen"-Codestellen durch einen Constructor aufruf ersetzen .
Also
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
Bruch b1 = new Bruch();
b1.set(12);

// nach

Bruch b1 = new Bruch(12);

Hier
Zitat:
ausblenden C#-Quelltext
1:
2:
Bruch Hilfsbruch = new Bruch();
Hilfsbruch = kuerze(tmpz, tmpn);

erzeugst du einen Bruch aber kuerze liefert dir schon eine neue Bruch instanz (in der Kuerze Methode ist ja auch ein new Bruch).
Du hast also einmal einen Bruch erzeugt denn du gar nicht benutzt sondern sofort wieder überschreibst.
Schreib einfach
ausblenden C#-Quelltext
1:
Bruch Hilfsbruch = kuerze(tmpz, tmpn);					



Dann noch ein paar Best Practices (Ignorier das wenn euer Lehrer will das ihr das so macht)

a.) Methodennamen und andere Member einer Klasse schreibt man in C# in Groß. Die meisten Entwickler die deinen Code sehen werden erstmal denken das ist Java bevor sie nach ein paar Sekunden die Kurve kriegen. Wenn du mal den von die benutzen Code aus dem Framework siehst z.B. Math.Abs sind die auch groß geschrieben.
b.) Auf interna einer anderen Klasseinstanz zuzugreifen ist ebenfalls verpönt. Wenn das aus gleichen Klassen heraus passiert geht das (eine Bruch Instanz schaut in eine andere Bruch Instanz) machen sollte man es trotzdem nicht. Ich würde dir empfehlen für nenner und zähler Properties zu veröffentlichen und nur über diese auf nenner und zähler zuzugreifen und nicht direkt auf die Felder wie du es z.B. in der multipliziere Methode machst mit other.m_izaehler. Wenn ihr Properties noch nicht hattet ignorier das.
c.) TypInformationen in Variablennamen unterbringen ist ein 80er und früher Phänomen und absolut nicht hilfreich lass das und gib den Variablen/Feldern einfach vernünftigen sprechenden Namen. Also z.b. in m_izaehler lass das i weg. Bei Klasseninternas (keiner ausserhalb der Klasse sieht das) verzeihlich aber bei veröffentlichten Dinge ärgerlich. Wenn du mal mit dem Code aus dem Framework vergleichst wirst du in keiner der zehntausenden Klassen eine finden die das macht.
d.) Variablen klein schreiben. Hilfsbruch1 -> hilfsbruch1. Und am besten die überflüssige 1 auch weglassen. Der Scope dieser Variablen ist nur die Methode es ist also egal das es in einer anderen Methode ebenfalls eine Variable gibt die so heißt. Es ist sogar hilfreich wenn Variablen die einen gleichen Sinn haben an anderen Stellen auch gleich benannt sind.
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Sa 21.09.13 12:44 
Okay, dann machen wir mal Codekritik :)

Ich persönlich hätte einen Bruch als struct implementiert. Weil andere Typen wie int etc. auch Wertetypen sind. Und natürlich immutable structs.
Aber nehmen mal die Klasse unter die Lupe:

ausblenden C#-Quelltext
1:
 public Bruch kuerze(int tmpz, int tmpn)					

Als public-Methode ganz grauslig. Man könnte schon erwarten, dass die Methode den Bruch selbst verändert/kürzt. Aber wofür braucht die dann noch Parameter? Und einen Rückgabewert?
Alternativ könnte man die Methode private und static machen.

ausblenden C#-Quelltext
1:
        public void set(int zaehler, int nenner)					

Würde sich bei einem immutable Design erübrigen. Außerdem gibt es ja bereits den Konstruktor mit Parametern. Aber halt:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
        public Bruch(int zaehler, int nenner)
        {
            m_izaehler = 0;
            m_inenner = 1;
        }
Aua. Der Konstruktor braucht Parameter, aber benutzt sie nicht???
Und:        public Bruch() { } Der Nenner bleibt also bei 0. Man muss direkt danach die set() Methode benutzen - umständlich!
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 21.09.13 13:42 
Zitat:
Man könnte schon erwarten, dass die Methode den Bruch selbst verändert/kürzt.


Könnte man ... klingt aber komisch wenn man im Satz vorher einen immutable Typ propagiert ;)

Edit: @Thund3rfury - ich vermute mal den Teil struct vs. class bzw. Referenztyp vs. Valuetyp hattet ihr noch nicht. Sollte sich eine Diskussion ergeben was geeigneter ist ignorier die ;) Es geht ja bei dir wahrscheinlich nicht darum wie man am besten einen Bruch implementiert sondern es geht darum andere Programmierkonzepte anhand des Beispiel eines Bruchs zu erlernen. Genauso wie Vergleiche honken Beispiele immer ;)
Thund3rfury Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 21.09.13 15:20 
Hallöchen nochmal ;)

hab mal versucht die Kuerzen-Methode als void umzuschreiben.
Er rechnet es richtig, verändert allerdings meine temporären Variablen tmpz und tmpn nicht, sodass das ungekürzte Ergebnis rauskommt:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bruch2
{
    public class Bruch
    {
        protected int m_izaehler;
        protected int m_inenner;

        public Bruch(int zaehler, int nenner)
        {
            m_izaehler = 0;
            m_inenner = 1;
        }

        public Bruch()
        { 
        
        }

        private void kuerze(int tmpz, int tmpn)
        {

            if (tmpz != 0)
            {
                int rest;
                int ggt = Math.Abs(tmpz);
                int divisor = Math.Abs(tmpn);
                do
                {
                    rest = ggt % divisor;
                    ggt = divisor;
                    divisor = rest;
                } while (rest > 0);
                tmpz = tmpz / ggt;
                tmpn = tmpn / ggt;
            }

        }

        public Bruch multipliziere(Bruch other)
        {
            int tmpz;
            int tmpn;
            tmpz = this.m_izaehler * other.m_izaehler;
            tmpn = this.m_inenner * other.m_inenner;

            kuerze(tmpz,tmpn);

            Bruch Hilfsbruch = new Bruch();
            Hilfsbruch.set(tmpz, tmpn);
            return Hilfsbruch; 
        }

        public void Ausgabe()
        {
            System.Console.WriteLine(m_izaehler + " / " + m_inenner);
        }

        public void set(int zaehler, int nenner)
        {
            if (nenner != 0)
            {
                m_izaehler = zaehler;
                m_inenner = nenner;
            }
        }
    }
    class Hauptprogramm
    {
        static void Main(string[] args)
        {
            Bruch b1 = new Bruch();
            Bruch b2 = new Bruch();

            b1.set(12);
            b2.set(12);

            Bruch b3 = b1.multipliziere(b2);
            b3.Ausgabe();


        }
    }
}


@ Ralf Jansen, Ja das ist richtig, wir sollen die Programmierkonzepte anhand des Beispiel eines Bruchs erlernen.
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Sa 21.09.13 17:00 
Zitat:
Könnte man ... klingt aber komisch wenn man im Satz vorher einen immutable Typ propagiert

Das war auch mehr so gemeint: "Man kann das ganze selbsverständlich auch mutable machen. In diesem Fall würde man jedoch erwarten, dass die Methode Kuerze() den Bruch verändert."
Und wenn das erlerenen von OOP das Ziel ist, brint es natürlich nicht viel auf structs umzusteigen - das leuchtet mir schon ein :P


Zum Thema: Man könnte entweder die Methode als Hilfsfunktion benutzten, die dann die Variablen direkt ändert: (ref Parameter bieten sich an)
(ref-Parameter beheben das Problem mit "verändert allerdings meine temporären Variablen tmpz und tmpn nicht" - sie werden dann verändert. Da das aber nicht immer gewünscht ist, muss man das explizit dranschreiben damit das funktioniert)

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
  private static void kuerze(ref int tmpz, ref int tmpn)
  {
    if (tmpz != 0)
    {
      int rest;
      int ggt = Math.Abs(tmpz);
      int divisor = Math.Abs(tmpn);
      do
      {
        rest = ggt % divisor;
        ggt = divisor;
        divisor = rest;
      } while (rest > 0);
      tmpz = tmpz / ggt;
      tmpn = tmpn / ggt;
    }
  }
  
  public Bruch multipliziere(Bruch other)
  {
    int tmpz = this.m_izaehler * other.m_izaehler;
    int tmpn = this.m_inenner * other.m_inenner;

    kuerze(ref tmpz, ref tmpn);

    Bruch Hilfsbruch = new Bruch();
    Hilfsbruch.set(tmpz, tmpn);
    return Hilfsbruch; 
  }

oder man kann hergehen und das Objekt verändern:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
  public void kuerze()
  {
    if (m_izaehler != 0)
    {
      int rest;
      int ggt = Math.Abs(m_izaehler);
      int divisor = Math.Abs(m_inenner);
      do
      {
        rest = ggt % divisor;
        ggt = divisor;
        divisor = rest;
      } while (rest > 0);
      m_izaehler = m_izaehler / ggt;
      m_inenner = m_inenner / ggt;
    }
  }

  public Bruch multipliziere(Bruch other)
  {
    int tmpz = this.m_izaehler * other.m_izaehler;
    int tmpn = this.m_inenner * other.m_inenner;

    Bruch Hilfsbruch = new Bruch();
    Hilfsbruch.set(tmpz, tmpn);
    Hilfsbruch.kuerze();
    return Hilfsbruch; 
  }


Wafür man sich letztlich entscheidet ist momentan wohl egal. Vielleicht hattet ihr noch keine ref Parameter (?) oder später soll der Bruch auch "auf Befehl" gekürzt werden können - in diesen FRällen wäre Lösung #2 besser.

Unabhängig davon bleibt die Sache mit dem Konstruktor! Der eine macht nix, der andere macht's falsch :?