Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
> Das (glaube ich) einzige Problem ist, dass wenn ein zweites Zeichen gedrückt wurde er zwar rechnen
> aber das Ergebnis nicht ins Anzeigefeld schreibt. Warum verstehe ich nicht.
welche Situation meinst du genau? wenn man 1 drückt und dann nochmal 1, dann steht 11 im Feld,
dann soll bestimmt noch nicht gerechnet werden,
also vielleicht genauer beschreiben was du meinst
mir sind da einige Sachen aufgefallen die da nicht allzu gut klappen,
etwa wenn man 2x hintereinader auf * klickt, dann wird das erste * als erste Zahl genommen -> Exception
(schaust du dir auch nebenbei die Fehlerausgaben an der Konsole an?)
oder wenn man ewig weit rechnet und dann irgendwann Infinty steht für Unendlich und man wieder auf Zahlen drückt,
dann steht da sowas wie Infinty687,
also da gibts genug Ecken wo man dran feilen kann
--------------
viel wichtiger: das Programm ist ja absolut unstrukturiert geschrieben, überall Wiederholung,
bei sowas schleichen sich immer Fehler ein, wenn du mal irgendwas ändern willst musst du gleich an x Stellen gleichzeitig ändern usw..
erstes Beispiel:
die rechnen-Operation,
da wird doch einfach nur 5x das gleiche gemacht, das geht auch viel kürzer
sehr viel schöner, sauberer und auch nicht schwerer zu programmieren?
übrigens fällt auf dass du in deiner rechnen()-Operation bei Math.pow
statt der public Klassenvariabe ergebnis lieber eine lokale Variable result genommen hast,
war das Absicht oder bei einer Änderung vergessen? sowas wär dann ein geniales
Beispiel für einen später mal sehr schwer zu findenen Fehler
mit der kompakten Schreibweise vermeidest du das (eher als in der langen),
da sieht man besser ob ergebnis oder result verwendet wird
-------------
nächstes Beispiel die 10 Zahlen,
da ein Attay zu verwenden spart jede Menge Zeilen,
bei der Anordnung der Buttons hat man ein paar Schwierigkeiten, aber geht auch
statt
Code:
btEins = new Button("1");
btEins.setBounds (20,140,25,25);
pnFenster.add(btEins);
btZwei = new Button("2");
btZwei.setBounds (55,140,25,25);
pnFenster.add(btZwei);
btDrei = new Button("3");
btDrei.setBounds (90,140,25,25);
pnFenster.add(btDrei);
btVier = new Button("4");
btVier.setBounds (20,105,25,25);
pnFenster.add(btVier);
btFuenf = new Button("5");
btFuenf.setBounds (55,105,25,25);
pnFenster.add(btFuenf);
btSechs = new Button("6");
btSechs.setBounds (90,105,25,25);
pnFenster.add(btSechs);
btSieben = new Button("7");
btSieben.setBounds (20,70,25,25);
pnFenster.add(btSieben);
btAcht = new Button("8");
btAcht.setBounds (55,70,25,25);
pnFenster.add(btAcht);
btNeun = new Button("9");
btNeun.setBounds (90,70,25,25);
pnFenster.add(btNeun);
da muss man natürlich bisschen rechnen, für das Feld 0 mit seiner Sonderposition muss
sowieso ne Extrabehandlung kommen, aber wenn du z.B. alle Felder um 5 Pixel nach rechts verschieben
oder den Abstand ändern willst, musst du bei dieser Schreibweise nur 2x statt 10x etwas ändern..
----------
wieso überhaupt AWT-Buttons und nicht Swing-JButtons? das kann irgendwann mal ins Auge
gehen wenn man diese Komponenten mischt,
normalerweise reicht einfach überall JButton statt Button zu schreiben,
allerdings haben die eine etwas andere Größe, so dass du dein Layout ändern müsstest
(Buttons größer, Abstand größer), deshalb vielleicht nicht angebracht
----------------
in der actionPerformed kann man am meisten sparen,
für die Zahlfelder ist es mit dem Array schon sehr einfach
auch bei den fünf Rechnungen steht praktisch fünf mal die gleichen 15 Zeilen,
nur mit + statt - oder * statt /,
da müssen doch die Alarmgocken klingelt!
hier kann man auch ein Array verwenden, dass vom Button auf das Zeichen mappt und
dann reicht eine Schleife aus,
die Zeilen
String zwischen = tfAnzeige.getText();
xZahl = Double.parseDouble(zwischen);
stehen 11x in der actionPerformed, wenn man die Rechnenbutton kürzt, dann noch 3x,
immer noch zu viel da ja wie anfangs beschrieben alles mögliche in der Eingabe steht
und damit auch Exceptions auftreten können
(zumindest solange bis du das Programm entsprechend angepasst hast)
dann ist es günstig 1x den String zu lesen und in ein double umzuwandeln
und danach nur noch die Zahl zu verwenden
ein Problem dabei: es gibt auch Situationen in denen es zur Exception kommen
kann obwohl alles in Ordnung ist, z.B. am Anfang, leeres Textfeld,
dann gehts das ganze nicht so einfach, in diesem Fall hilft ein Trick:
am Anfang alle anderen Buttons bearbeiten die damit nix zu tun haben
und mit return die Operation verlassen,
und erst weiter hinten vor den Buttons die sowieso alle den
Double.parseDouble()-Befehl ausführen würden einmal vorne weg parsen
---------
um Strings zu vergleichen besser equals statt == nehmen! (Vorsicht bei null-Werten)
--------
wenn sich Ereignisse gegenseitig ausschließen, dann statt
if {
}
if {
}
if {
}
besser
if {
} else if {
} else if {
}
verwenden, so werde nach evtl. erfolgreicher Bearbeitung des ersten Falles nicht mehr die
anderen Bedingungen unnötig geprüft
---------
naja usw., alles Tipps die dir vielleicht gut weiterhelfen,
wenn du nicht alle verstehst oder gar anwenden willst ist das nicht schlimm
aber mit einigen einfachen Mitteln läßt sich der Quellcode locker von 300 auf 200 Zeilen kürzen,
viel mehr wäre bestimmt noch möglich, aber allzu kryptisch muss es ja auch nicht werden
Code:
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
/**
* Einfacher (!) Taschenrechner
*
* @version 0.99 vom 5.1.2006
* @autor xyz
*/
class TaschenrechnerGUI extends JPanel implements ActionListener {
private JFrame fenster;
private JPanel pnFenster;
private JLabel tfAnzeige;
private Button[] btZahl = new Button[10];
private Button btPlus = new Button("+");
private Button btMinus = new Button("-");;
private Button btMal = new Button("*");;
private Button btGeteilt = new Button("/");;
private Button btHoch = new Button("^");;
private Button btPunkt;
private Button btGleich;
private Button btBack;
private Button btReset;
private Object[][] btRech = {
{btPlus ,"+"},
{btMinus ,"-"},
{btMal ,"*"},
{btGeteilt ,"/"},
{btHoch ,"^"} };
public String neueZiffer;
public String zeichen;
public int zeichenEingegeben;
public int bedingung;
public double ersteZahl;
public double zweiteZahl;
public double ergebnis;
public TaschenrechnerGUI() {
erzeugeFenster();
}
public void erzeugeFenster() {
fenster = new JFrame("Einfacher Taschenrechner");
//Anlegen des Inhaltsbereiches
pnFenster = (JPanel) fenster.getContentPane();
fenster.setSize(180, 285);
pnFenster.setLayout(null);
fenster.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
pnFenster.setBackground(Color.black);
tfAnzeige = new JLabel();
tfAnzeige.setBounds(20, 20, 130, 20);
tfAnzeige.setBackground(Color.white);
tfAnzeige.setHorizontalAlignment(SwingConstants.RIGHT);
tfAnzeige.setOpaque(true);
pnFenster.add(tfAnzeige);
for (int i=1; i<10; i++) {
btZahl[i] = new Button(""+i);
btZahl[i].setBounds(20 + 35*((i-1) % 3), 140 - ((i-1)/3)*35, 25, 25);
btZahl[i].addActionListener(this);
pnFenster.add(btZahl[i]);
}
btZahl[0] = new Button("0");
btZahl[0].setBounds(20, 175, 25, 25);
btZahl[0].addActionListener(this);
pnFenster.add(btZahl[0]);
btPlus.setBounds(125, 175, 25, 25);
pnFenster.add(btPlus);
btMinus.setBounds(125, 140, 25, 25);
pnFenster.add(btMinus);
btMal.setBounds(125, 105, 25, 25);
pnFenster.add(btMal);
btGeteilt.setBounds(125, 70, 25, 25);
pnFenster.add(btGeteilt);
btGleich = new Button("=");
btGleich.setBounds(90, 210, 60, 25);
pnFenster.add(btGleich);
btPunkt = new Button(".");
btPunkt.setBounds(55, 175, 25, 25);
pnFenster.add(btPunkt);
btHoch.setBounds(90, 175, 25, 25);
pnFenster.add(btHoch);
btReset = new Button("C");
btReset.setBounds(55, 210, 25, 25);
pnFenster.add(btReset);
btBack = new Button("Del");
btBack.setBounds(20, 210, 25, 25);
pnFenster.add(btBack);
fenster.setVisible(true);
btPlus.addActionListener(this);
btMinus.addActionListener(this);
btMal.addActionListener(this);
btGeteilt.addActionListener(this);
btGleich.addActionListener(this);
btPunkt.addActionListener(this);
btHoch.addActionListener(this);
btReset.addActionListener(this);
btBack.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
for (int i=0; i<10; i++) {
if (e.getSource() == btZahl[i]) {
dazuSchreiben(""+i);
return;
}
}
if (e.getSource() == btPunkt) {
String zeichen = ".";
tfAnzeige.setText(tfAnzeige.getText() + zeichen);
// wieso nicht dazuSchreiben("."); ?
return;
} else if (e.getSource() == btReset) {
tfAnzeige.setText("");
ersteZahl = 0;
zweiteZahl = 0;
return;
} else if (e.getSource() == btBack) {
String text = tfAnzeige.getText();
tfAnzeige.setText(text.substring(0, text.length() - 1));
// Vorsicht wenn leerer ext im Textfeld, besser
//if (text.length() > 0) {
// tfAnzeige.setText(text.substring(0, text.length() - 1));
//}
return;
}
String zwischen = tfAnzeige.getText();
double newZahl = 0;
try {
newZahl = Double.parseDouble(zwischen);
} catch (Exception ex) {
System.out.println("Exception beim Parsen der Zahl aus AnzeigeFeld: "+
("".equals(zwischen) ? "(leer)" : "zwischen"));
return;
}
for (int i=0; i<btRech.length; i++) {
if (e.getSource() == btRech[i][0]) {
bedingung++;
if (bedingung == 2) {
zweiteZahl = newZahl;
rechnen();
}
zeichen = (String) btRech[i][1];
zeichenEingegeben = 1;
if (bedingung <= 1) {
ersteZahl = newZahl;
tfAnzeige.setText(zeichen);
}
return;
}
}
if (e.getSource() == btGleich) {
zweiteZahl = newZahl;
rechnen();
}
}
public void dazuSchreiben(String neueZiffer) {
if (zeichenEingegeben == 1) {
tfAnzeige.setText(neueZiffer);
zeichenEingegeben = 0;
} else
tfAnzeige.setText(tfAnzeige.getText() + neueZiffer);
}
public void rechnen() {
if ("+".equals(zeichen)) {
ergebnis = ersteZahl + zweiteZahl;
} else if ("-".equals(zeichen)) {
ergebnis = ersteZahl - zweiteZahl;
} else if ("*".equals(zeichen)) {
ergebnis = ersteZahl * zweiteZahl;
} else if ("/".equals(zeichen)) {
ergebnis = ersteZahl / zweiteZahl;
} else if ("^".equals(zeichen)) {
ergebnis = Math.pow(ersteZahl, zweiteZahl);
} else {
System.out.println("unerwartetes Zeichen in rechnen: "+zeichen);
}
String endergebnis = String.valueOf(ergebnis);
tfAnzeige.setText(endergebnis);
bedingung = 0;
ersteZahl = Double.parseDouble(endergebnis);
}
public static void main(String[] args) {
new TaschenrechnerGUI();
}
}
xO Oh man so ne geballte Fachkompetenz hat mich jetzt erst mal über den Haufen gehauen^^ .
Also ich hab das jetzt erst mal überflogen und wirklich nicht alles verstanden aber trotzdem danke ;-)
Ich weiß ja das noch viele Fehler bei bestimmten Kombinationen drin sind...nur hab halt überhaupt keine Erfahrung wie man die alle findet und rausbekommt. Eigentlich habe ich überhaupt keine Erfahrung, da ich mich letzten Mittwoch das erste mal mit Java befasst habe^^
Da ja beim Quelletxt von Andre (danke nochmal!) keine Fehler drin sind(?) werde ich wohl den nehmen...
Fehler sind da wohl weniger drin, aber ein paar auch noch,
etwa ne Exception wenn man anfangs auf Entfernen drückt
(wie man das lösen kann siehe actionPerformed von mir gepostet)
wenn man ne sehr große Zahl hat oder durch 0 teilt wird ein Text angezeigt (Infinity bzw. NaN)
an den man noch weitere Zahlen anhängen kann (NaN53) und der bei weiteren Rechnungen Exceptions auslöst
also noch ziemlich das gleiche nur dass es keinen Fehler mehr gibt wenn man 2 Rechenzeichen hintereinander drückt,
also schon durchaus ne Verbesserung
Wenn Chili's Lehrer ein perfektes Programm vorfindet, wird da nicht misstrauisch werden?
Ich denke schon. Hausaufgabenhilfe bedeutet für mich nicht eine möglichst perfekte Lösung anzustreben,
sondern dem Schüler da zu helfen wo er Schwierigkeiten sieht :wink:
klingt so als traust du mir was anderes zu
ich versuche auch nur zu helfen
und die Erkenntnis 10 gleiche Zeilen durch eine Schleife zu ersetzen ist viel wichtiger
als was jetzt im Taschenrechner so zu tun ist, (nur meine Meinung)
deswegen mal von mir ein Beispiel worum man sich eigentlich in dem Programm kümmern sollte
natürlich bin ich da teilweise etwas weit vorgeprescht, die Vorlage bot das aber auch zu schön an
Hi Leute...
Also SlaterB du hast ja an Andres Programm 2 Sachen auszusetzten.
Dazu das wenn man ne sehr goße Zahl durch 0 teilt dann son Text kommt kann ich nur folgendes sagen: Das passiert wenn jede beliebige Zahl (auch 2 oder sowas kleines) durch 0 teilt. Durch 0 teilen geht nun mal nicht. Ist mathematisch nicht definiert. Da wird dir jeder "professionelle" Taschenrechner den man im Laden kaufen kann einen Fehler anzeigen... Das kleine Problemchen dabei sind dann die Folgen für die nächsten Rechnungen. Kann man das denn irgendwie vermeiden, also dass dieser Text direkt rausgelöscht wird oder so?
Und das andere, wenn man Anfnfangs auf "Del" drückt, dass dann ne exception kommt ist ja nachzuvollziehen (wie soll man wo nix steht noch ein Zeichen wegnehmen) aber deine Lösung verstehe ich nicht. Also ich blicke einfach nicht durch ums mal so zu sagen...
die Exception kommt weil du von einem String der Länge 0 ein Zeichen wegnehmen willst
durch substring(0,-1)
wie kann da mein Tipp 'bei Länge 0 NICHT ein Zeichen wegnehmen' unverständlich sein?
das bedeutet doch ganz einfach dass die Del-Taste nur dann was tut wenn auch was da ist,
ist nix da so tut die Taste nix und löst damit auch keine Exception aus
--------
zu dem anderen Problem:
das ist ja grundsätzlich in dem Programm so eingestellt,
wenn man 10 * 2 nimmt kommt 20 raus, wenn man dann noch 3 drückt steht da 203,
da würde ich eher die allgemeine Funktionalität jedes Taschenrechners empfehlen:
wenn man nach einem Ergebnis ne neue Zahl drück verschwindet das alte Ergebnis,
das Löschen an sich ist ja kein Problem, du müsstest dir nur diesen besonderen Zustand merken
(nach Gleichheitstaste im Zustand 'ergebnisanzeigen') und bei einer Zahleingabe immer abfragen ob gerade dieser Zustand ist (dann Löschen und neu eingeben) oder nicht (dann wie bisher),
nach Druch der nächsten Taste ist der Zustand auf jeden Fall weg, nicht vergessen
naja usw. das ist doch genau wie bisher, immer überlegen was wann auf welchen Tastendruck passiert
Bzw. ich hab mir grad nochmal überlegt...das ist ja gar nicht so schlimm mit Problem 2). Wenn man mit genau dem Ergebnis weiter rechnen will kann man ja einfach ein Rechenzeichen eingeben und ne neue Zahl und so weiter oder man kann das Ergebnis verändern wenn man möchte. Und falls man nach einer Rechnung ne komplett neue Rechnung beginnen möchte drückte man halt Reset (C).
Wenn man das verändert kann man ja gar nicht mehr mit dem Zwischenergebnis weiterrechnen und es wär ja wie vorher vor den ganzen Änderungen.
Also das will ich wirklich nicht veräandern aus den oben genannten Gründen.
Aber du hattest noch folgendes geschrieben:
"...wird ein Text angezeigt (Infinity bzw. NaN)
an den man noch weitere Zahlen anhängen kann (NaN53) und der bei weiteren Rechnungen Exceptions auslöst..."
Das würde ich gerne noch ändern. Also sozusagen irgendwo einbauen, dass wenn im Textfeld infinity oder nan steht, dass dann die nächste Zahl das praktisch überschreibt...naja guck ich morgen ma bin jetzt echt zu platt...
tja und nu, gar keine Idee wie man da vorgehen könnte?
-> vor der Abfrage den Text im Textfeld ausgeben, evtl. noch mit | dvor und | dahinten um zu schauen ob vielleicht ein Leerzeichen oder so dabei ist,
ist aber alles ok und woran lags: Tippfehler , hab ich ja auch schon im vorherigen Post falsch getippt,
Infinity statt Infintiy
Oh ja...klar...
Mhh jetzt bin ich dabei die Kommentare zu schreiben...ich lick zwar so einigermaßen durch aber nicht komplett...evtl meld ich mich gleich nochmal