Mein Informatiklehrer sagt, dass
-
seien wir froh, dass überhaupt noch c++ irgendwo unterrichtet wird, die tendenz ist eine andere...
-
Ich stelle hier fest, das mehrheitlich dem Lehrer zugestimmt wird!
Meine pers. Erfahrung ist die, das ich außer in switch-case fast nie break einsetze, wenn dann nur, weil ich mir nicht viel Gedanken für eine Alternative gemacht habe! continue habe ich glaube ich in meinem Leben nur einmal benutzt... zum Ausprobieren.
-
Also meiner Ansicht nach hat der Lehrer im Prinzip recht. Häufig deuten break oder continue auf schlechten Code hin. Aus pädagogischer Sicht ist ein solcher Hinweis daher angebracht.
Es gibt dennoch Situationen, in denen diese Konstrukte sinnvoll sind.
Ein sehr einfaches Beispiel wäre:
int z; while (true) // ist das unsauber? { std::cout << "Bitte geben Sie eine Zahl zwischen 1 und 10 ein:"; std::cin >> z; if (z >= 1 && z <= 10) break; std::cout << "Die Zahl " << z << " ist nicht zwischen 1 und 10.\n"; }
Ohne break hätte man ein Problem. Da müsste man die Bedingung 2 mal prüfen, was unschön ist:
int z; do { std::cout << "Bitte geben Sie eine Zahl zwischen 1 und 10 ein:"; std::cin >> z; if (z < 1 || z > 10) std::cout << "Die Zahl " << z << " ist nicht zwischen 1 und 10.\n"; } while (z < 1 || z > 10); // 2. Prüfung
-
char const* const message = "Bitte geben Sie eine Zahl zwischen 1 und 10 ein:"; std::cout << message; int z = 0; while(!(std::cin >> z) || z < 1 || z > 10) { std::cout << "Die Zahl " << z << " ist nicht zwischen 1 und 10.\n"; std::cout << message; std::cin.clear(); std::cin.ignore(std::cin.rdbuf()->in_avail()); }
Man kann sehr vieles umformen. Ich persönlich brauche
continue
fast nie,break
ein wenig öfter, aber meistens schreibe ich Schleifen ohnebreak
undcontinue
.break
undcontinue
allerdings einfach zu verfluchen und verbieten, wie es ca. der Lehrer gemacht hat, würde ich nicht. Zum Teil gibt es Schleifen, wenn man dort keinbreak
einführen würde, dann würde die Schleifen-Bedingung viel zu komplex und unübersichtlich werden oder die Schleife weisst dann x-facheif
-Verschachtelungen auf. Es gilt halt wie für alle Sprachmittel: "Überlege bevor du sie verwendest".Grüssli
-
Ich stelle fest, dass Gegner von
break
undcontinue
in diesem Thread keine Argumente bringen, sondern nur von ihrem ästetischen Empfinden berichten und/oder behaupten, es gäbe immer eine elegantere Schleifenvariante, die ohnebreak
undcontinue
auskommt. Letzteres ist natürlich schwer zu beweisen -- gerade auch weil Dijkstra und Knuth sich mit dem Thema auseinander gesetzt haben und zu dem Schluss gekommen sind, dass man mitgoto
s -- damals gabs noch keinbreak
undcontinue
-- in manchen Fällen Code-Duplikationen und "Sonderbedingungen" reduzieren kann. Ich denke, heutzutage bekommt man Dijkstras und Knuths Beispiele auch elegant ohnegoto
hin, wenn manbreak
,continue
undreturn
benutzen darf.Gruß,
SP
-
int z; std::cout << "Bitte geben Sie eine Zahl zwischen 1 und 10 ein:"; std::cin >> z; while (z < 1 || z > 10) { std::cout << "Die Zahl " << z << " ist nicht zwischen 1 und 10.\nBitte geben Sie eine Zahl zwischen 1 und 10 ein:"; std::cin >> z; }
Ginge auch - da hätte man allerdings Ausgabe/Eingabe doppelt. Andererseits ist hier eine klare "Fehlerfallbehandlung" separat gekapselt, was IMHO auch Vorteile hat.
Gruß,
Simon2.
-
Um ehrlich zu sein, das würde ich so schreiben:
int z; for (;;) { std::cout << "Bitte geben Sie eine Zahl zwischen 1 und 10 ein:"; std::cin >> z; if (1 <= z && z <= 10) break; std::cout << "Die Zahl " << z << " ist nicht zwischen 1 und 10.\n"; }
Das ist ein typischer Kandidat für die "and-a-half"-Schleifen, bei denen die Abbruchbedingung weder am Anfang noch am Ende steht.
Gruß,
SP
-
Hallo,
bei mir wird gar nicht mehr C++ unterrichtet. Ich lerne Delphi in der Schule aber da meine "Hauptsprache" nun mal
C++ ist unterhalte ich mich mit meinem Lehrer schon mal darüber! Als ich ihm ein kleines Programm gezeigt habe, meinte er halt, dass
break und continue schlechter Stil wäre und dass man sie meiden solle...Ich war damals noch nicht so erfahren und habe einfach gesagt "Ich weiß!" doch darüber schäme ich mich, denn
ich sagte es nur aus Unwissenheit bzw und meinen Lehrer zufrieden zu stellen!Heute würde mir das nicht mehr passieren, da ich der Meinung bin, dass break und continue durchaus angebracht sind!
Vielen Dank
lg, freakC++
-
Es kommt halt immer auf die Situation an. Auch ein
goto
hat seine Berechtigung. Wenn man allerdingsgoto
, oder auchbreak
undcontinue
ständig braucht lediglich, weil man zu faul ist sich, wie schon vorhin gezeigt, gedanken über Bedingungen o.ä. zu machen, dann ist das bestimmt schlechter Stil.
Wen man allerdings einen Grund hat und Alternativen zu umständlich/unleserlich wären, dann kann man alles brauchen, was die Sprache hergibt.
-
Ich stelle fest, dass Gegner von break und continue in diesem Thread keine Argumente bringen
Vollkommen richtig, ich dachte die Argumente wären allen bekannt
Wie auch immer break, continue und return sind ebenso Sprunganweisungen wie goto, es gilt die selbe Argumentation...
Man kann also nur diskutieren ob die Probleme, die durch Sprunganweisungen verursacht werden nicht geringer sind als die, die durch die umstrukturierung verursacht werden, deswegen gibt es nur Beispiele, wie man es besser machen kann.deswegen =>
Als ich ihm ein kleines Programm gezeigt habe, meinte er halt, dass
break und continue schlechter Stil wäre und dass man sie meiden solle...So formuliert imho richtig. Meiden heißt aber auch nicht, gar nicht verwenden. Wer weiß was du ihm vorgelegt hast
-
JustAnotherNoob schrieb:
Wie auch immer break, continue und return sind ebenso Sprunganweisungen wie goto, es gilt die selbe Argumentation...
Nicht zu vergessen for, while, if/else, case
-
Gerade auf meiner Platte gefunden:
C:\angstkopie\drvd\src\raetsel\main.cpp#include <iostream> using namespace std; bool istPrim(int kandidat) { bool prim=true; for(int i=2;i<=kandidat-1;i=i+1) { if(kandidat%i == 0) { prim=false; break; } } return prim; } int main() { for(int a=0;a<=9;++a) { for(int b=0;b<=9;++b) { for(int c=0;c<=9;++c) { for(int d=0;d<=9;++d) { if(a+b+c+d!=26) continue; if((a*b*c*d)%2!=0) continue; if(c!=d) continue; if(!istPrim(100*b+10*c+d)) continue; cout<<a<<b<<c<<d<<'\n'; } } } } return 0; }
edit: das rätsel dazu war anscheinend
http://www.bu-on.de/raetsel/raetsel2.htmDie Ausgabe des Programms ist
4499 4877 6677
Die Bedingung 3) wollte ich nicht ausprogrammieren.
Übrigens ist die istPrim schrecklich mit der komischen Variablen da. Warum nicht gleich rausreturnen, wenn sie nicht prim ist?
-
JustAnotherNoob schrieb:
ich dachte die Argumente wären allen bekannt
Welche sind denn das? Bring das doch mal auf'n Punkt!
Gesprungen wird immer irgendwo irgendwie, zB auch beim Funktionsaufruf. :p
Das wichtige dabei ist doch die Lesbarkeit. Wenn ich ein "goto" sehe, dann muss ich erstmal die Sprungmarke suchen, um zu wissen, wo's weiter geht. Das ist schlechte daran. Es hat auch zur Folge, dass es schwieriger wird, sich von der Korrektheit des Programms zu überzeugen.
Wie sieht es mit break, continue und return aus? Wenn Deine Schleifen mehrere Seiten lang sind, hast Du sowieso etwas falsch gemacht. Bei break und continue ist sofort klar, wo's weitergeht. Mit return springe ich aus der Funktion heraus. Willst Du mir jetzt erzählen dass die Nutzung von break, continue und return die Lesbarkeit verschlechtert? Wie würdest Du denn das Beispiel von tntnet mit der "and-a-half"-Schleife umsetzen?
So vielleicht? (Mit Zusatzvariable)
bool wiederholen = true; do { AAA wiederholen = ....; // Test if (wiederholen) { BBB } } while (wiederholen);
Oder so vielleicht? (Mit Code Duplication)
AAA while (...) { BBB AAA }
?
Ist doch alles Käse!
Gruß,
SP
-
#include <iostream> using namespace std; bool istPrim(int kandidat) { bool prim=true; for(int i=2;i<=kandidat-1;i=i+1) { if(kandidat%i == 0) { prim=false; return prim; } } return prim; } int main() { for(int a=0;a<=9;++a) { for(int b=0;b<=9;++b) { for(int c=0;c<=9;++c) { for(int d=0;d<=9;++d) { if(a+b+c+d!=26) ; else if((a*b*c*d)%2!=0) ; else if(c!=d) ; else if(!istPrim(100*b+10*c+d)) ; else cout<<a<<b<<c<<d<<'\n'; } } } } return 0; }
-
adfkhl schrieb:
#include <iostream> using namespace std; bool istPrim(int kandidat) { bool prim=true; for(int i=2;i<=kandidat-1;i=i+1) { if(kandidat%i == 0) { prim=false; return prim; } } return prim; } int main() { for(int a=0;a<=9;++a) { for(int b=0;b<=9;++b) { for(int c=0;c<=9;++c) { for(int d=0;d<=9;++d) { if(a+b+c+d!=26) ; else if((a*b*c*d)%2!=0) ; else if(c!=d) ; else if(!istPrim(100*b+10*c+d)) ; else cout<<a<<b<<c<<d<<'\n'; } } } } return 0; }
das continue dürckt mehr sofort aus, nämlich "dieser fall ist erledigt, sofort den nächsten ausprobieren!".
-
Sebastian Pizer schrieb:
Bei break und continue ist sofort klar, wo's weitergeht.
Wo es weitergeht ist klar. Herausfinden wie der Algorithmus aussieht, kann* allerdings erschwert werden. Durch ein break kann man zum Beispiel Codeduplizierung entfernen, wie es tntnet vorgeführt hat. Dadurch hast du aber eben irgendso eine halbe Schleife. Um die Schleife zu verstehen, muss du sie in deinem Kopf wieder entpacken und hast dann im Kopf die Codeduplizierung. Daher ist auch Codeduplizierung nicht einfach nur grundlegend schlecht und wenn man das dann noch in Funktionen aufteilt oder auf Variablen verteilt (z.B. die
message
Variable in meinem vorherigen Code), dann sehe ich eher Vorteile in der Lesbarkeit.*Ich möchte, dass man dieses kann nicht vergisst: kann werden != wird
Grüssli
-
Gesprungen wird immer irgendwo irgendwie, zB auch beim Funktionsaufruf.
Der Unterschied beim Funktionsaufruf ist, dass dieser bewusst implementierungsdetails versteckt.
Im Gegensatz zu Sprunganweisungen wird der Lesefluss daher nicht unterbrochen.und break hat insofern den selben Sucheffekt wie goto, weil du nun nicht mehr beim lesen des Schleifenkopfes sagen kannst, wann die Schleife verlassen wird.
-
Hi,
ich habe nur mal kurz geschaut, aber tut's nicht auch:
... if((a+b+c+d!=26) || (a*b*c*d)%2!=0) || (c!=d) || !istPrim(100*b+10*c+d)) cout<<a<<b<<c<<d<<'\n';
?
(OK ||-operator sollte nicht überladen sein)Gruß,
Simon2.
-
JustAnotherNoob schrieb:
und break hat insofern den selben Sucheffekt wie goto, weil du nun nicht mehr beim lesen des Schleifenkopfes sagen kannst, wann die Schleife verlassen wird.
Ja. Aber nicht ganz so schlimm wie goto, weil man wenigstens weiß, daß ans Ende der Schleife gesprungen wird.
return ist da noch ein wenig besser, weil man weiß, daß die ganze Funktion beendet wird.
-
JustAnotherNoob schrieb:
und break hat insofern den selben Sucheffekt wie goto, weil du nun nicht mehr beim lesen des Schleifenkopfes sagen kannst, wann die Schleife verlassen wird.
Da gibt's sicherlich genug Gegenbeispiele, was die Lesbarkeit von Schleifen ohne break bzgl Abbruchbedingung angeht. ZB das hier:
bool wiederholen = true; do { AAA wiederholen = ...; // Test if (wiederholen) { BBB } } while (wiederholen);
Hier ist es noch viel schlechter mit der Lesbarkeit. Alternativ bleibt "code duplication"
AAA while (...) { BBB AAA }
welches ich immer noch zugunsten von
for (;;) { AAA if (!...) break; BBB }
ablehnen würde.
Gruß,
SP