View Full Version : [Frage] Unterschiede: schlechtes/gutes Programm?!
@
da stimm ich dir voll und ganz zu
nur wo und wie sollen programmieranfänger lernen, wie sie an ein programm herangehen sollen und lösungsansätze entwickelt?
Bin ja selber Programmieranfängerin. Kann da ja nur aus Erfahrung sprechen.
Allein schon die Runde 2, die ich heute endlich mal abgegeben habe, war für mich ein Hammer. Programme zu bewerten, wenn man nicht einmal weiß, welche Kriterien gute Programme haben müssen. Habe dann als Hilfe Abgabefiles von anderen Studenten zur zweiten Runde studiert und mir vor allem angeschaut, an was die sich so bei einer Beurteilung orientieren. Hat doch geholfen. Aber dadurch sind noch mehr Fragen in mir aufgekommen. Habe Fragen und suche nun die entsprechenden Antworten.
was aber meiner meinung nach programmieranfängern oft fehlt, ist die denkweise, wie man an das problem herangeht (was oft gar nichts mit programmieren zu tun hat, sondern eher mit geordnetem und kreativem denken).
:rolleyes: Wie schaut bitte ein gutes gelungenes Programm aus und wie schaut eine Arbeit aus, die eher durch ein geordnetes und kreatives Denken zustande gekommen ist?
Ist ein Programm dann als gut anzusehen, wenn es
1.) aus vielen If-Else Abfragen, for und do while-Schleifen besteht
oder
2.) aus vielen Methoden aufgebaut ist.
Hab im Attachment zwei Programme aus meiner ehemaligen zweiten Runde+Spezifakation ubgeloaded. Beispielsname: Silbentrennung
Das erste Programm ernährt sich hauptsächlich von Schleifen
das andere von Methoden.
Würde man solche Programme zur Kategorie << als gelungen>> geben, oder in die "Naja-Es-Wird-Schon-Abteilung deponieren. Und wenn das letztere zutrifft, wie hätte man das besser bewältigen können?
:confused: Ferner wäre mal gut den Begriff der >>Verwendbarkeit eines Programmes<<zu klären. So trivial auch die Frage klingt: Versteht man unter Verwendbarkeit, wie gut es sich als Teil in einem größeren Programm integrieren lässt. Was sind die Parameter, die Kriterien dafür?
:rolleyes: Warum ist es gut für die Verwendbarkeit eines Programmes, dass man so viele Operationen wie möglich in Methoden ausarbeitet?
:confused: Warum ist es für die Verwendbarkeit eines Programmes gut, dass die Methode println so wenig wie möglich aufgerufen wird? Im ersten Programm wird println viermal aufgerufen, im zweiten nur einmal. Heißt das, dass die erste Arbeit schlechter ist als die zweite?
:rolleyes: Warum ist es für die Verwendbarkeit eines Programmes gut, dass so wenig Fehlermeldungen als möglich auftreten? In den zwei Arbeiten treten ja viele Fehlermeldungen in Form von >>return false<< oder >>richtigeEingabe = false<<.
:confused: Warum ist es für die Verwendbarkeit eines Programmes gut, dass Eingabe und Ausgabe vom restlichen Code getrennt sind. Wie schaut das eigentlich aus, wenn Ein- und Ausgabe vom restlichen Code getrennt sind.
In den zwei Programmen ist es doch nicht der Fall, oder?
:rolleyes:Übrigens würde ich gerne erfahren, ob es geschickt ist in einem Programm den Try-catch (Exception e)-Block zu verwenden, so wie es in der ersten Arbeit gemacht wurde. Die Exception hat ja die Funktion im Falle einer Fehlermeldung das Programm abzubrechen. Na gut im zweiten Programm ist ja kein Try-catch Block und da wird das Programm ohne weiteres bei >>Falsche Eingabe<< abgebrochen.
:confused:Nich zuletzt ist gut zu wissen, wie es mit Aufbau, Form und Struktur in den beiden Programmen ausschaut? Ist das so wie es ist akzeptabel? Ist die Spezifikation wirklich in meinen Beispielen auf schnelle, unkomplizierte Weise gelöst.
Wenn du beim Programmieren ein Problem hast, kannst du es ins Forum posten, und jeder, der das Beispiel auch hat, kann seine Lösungsansätze posten. Der Vorteil ist hier, dass auch Informatiker, die z.B. voriges Jahr EPROG gemacht haben, auch ihre Erfahrungen mit dem Beispiel posten können oder zur Lösung des Problems beitragen.
:thumb:Ich würde da unheimlich die Meinung von anderen zu hören, besonders von doch schon etwas erfahreren Programmierern?
aber sich selbst eine programmiersprache oder programmieren an sich beizubringen, sprich alles aus einem oder besser mehreren büchern zu lernen, das ist wohl gerade bei dieser materie sauschwer,... Darum wäre das für mich doch sehr profitabel, wenn sich da jemand mal kurz die Zeit nimmt, und wenn er auch nur die zwei Programme überfliegt und dann mir sein Statement abliefert, mit dem hoffentlich einige meiner Fragen beantwortet werden.
Lg.,
Silvia
Plantschkuh!
25-12-2004, 23:37
:rolleyes: Wie schaut bitte ein gutes gelungenes Programm aus und wie schaut eine Arbeit aus, die eher durch ein geordnetes und kreatives Denken zustande gekommen ist?
Naja, es schaut geordnet und kreativ aus ;) Man kann das nicht so leicht beschreiben, viele Leute sagen deswegen auch, daß Programmieren eine Knust ist.
Auf jeden Fall sollte es lesbar und verständlich sein, klar gegliedert, gleicher Code sollte sich nicht an mehreren Stellen wiederholen (das ist nicht immer möglich, aber oft). Und aussagekräftig kommentiert. Und sicher noch viel mehr, was mir jetzt nicht so einfällt.
:confused: Ferner wäre mal gut den Begriff der >>Verwendbarkeit eines Programmes<<zu klären. So trivial auch die Frage klingt: Versteht man unter Verwendbarkeit, wie gut es sich als Teil in einem größeren Programm integrieren lässt. Was sind die Parameter, die Kriterien dafür?
Ja, das versteht man darunter, und generell auch die Wiederverwendung, d.h. die Verwendung eines bestehenden Programmstücks in einem ganz neuen Programm. Aber nicht unbedingt das ganze Programm, auch einzelne Klassen oder Methoden sollten so geschrieben sein, daß man sie wiederverwenden kann.
Daß bedeutet unter anderem, daß du die Kopplung nach außen minimieren solltest; das Restprogramm sollte auf die Daten deiner Klasse nur über klar definierte Interfaces mit get- und set-Methoden zugreifen können, nicht über public-Variablen oder sowas. Variable, die nur innerhalb einer Methoder verwendet werden, sollten auch nur in dieser deklariert werden und nicht als Variablen in der Klasse. static-Variablen und -Methoden sollten nur zum Einsatz kommen, wo das unbedingt nötig ist.
Es bedeutet auch, daß du möglichst allgemein programmieren solltest: Wenn dein Programm eine Funktion berechnen soll, du aber weißt, daß sie nur mit Werten aus dem Bereich {0, ..., 100} aufgerufen wird, schreib die Funktion trotzdem so, daß sie für alle Zahlen funktioniert; vielleicht wird der Bereich der zulässigen Werte irgendwann vergrößert.
:rolleyes: Warum ist es gut für die Verwendbarkeit eines Programmes, dass man so viele Operationen wie möglich in Methoden ausarbeitet?
Eben weil du dann die Methode einfach nur aufrufen oder kopieren mußt, wenn du in einem anderen Programm die gleiche Funktionalität wieder brauchst. Die Formulierung "so viele wie möglich" sollte aber durch "so viele wie sinnvoll" ersetzt werden, aber das ist wiederum eine Frage der Erfahrung, was man als sinnvoll erkennt und was nicht.
:confused: Warum ist es für die Verwendbarkeit eines Programmes gut, dass Eingabe und Ausgabe vom restlichen Code getrennt sind.
Wenn du Ein- und Ausgabe jeweils nur an einer Stelle hast, sind Änderungen leicher möglich: Vielleicht soll das Programm irgendwann die Meldungen in einer anderen Sprache oder sonstwie in einer anderen Form ausgeben. Wenn du das an einer Stelle konzentriert hast, kannst du sowas sauberer ändern, als wenn du über das ganze Programm verstreute Aufrufe von println suchen und ersetzen mußt.
Und die Wiederverwendbarkeit spielt hier auch eine Rolle: Angenommen, du schreibst ein Programm zur Berechnung von Knusperflocken. Ich find das Programm extrem cool und borg mir den Code einer Funktion aus, die ich für besonders gelungen halte. Dann möchte ich nicht, daß dein Programm das Terminal meines Users mit Meldungen wie "17 Knusperflocken im Anflug" vollschreibt, wenn es bei mir um Buchhaltung geht :)
Die Exception hat ja die Funktion im Falle einer Fehlermeldung das Programm abzubrechen
Nein, hat sie nicht. Man kann sie auch für sowas verwenden, aber Exceptions sind viel allgemeiner: Sie signalisieren einen Ausnahmezustand, normalerweise einen Fehler, der "üblicherweise" nicht auftritt, sondern nur in "Ausnahmefällen", wenn der Benutzer zum Beispiel sein Keyboard auffrißt oder wenn der Rechner keinen Speicher mehr hat oder die Netzverbindung plötzlich abreißt oder sowas.
Deine Programme hab ich mir jetzt (noch?) nicht angeschaut, aber ich hoffe, daß dir diese Kommentare mal ein bissi weiterhelfen. Nur nicht entmutigen lassen, und üben, üben, üben, ... :thumb:
Ich bin auch Programmieranfänger und hab mich so ziemlich die gleichen Sachen gefragt wie du - Im Endeffekt hab ich dann halt "irgendeine" Bewertung abgegeben; Ich hab einfach das bewertet, was ich auch beurteilen konnte (Ist das Programm gut erklärt? Sind die variablennamen eindeutig? Würde das Programm bei einer etwas abgeänderten bzw. etwas komplexeren Aufgabenstellung wesentlich länger werden? Reagiert es auch auf außergewöhnliche Eingaben korrekt?...)
Ich denke aber, dass das nicht so wichtig ist, da die Beispiele eh von einem Computer bewertet werden. Dem sind die Reviews so ziemlich egal. - Ich hab jedenfalls auch so alle Punkte bekommen. Mach dir daher lieber nicht zu viele Gedanken zu Runde 2 und gib sie einfach ab; die Zeit solltest du besser in die nächsten Runden investieren (die Bewertung geht ja nur bis 17.1. oder?)
Wie schaut bitte ein gutes gelungenes Programm aus und wie schaut eine Arbeit aus, die eher durch ein geordnetes und kreatives Denken zustande gekommen ist?... Ich hab das so verstanden, dass geordnetes und kreatives Denken eine Voraussetzung für gutes Programmieren ist und kein Gegensatz ;) .
Lg Vench
Ist ein Programm dann als gut anzusehen, wenn es
1.) aus vielen If-Else Abfragen, for und do while-Schleifen besteht
oder
2.) aus vielen Methoden aufgebaut ist.
Es geht darum ein Problem in seine Teile zu zerlegen und diese sinnvoll zu strukturieren. Dein Ansatz mit den zahlreichen if-Abfragen ist eindeutig schlecht strukturiert, ist eine lange Wurst Code an deren Ende ich bereits vergessen habe, worum es am Anfang ging.
Zur Strukturierung eines Programmes sind Methoden (sowie Klassen und Packages) der richtige Weg. Methoden haben einen Namen, haben Übergabeparameter und Rückgabewerte. Benennt man diese sinnvoll, so wird das Programm leichter lesbar.
Ein Beispiel anhand einiger Zeilen Code:
import eprog.EprogIO;
public class Verifier {
public static boolean isCharacterValid(char c) {
// hier sollte die Überprüfung des Characters stehen
}
public static boolean isStringValid(String s) {
// alle Zeichen im String einzeln überprüfen
for (int i = 0; i < s.length(); i++) {
if (!isCharacterValid(s.charAt(i))) {
return false;
}
}
// wurden alle Zeichen überprüft und keine ungültigen gefunden,
// ist der String gültig
return true;
}
public static void main(String args[]) {
String input = EprogIO.readWord();
if (isStringValid(input)) {
EprogIO.println("Input is valid.");
} else {
EprogIO.println("Input is invalid.");
}
}
}
Das Programm soll überprüfen, ob ein String gültig ist, genau gesagt ob er keine ungültigen Zeichen enthält.
Wir beginnen zu lesen, wo jedes Programm startet: In der Methode main. Dort sind nur einige Zeilen Code, die anhand des sprechenden Methodennamens auch leicht gelesen werden können: Zuerst lesen wir einen String ein, und dann geben wir - je nachdem, ob der String ok ist oder nicht, eine entsprechende Meldung aus.
Wer sich für Details interessiert liest nun in der Methode "isStringValid" nach und sieht, dass diese Zeichen für Zeichen den String durchläuft und überprüft, ob alle Zeichen gültig sind - durch Aufruf der Methode isCharacterValid. Wohlgemerkt muss man nicht vorher isCharacterValid gelesen und verstanden haben. Alleine der Name der Methode hilft mir ihre Aufgabe zu verstehen. Natürlich können Namen auch irre führen, verlassen kann man sich nicht immer darauf. In diesem Fall erhalte ich aber auch in dieser Methode genau soviel Informationen wie nötig sind um sie zu verstehen.
Im besten Fall verseht man die Köpfe der Methoden noch mit einer Beschreibung ihrer Aufgabe. So kann jeder Leser Aufgabe und Ablauf des Programms schnell erfassen.
Und nun stell dir das ganze in einer Methode vor - eindeutig schwerer lesbar.
Würde man solche Programme zur Kategorie << als gelungen>> geben, oder in die "Naja-Es-Wird-Schon-Abteilung deponieren. Und wenn das letztere zutrifft, wie hätte man das besser bewältigen können?
Gelungen ist was anderes, du bist jedoch Anfänger und entsprechend sieht dein Programm aus. Das gute ist, dass du Fragen stellst, nur so wirst du auch besser.
:confused: Ferner wäre mal gut den Begriff der >>Verwendbarkeit eines Programmes<<zu klären. So trivial auch die Frage klingt: Versteht man unter Verwendbarkeit, wie gut es sich als Teil in einem größeren Programm integrieren lässt. Was sind die Parameter, die Kriterien dafür?
Du meinst in Eprog? Puh. Allgemein ist die Qualität eines Programms von mehreren Faktoren abhängig: Robustheit, Laufzeit, Modularität, Lesbarkeit ... (das steht sicher in einem schlauen Lehrbuch genauer). Die Laufzeit fällt bei den kleinen Eprog-Programmen selten ins Gewicht, hier zählt vor allem wie Robust (fehlerfrei) der Code ist, und wie gut er sich in dein Programm integrieren lässt, was von der Modularität abhängt.
:rolleyes: Warum ist es gut für die Verwendbarkeit eines Programmes, dass man so viele Operationen wie möglich in Methoden ausarbeitet?
Wer sagt das? Dieser Ansatz erhöht vielleicht die Laufzeit, da Methodenaufrufe vermieden werden, verringert jedoch die Lesbarkeit, ist fehleranfälliger (weil unübersichtlich), und schlecht wiederverwendbar.
:confused: Warum ist es für die Verwendbarkeit eines Programmes gut, dass die Methode println so wenig wie möglich aufgerufen wird? Im ersten Programm wird println viermal aufgerufen, im zweiten nur einmal. Heißt das, dass die erste Arbeit schlechter ist als die zweite?
Grundsätzlich gilt es, keinen Code doppelt zu schreiben. Das gilt auch für die Ausgabe. Um dies zu vermeiden verwendet man auch Methoden.
:rolleyes: Warum ist es für die Verwendbarkeit eines Programmes gut, dass so wenig Fehlermeldungen als möglich auftreten? In den zwei Arbeiten treten ja viele Fehlermeldungen in Form von >>return false<< oder >>richtigeEingabe = false<<.
Ganz einfach: Es sollen genau so viel Fehlermeldungen auftreten wie nötig.
:confused: Warum ist es für die Verwendbarkeit eines Programmes gut, dass Eingabe und Ausgabe vom restlichen Code getrennt sind. Wie schaut das eigentlich aus, wenn Ein- und Ausgabe vom restlichen Code getrennt sind.
In den zwei Programmen ist es doch nicht der Fall, oder?
Wenn du die Ein- und Ausgabe von der eigentlichen Programmlogik entkoppelst kannst du leichter die Benutzerschnittstelle austauschen - zum Beispiel von der Kommandozeile zur Swing-Applikation (bunte Fenster).
:rolleyes:Übrigens würde ich gerne erfahren, ob es geschickt ist in einem Programm den Try-catch (Exception e)-Block zu verwenden, so wie es in der ersten Arbeit gemacht wurde. Die Exception hat ja die Funktion im Falle einer Fehlermeldung das Programm abzubrechen. Na gut im zweiten Programm ist ja kein Try-catch Block und da wird das Programm ohne weiteres bei >>Falsche Eingabe<< abgebrochen.
boolean-Variablen, die speichern ob ein Fehler aufgetreten ist sind vielleicht in C noch schick, in Java gibt's aber - richtig bemerkt - Exceptions. Der Ansatz mit der Fehlervariable hat den Nachteil, dass beim Auftreten eines Fehlers mein Programmcode weiterverfolgt wird, ich bei jeder relevanten Operation überprüfen muss, ob nun schon ein Fehler aufgetreten ist oder nicht - man ist sich stets unsicher über den aktuellen Zustand des Programms.
Eine Exception unterbricht den Programmablauf an der Stelle an der sie geworfen wurde. Wenn eine Methode bei einem Fehler eine Exception wirft, ich aber bis zur nächsten Methode gelange weiß ich, dass die Methode zuvor fehlerfrei ausgeführt worden ist. Tritt hingegen ein Fehler auf, wird sie in einem catch-Block abgefangen, in dem klar ist, _dass_ ein Fehler aufgetreten ist.
:confused:Nich zuletzt ist gut zu wissen, wie es mit Aufbau, Form und Struktur in den beiden Programmen ausschaut? Ist das so wie es ist akzeptabel? Ist die Spezifikation wirklich in meinen Beispielen auf schnelle, unkomplizierte Weise gelöst.
Unsortierte Kommentare:
Halte dich zuerst einmal an einen einheitlichen Standard beim Schreiben deines Codes, z.B. die Code Conventions for the Java Programming Language (http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html).
Weiters wählst du ungeschickte Lösungen: Wieso ein Array von Strings verwenden, um einzelne Character zu speichern? Ein Array von char wäre ausreichend gewesen (und schneller).
Bei if-Abfragen solltest du immer einen Block machen, auch wenn du nur eine Anweisung reinschreibst.
Mit Exception-Handling könntest du dein Programm besser strukturieren.
Kommentare würde ich stets über, und nicht neben der Anweisung schreiben.
So, fällt mir grad nicht mehr ein, gäbe aber sicher mehr.
Ich hätte zu dem kleinen Programm noch eine Frage:
Wieso wird nicht immer true zurueck gegeben, wenn es außerhalb der if-Abfrage steht? Wird ein evtl vorhandenes false nicht "überschrieben"?
Lg
Wings-of-Glory
26-12-2004, 01:28
Ich hätte zu dem kleinen Programm noch eine Frage:
Wieso wird nicht immer true zurueck gegeben, wenn es außerhalb der if-Abfrage steht? Wird ein evtl vorhandenes false nicht "überschrieben"?
Lg
nein, denn durch das return bricht die methode ab.
public static boolean isStringValid(String s) {
// alle Zeichen im String einzeln überprüfen
for (int i = 0; i < s.length(); i++) {
if (!isCharacterValid(s.charAt(i))) {
return false;
}
}
// wurden alle Zeichen überprüft und keine ungültigen gefunden,
// ist der String gültig
return true;
}
@Usagi
ich hab die programme mal kurz überflogen. zwar nicht wirklich durchgedacht, sprich versucht zu verstehen, was der autor da wirklich machen will, sondern nur das herausgeschrieben, was wirklich ins auge sticht. was fällt als erstes auf: programm 1 ist um 100 zeilen länger als programm 2, obwohl beide in etwa gleich stark dokumentiert sind.
programm 1 beginnt mit einer try-anweisung und endet mit catch. sprich rund um das gesamte programm ist eine try-catch anweisung geschrieben. das ist nicht gut. try-catch blöcke sollte nur in den teilen des programms auftreten, an denen wirklich auch eine exception vorkommen kann, wie z.b. beim einlesen (falscher datentyp) oder überprüfen der korrektheit einer eingabe (IndexOutOfBounds, ArrayIndexOutOfBounds, etc) was mich schon zu einem großen manko von programm #1 bringt: die überprüfung, ob nur gültige zeichen vorkommen wird so gemacht: kommen kleinbuchstaben vor, kommen großbuchstaben vor und zu guter letzt noch wird geprüft ob ein semikolon vorkommt. das ganze zieht sich auf ~30 codezeilen.
so wärs einfacher gewesn:
for (int i = 0; i < eingabe.length(), i++) {
if (!(Character.isLetter(eingabe.charAt(i)) || eingabe.charAt(i)==';'))
fehler = true; } ist nur ein vorschlag aber so funktionierts sicher und ist vor allem kurz. weiters werden viel boolean variablen verwendet um fehler zu finden. beispielsweise: eingabeendetmitStrichpunkt, richtigeEingabe, kleinbuchstabe, grossbuchstabe...
und dann ist da noch dieser RIESENGROSSE IF-BLOCK
Dein Ansatz mit den zahlreichen if-Abfragen ist eindeutig schlecht strukturiert, ist eine lange Wurst Code an deren Ende ich bereits vergessen habe, worum es am Anfang ging....und genau das passiert hier.
was fällt noch auf bei programm#1: wie schon erwähnt: keine methoden. nur spaghetticode und der ist bekanntlich schlecht lesbar und verwendbar. das ist wirklich ein grundsatz der programmierung: MODULARISIERTE PROGRAMMIERUNG sprich, verfasst eure programme in methoden auch wenn sie noch so klein und unütz erscheinen mögen, sie tragen sehr sehr viel zur lesbarkeit des programms bei.
positiv anzumerken zumindest, dass die namen der variablen (bis auf diese ominöse "flucht" variable) gut verständlich sind.
zu programm #2:
hier werden methoden verwendet, die das programm in einezlne blöcke unterteilen, wo man dann weiß was passiert hier, auch wenn man den code nicht konzentriert verfolgt. wie beispielsweise die überprüfung ob ein zeichen ein vokal iststatic boolean vocal(int index, String eingabe){ //vokal feststellen
String[] vokale={"a","e","i","o","u"};
int i;
for (i=0;i<5;i++)
{
if (eingabe.substring(index,(index+1)).toLowerCase(). equals(vokale[i])) return true;
}
return false;die methode mag manchem vielleicht unnütz erscheinen, doch wenn man zweimal darüber nachdenkt ist sie durchaus sinnvoll. oder: static boolean semicolon(int index, String eingabe){ //semicolon feststellen
if (eingabe.substring(index,(index+1)).equals(";")) return true;
else return false;...meiner meinung nach auch gut!
was das (< y) mitten im programm machen soll, weiß ich zwar nicht aber ansonsten würd ich, wenn ich wählen müsste, mich sicherheit programm 2 den vorzug geben.
----edit----
post #200 :thumb:
duracell
26-12-2004, 17:50
programm 1 beginnt mit einer try-anweisung und endet mit catch. sprich rund um das gesamte programm ist eine try-catch anweisung geschrieben. das ist nicht gut.
Das würde ich so nicht sagen. Dies ist durchaus eine sinnvollge Verwendung von Exceptions:
try
{
String eingabe = EprogIO.readWord();
if (eingabe.length() < 10)
throw new EprogException();
}
catch (EprogException e)
{
EprogIO.println("FALSCHE EINGABE");
}
Es wird zwar in diesem Kontext nicht implizit eine Exception geworfen, aber da die Laenge der Eingabe < 10, wurde eine Gueltigkeitsregel der Spezifikation verletzt. Wir werfen die Exception explizit.
static boolean semicolon(int index, String eingabe) {
if (eingabe.substring(index,(index+1)).equals(";"))
return true;
else
return false;
Kann man als gute Idee durchgehen lassen, aber der Ansatz ist schlecht. Warum?
1. Du willst überprüfen, ob ein Character aus einem String ein Semikolon repräsentiert. Die Methode ist aber auf Grund ihrer Eingangsparameter auf einem index eines Strings limitiert. Tue das, was die Methode tun soll.. vergleiche chars, nicht Strings!
2. Du benötigst nur ein Zeichen aus dem String. Verwende charAt(index) und nicht substring(index, index+1)!
...
char c = eingabe.charAt(index);
boolean ergebnis = isSemikolon(c);
private boolean isSemikolon(char c)
{
return c == ';';
}
das wars!
@duracell
der code ist ja nicht von mir!!
und zu den exceptions: jaja die verwendung und implementierung erfüllt ihren zweck voll und ganz, daran besteht kein zweifel, nur würde bei der länge des programms keinen try-catch block rund herum schreiben. sondern eben nur dort, wo auch wirklich eine exception auftreten kann. das mag vielleicht geschmacksache sein und die sichere variante ist wahrscheinlich:public class Ausnahme {
public static void main (String[] args) {
try {
....gesamtes programm }
catch (EprogException e) {
EprogIO.println("FALSCHE EINGABE"); } } } hier würde dann halt mit sicherheit jede exception erkannt und verarbeitet werden. diese lösung ist meiner meinung nach aber nicht sonderlich elegant...wie gesagt: eine frage des geschmacks!
@JohnFoo
Gelungen ist was anderes, du bist jedoch Anfänger und entsprechend sieht dein Programm aus. Das gute ist, dass du Fragen stellst, nur so wirst du auch besser. Um ein Missverständnis auszuräumen, diese Programme sind nicht von mir, sondern ich habe diese zwei von meiner zweiten Runde ausgewählt, da sie von ihrem Programmierstil her sehr unterschiedlich sind.
Grundsätzlich gilt es, keinen Code doppelt zu schreiben. Das gilt auch für die Ausgabe. Um dies zu vermeiden verwendet man auch Methoden. Versuche nachzuvollziehen, was du mir da sagst. Na gut. Dann verhindere ich also, indem ich für die Ausgabe die Methode println verwende,: EprogIO.println("FALSCHE EINGABE");dass ich den Code doppelt schreibe. Ist es aber für das Programm gut, wenn man viele solcher println verwendet? Wenn nein, wie hätte man das im ersten Programm, also im Schleifenprogramm verhindern können? Vielleicht durch den Einsatz mehr Methoden.
Wenn du die Ein- und Ausgabe von der eigentlichen Programmlogik entkoppelst kannst du leichter die Benutzerschnittstelle austauschen - zum Beispiel von der Kommandozeile zur Swing-Applikation (bunte Fenster). Ich würde aber gerne an einem konkreten Beispiel sehen, wenn Ein- und Ausgabe getrennt sind und ob das in meinen zwei unten angeführten Beispielen der Fall ist. Im ersteren also im Schleifenprogramm ist das ja eher nicht der Fall, da alles doch wie du es nennst sehr verwurstelt ist.Im zweiten Programm ist es glaube ich der Fall:
In der Hauptmethode main sind die Eingabe und Ausgabe deklariert und ausgeführt:
public static void main(String[] args) {
String eingabe ="";
eingabe=readWord(); //eingabe
String ausgabe ="";
if (checkeingabe(eingabe)){
int anzahlzeichen=eingabe.length();
int zeichen,wortanfang=0;
for (zeichen=0;zeichen<anzahlzeichen;zeichen++){
if (semicolon(zeichen,eingabe)) {
ausgabe+
=silben(eingabe.substring(wortanfang,zeichen))+";";
wortanfang=(zeichen+1);
}
}
//letztes wort falls es nicht mit ; abgeschlossen ist
if (wortanfang!=anzahlzeichen)
ausgabe+
=silben(eingabe.substring(wortanfang,anzahlzeichen ));
}
else ausgabe="FALSCHE EINGABE";
println(ausgabe); //ausgabe
}
Sollte das ein Irrtum von mir sein, dann bitte um Korrektur.
Eine Exception unterbricht den Programmablauf an der Stelle an der sie geworfen wurde. Wenn eine Methode bei einem Fehler eine Exception wirft, ich aber bis zur nächsten Methode gelange weiß ich, dass die Methode zuvor fehlerfrei ausgeführt worden ist. Tritt hingegen ein Fehler auf, wird sie in einem catch-Block abgefangen, in dem klar ist, _dass_ ein Fehler aufgetreten ist. Interessant, im zweiten, also im Methoden-Programm gibt es keinen try-catch- Block und trotzdem wird das Programm unterbrochen. Bei Unterbrechung des Programmablaufes beziehe ich mich auf das, was nach Ausführung in der schwarzen Konsole kommt.
Ich compiliere und führe das Programm in der Eingabeaufforderung aus.
Na gut, wenn ich nach dem Befehl java Silbe eine falsche Eingabe hinschreib, dann wird automatisch der Programmablauf unterbrochen und der Cursor springt wieder zum Verzeichnis, wo ich meine weiteren Befehle eingeben kann, zurück. Wenn das nicht mit Exception zusammhängt, na dann durch welchen Befehl wird dieses Verhalten ermöglicht. Natürlich habe ich da auch ein Beispiel mitgeliefert, wo das der Fall ist, dass der Cursor nach einer falschen Ausgabe nicht wieder in das Verzeichnis zurückspringt. S. Attachment. Anmerkung: Dieses Beispiel ist nicht von mir. Wo ist da der Fehler?
Weiters wählst du ungeschickte Lösungen: Wieso ein Array von Strings verwenden, um einzelne Character zu speichern? Ein Array von char wäre ausreichend gewesen (und schneller). Ich konkretisiere:
Also, dann müsste man überall wo String [] char[] hinschreiben.
static boolean checkeingabe(String text){
String[] code= besser: char[] code
oder: static boolean vocal(int index, String eingabe){
String[] vokale= besser: char[]
Ich hoffe, dass sich sonst nichts weiters im Code ändert, zumindest dass die jeweiligen Parameter die selben bleiben. Aber warum schneller? Bezieht sich das auf die Laufzeit? Kann ich mir aber nur schwer vorstellen.
Als Anfängerin schreibst du vielelicht keine
"schönen" Programme, musst du aber auch nicht. Wie schaut dann denn bitte ein schönes Programm aus? Kannst du uns da konkret bitte etwas zeigen, wo du sagst, dass ist wirklich gut programmiert. Etwas von der Sourceforge - Seite, oder wo auch immer.
Apropos, soweit ich informiert gibst du ja die Prüfung.
Kannst du uns vielleicht sagen, welche Sourcecodes wir uns da
gut anschauen sollten?
Vielleicht könntest du uns sogar deine Eprog-Prüfung
(Aufgabenstellung + Lösung) posten.
Bitte sag jetzt nicht du hast sie nicht mehr, denn das
gilt nicht. ;)
@Plantschkuh
das Restprogramm sollte auf die Daten
deiner Klasse nur über klar definierte Interfaces mit
get- und set-Methoden zugreifen können, nicht über
public-Variablen oder sowas. Variable, die nur
innerhalb einer Methoder verwendet werden, sollten auch
nur in dieserdeklariert werden und nicht als Variablen
in der Klasse. Na das hört sich mal ganz gut an.
Aber könntest du vielleicht diese Behauptung durch ein
konkretes Beispiel unterstützen, denn dann glaube
ich kann man sich schon mehr vorstellen.
..., daß dein Programm das Terminal meines
Users mit Meldungen wie "17 Knusperflocken im Anflug"
vollschreibt,wenn es bei mir um Buchhaltung geht :) Was ist das: " Terminal meines Users"
aber Exceptions sind viel allgemeiner:
Sie signalisieren einen Ausnahmezustand, normalerweise einen
Fehler, der "üblicherweise" nicht auftritt, sondern nur in
"Ausnahmefällen", wenn der Benutzer zum Beispiel sein
Keyboard auffrißt... Was passiert dann bitte? Dann wird der Programmablauf
abgebrochen, d.h das Programm funktioniert nicht mehr, oder.
Aber ich glaub, wenn der Benutzer sein Keyboard auffrißt,
oder wenn die Netzwerkverbindung abreißt,
dann wird mehr nicht funktionieren.
@ Poppe
try-catch blöcke sollte nur in den teilen des programms auftreten, an denen wirklich auch eine exception vorkommen kann, wie z.b. beim einlesen (falscher datentyp) oder überprüfen der korrektheit einer eingabe (IndexOutOfBounds, ArrayIndexOutOfBounds, etc) Wenn ich mir das so durchlese, dann fällt mir so ein konkretes Beispiel ein, wo das gemacht wurde. Das Beispiel habe ich sicherheitshalber im Attachment gelagert und heißt Testen.java public static void main(String[] args){
try{
//hier wird ueberprueft ob der eingelesene String gueltig ist
if (gultig == true ) {
beistrich_setzen_wo();
beistriche_setzen();
EprogIO.println("" + silbe);
}
else {
EprogIO.println("FALSCHE EINGABE\n");
}
}catch(Exception e){ EprogIO.println;}
} Das trifft doch den Nagel auf den Kopf, Andreas.
Aber, wenn man es in perform-Methode umwandelt, dann hast du mir mal gesagt, alle EprogIO.println mit return ersetzen. Na gut habe ich gemacht.
Jedoch wenn man main in eine perform-Methode modifiziert, dann muss ich
}catch(Exception e){ return"?";} wie folglt schreiben.
public static String perform (){
try{
string_einlesen();
//hier wird ueberprueft ob der eingelesene String gueltig ist
if (gultig == true ) {
beistrich_setzen_wo();
beistriche_setzen();
return( silbe);
}
else {
return("FALSCHE EINGABE\n");
}
}catch(Exception e){ return"?";}
} Warum ist das so?
was mich schon zu einem großen manko von programm #1 bringt: die überprüfung, ob nur gültige zeichen vorkommen wird so gemacht: kommen kleinbuchstaben vor, kommen großbuchstaben vor und zu guter letzt noch wird geprüft ob ein semikolon vorkommt. das ganze zieht sich auf ~30 codezeilen. Falsch Andreas, das zieht sich laut meiner Betrachtungen über 10 Zeilen Code. Ich konkretisiere:
... if (eingabebuchstaben[i]>96&& eingabebuchstaben[i]<123)
kleinbuchstabe = true;
else if (eingabebuchstaben[i]==225)
kleinbuchstabe = true;
else
kleinbuchstabe = false;
if (eingabebuchstaben[i]>64 && eingabebuchstaben[i]<91)
grossbuchstabe = true;
else
grossbuchstabe = false;
if (!grossbuchstabe && !kleinbuchstabe && eingabebuchstaben[i]!=59)
richtigeeingabe = false;
...
Dann müsst ich deinen Vorschlag in etwa durch diesen oben zitierten Codeteil ersetzen?
for (int i = 0; i < eingabe.length(), i++) {
if (!(Character.isLetter(eingabe.charAt(i)) || eingabe.charAt(i)==';'))
fehler = true; }
zu programm #2:
hier werden methoden verwendet, die das programm in einezlne blöcke unterteilen, wo man dann weiß was passiert hier
was das (< y) mitten im programm machen soll, weiß ich zwar nicht
aber ansonsten würd ich, wenn ich wählen müsste, mich sicherheit programm 2 den vorzug geben. Du schaust dir das Programm doch sehr gut an. Das < y ist auf meinen Mist gewachsen. Ist passiert als ich nach dem Compilieren gefragt wurde, ob ich es abspeichern will und dann habe ich auf y für yes gedrückt. Vielleicht zu oft, wie man sieht.
Dann würdest du sagen, dass 2. Programm kann als ein schönes Programm betrachtet werden, auf das man sich beim Lernen stützen kann?
Wings-of-Glory
28-12-2004, 01:59
@JohnFoo
Versuche nachzuvollziehen, was du mir da sagst. Na gut. Dann verhindere ich also, indem ich für die Ausgabe die Methode println verwende,: EprogIO.println("FALSCHE EINGABE");dass ich den Code doppelt schreibe. Ist es aber für das Programm gut, wenn man viele solcher println verwendet?
Ich glaube, du hast johnfoo mißverstanden. nicht das verwenden von println ansich verhindert, dass du ausgabe-code doppelt schreibst.
da die eprog-aufgaben so gestaltet sind, dass es nur eine (1) ausgabe gibt, wäre z.b. folgender ansatz nicht schlecht:
du sammelst z.b. in einer variable, alles was du später ausgeben möchtest, und nachdem du das programm abgearbeitet hast, brauchst du nur diese variable mit print bzw. println ausgeben und fertig.
Plantschkuh!
28-12-2004, 11:05
[Kapselung]
Na das hört sich mal ganz gut an.
Aber könntest du vielleicht diese Behauptung durch ein
konkretes Beispiel unterstützen, denn dann glaube
ich kann man sich schon mehr vorstellen.
Hier ein triviales Beispiel, vielleicht sogar kompilierbar: Eine Klasse, die einen Wert x speichert, sowie einen von x abhängigen internen Zustand, in diesem Fall xplus2.
class XPlus2
{
private int x, xplus2;
XPlus2()
{
x = 0;
xplus2 = x + 2;
}
XPlus2(int n)
{
x = n;
xplus2 = x + 2;
}
int getX()
{
return x;
}
int setX(int n)
{
x = n;
xplus2 = x + 2;
}
}
Wenn x public wäre und das Restprogramm einfach mittels Zuweisungen den Wert verändern dürfte, wäre nicht sichergestellt, daß xplus2 auch immer auf den richtigen Wert gesetzt wird. Ist hier jetzt nicht sooo aufregend, aber in echten Programmen gibt es eben solche Beziehungen zwischen den Daten.
Der andere Grund für saubere Interfaces ist Information Hiding: Ich will dich nicht mit zusätzlichen Details belasten und zeige dir deswegen nicht, wie meine Klasse implementiert ist; ich sag dir nur, welche Methoden du aufrufen darfst.
Was ist das: " Terminal meines Users"
Der Bildschirm, wenn dir das lieber ist.
Was passiert dann bitte? Dann wird der Programmablauf
abgebrochen, d.h das Programm funktioniert nicht mehr, oder.
Aber ich glaub, wenn der Benutzer sein Keyboard auffrißt,
oder wenn die Netzwerkverbindung abreißt,
dann wird mehr nicht funktionieren.
Das Programm kann dann zwar nicht mehr das machen, was es machen wollte, aber ganz abbrechen ist trotzdem oft unsinnig. Man kann z.B. den Benutzer über den unglücklichen Zustand informieren und um Rat fragen. Oder, ganz wild, man kann einfach in ein paar Minuten nochmal probieren, ob das Netz wieder geht...
Selbst wenn man echt das Programm abbricht, möchte man vorher oft noch eine Fehlermeldung ausgeben oder sowas. Daß ein Programm einfach mit einer nackten ungefangenen Exception zugrundegeht, ist nicht hübsch und nicht Sinn der Sache.
Aber, wenn man es in perform-Methode umwandelt, dann hast du mir mal gesagt, alle EprogIO.println mit return ersetzen. Ganz genau. Denn alles was durch Eprog.IO.println() normalerweise ausgegeben werden soll, soll ja an die Klasse Main zurückgegeben werden. catch(Exception e){ EprogIO.println;} ich kann mir nicht vorstellen, dass diese Zeile compilierbar ist. korrekt müsste sie nämlich heißen:catch(Exception e){ EprogIO.println();} und ist ja komplett sinnlos, weil alles was die aufgetretene Exception hier zu Stande bringt, ist, dass ein Zeilenvorschub ausgegeben wird. Das was zwischen den Klammern steht, dass soll ja wahrscheinlich die Fehlermeldung bei einem falschen Datentyp sein, also "?". Und daher: catch(Exception e) { EprogIO.println("?");} Nun mach, wie ich behaupte, aus EprogIO.println("?") ein return "?" und ? wird an Main zurückgegeben.Dann würdest du sagen, dass 2. Programm kann als ein schönes Programm betrachtet werden, auf das man sich beim Lernen stützen kann? "schön" vielleicht nicht, aber definitiv besser als nummer 1, weil es u.a.methodisiert ist.
ein einfaches beispiel für methoden nach dem EVA-Prinzip: // Dieses Programm berechnet die Summe von 2 Zahlen
import eprog.*;
public class Summe
{
public static void main (String[] args)
{ int zahl1 = eingabe();
int zahl2 = eingabe();
int summe = verarbeitung(zahl1, zahl2);
ausgabe(summe);
}
private static int eingabe() // Eingabe der Zahlenwerte
{ int z=0;
try { z = EprogIO.readInt(); }
catch (EprogException e) {EprogIO.println("FALSCHE EINGABE");}
return z;
}
private static int verarbeitung(int z1, int z2) // Berechnung der Summe
{int s = z1 + z2;
return s;
}
private static void ausgabe(int s) // Ausgabe der Summe
{EprogIO.println(s);}
}
---edit---
Programm #2 eignet sich deshalb auch besser für die Wiederverwendung (also für die Verwendung in Runde 2) da man sehr wenig verändern muss!
public class Silbe -> public class Testen
publi staic void main -> public static void perform
println(ausgabe) -> return ausgabe
vBulletin® v3.7.1, Copyright ©2000-2009, Jelsoft Enterprises Ltd.