mehrere return-Anweisungen schlecht?
-
Hab hier n Miniprogramm, das ein mehrdimensionales Array mit Zufallszahlen befüllt & dann die zufälligen Zahlen im Array in 10er Einheiten ausgibt.
#include <stdio.h> #include <stdlib.h> int main (void) { /* Deklaration eines dreidimensionalen Arrays mit 1000 Elementen */ int zufall_array [10] [10] [10] = {{0}}; int a = 0, b = 0, c = 0; /* fuellt das Array mit Zufallszahlen */ for (a = 0; a < 10; a++) { for (b = 0; b < 10; b++) { for (c = 0; c < 10; c++) { zufall_array [a] [b] [c] = rand (); } } } /* Anzeige der Array-Elemente in 10er Einheiten */ for (a = 0; a < 10; a++) { for (b = 0; b < 10; b++) { for (c = 0; c < 10; c++) { printf ("\nzufall_array [%d] [%d] [%d] = ", a, b, c); printf ("%d", zufall_array [a] [b] [c]); } printf ("\nWeiter mit Return, Verlassen mit STRG-C."); getchar (); } } return 0; }
Um die nächste 10er Einheit anzuzeigen, soll man Return drücken, um das Programm zu verlassen, soll STRG-C gedrückt werden.
Das Programm läuft solange, bis die letzten möglichen Array-Elemente (zufall_array [9] [9] [9])ausgegeben wurden o der User das Programm durch STRG-C vorzeitig beendet.
Bei mir crasht das Programm aber, wenn ich STRG-C drücke, sprich die CMD hängt sich auf & im Editor gibts ne Fehlermeldung:
'Eine Ausnahme (erste Chance) bei 0x7c87647d in proc.exe: 0x40010005: Control-C.'Habe deswegen die eigentliche printf-Anweisung (Z35) rausgelöscht & dafür ne 2. return-Anweisung eingebaut (Code unten).
Die Variable 'weiter_o_verlassen' in der if-Anweisung wurde natürlich im Zug der Programmänderung definiert/initialisiert.printf ("\nWEITER durch Eingabe von \'1\', VERLASSEN durch Eingabe von \'2\': "); scanf ("%d", &weiter_o_verlassen); if (weiter_o_verlassen == 2) { return 0; }
Im Buch hab ich aber mal gelesen, dass man mehrere return-Anweisungen vermeiden & nur wenn unbedingt notwendig verwenden soll.
Was is an mehreren return-Anweisungen so schlecht o gefährlich?
Das Programm funktioniert jetzt prima & crasht nich mehr.
-
Wo werden deine Zufallszahlen initialisiert?
Teste mal, ob das mit dem Zufall funktioniert oder ob an der gleichen Position jedes Mal, wenn du das Programm neu aufrufst, die gleichen Zahlen stehen.
MfG f.-th.
-
Es erzeugt (nach dem Geschmack vieler Leute) unübersichtlichen Code und verhindert gewisse Compileroptimierungen (letzteres könnte sich geändert haben). Sollte man sich aber auch nicht religiös dran klammern, dass man mehrere returns vermeidet, wenn man dadurch wesentlich an Übersicht gewinnen sollte.
Es ist aber für Anfänger eine gute Daumenregel, um Spaghetticode zu vermeiden. Dies, so muss ich sagen, gilt auch für dich: Dein Programmfluss ist derzeit Unsinn.
-
SeppJ schrieb:
Daumenregel
Faustregel.
-
volkard schrieb:
SeppJ schrieb:
Daumenregel
Faustregel.
Wo ist der Unterschied?
-
@f.-th. - stimmt, das mit dem Zufall is n Reinfall. Jedesmal, wenn ich das Programm neu aufrufe, stehen an den gleichen Positionen die gleichen Zahlen, omg
.
Hatte ich vorher gar nich bemerkt.
Kann man denn Zufallszahlen initialisieren? Wußte ich gar nich? Wie soll das gehen?@SeppJ - also wenn der Code dadurch übersichtlicher wird, is es erlaubt mehrere returns zu verwenden, ich als Anfänger sollte es aber vermeiden?!
Was meinst mitSeppJ schrieb:
Dein Programmfluss ist derzeit Unsinn.
...zuviele Whitespaces?
-
SG1 schrieb:
volkard schrieb:
SeppJ schrieb:
Daumenregel
Faustregel.
Wo ist der Unterschied?
-
cooky451 schrieb:
SG1 schrieb:
volkard schrieb:
SeppJ schrieb:
Daumenregel
Faustregel.
Wo ist der Unterschied?
xD aber generell liegt der unterschied an der grösse, sprich ne metapha...
desto grösser das objekt im bezug auf die wichtigkeit umso wichtiger ist es =b
-
Wir haben da zwei gegensätzliche Zielanforderungen:
a) Sobald ein Ergebnis feststeht, sofort mit return raus! Das erhöht die Verständlichkeit ungemein.
b) Nur einen return-Ort verwenden, damit man einfach für jedes open() ein close() machen kann, das erhöht die Fehlerarmut ungemein.Früher war das eindeutig. Da sprach man sich klar für b) aus. Denn die Funktionen wqren groß, so groß wie Deine und noch größer. Denn jeder Funktionsaufruf hat mindestens gefühlte 86 Takte gekostet und je mehr Parameter er hatte, desto mehr. Der Stack war normales ungecachetes RAM und pushen hieß schreiben und des Stackpointer erniedrigen, und zwar nacheinander. Und bei großen Funktionen, die zugelich viele verschiedene Sachen machen, kann man einfach nicht jedes open() im Auge behalten. Mit b) kann man wenigstens diesen nervigen(!!!) Fehler wegmachen.
Deswegen nervig(!!!), weil man ihn selbst mit dem Debugger nicht findet. Obwohl die Funktion das richtige ausgibt, ist wegen der Funktion das Programm falsch. Zum Beispiel kann die Datei, weil sie aus Versehen noch offen ist, beim nächsten Durchlaufen der Funktion nicht wieder geöffnet werden. Oder nach 5 Minuten Laufzeit gehen die GDI-Ressourcen leer. Oder der Server frißt pro Stunde 20MB Speicher und nach zwei Wochen kackt er mangels Speicher ab.Heute kosten Funktionsaufrufe sehr wenig. Zum einen werden sie in trivialen Fällen eh inline gemacht, also die aufrufende Funktion macht gar keinen echten Funktionsaufruf, sondern der Compiler optimiert das und kopiert den Code der aufgerufenen Funktion dahin, wo die aufrufende Funktion die aufgerufene Funktion aufrufen würde. Zum anderen sind sogar echte Funktionsaufrufe sehr billig geworden und man hört von großen Funktionen, die messbar schneller sind, weil gerade kein inlining erzwungen wird, denn die paar Aufrufe sind billiger, als wenn die Gesamtfunktion nicht mehr in den Porzessorcache paßt.
Ich mache Funktionen so klein wie noch sinnvoll möglich, und sie rufen sich halt gegenseitig auf. Mini-Funktionen, aber dafür sauviele. Der Compiler kann sehr gut abschätzen, wo er inlinen sollte und wo nicht.
Mit den sauvielen Mini-Funktionen sind sowohl a) als auch b) kaum noch relevant. Die betrachtete Funktion ist so klein, daß Du sie auf anhieb verstehst, und sie ist so klein, daß Du kein close() vergißt.
Man kann close() sogar garantieren, wenn man den mystischen Wrapper-Trick nimmt:
int foo(int a,int b,char* filename){ FILE* file=fopen(filename,... int returnCode=fooSub(a,b,file);//fooSub kann returnen wie verrückt fclose(file); return returnCode; }
Bei mehreren open/close-Objekten wird das nervig, da ist vielleicht nicht schlecht, trotzdem "quasi" zu returnen mit
rc=17; goto myExit;
und beim label myExit wird alles geclosed (,was noch nicht geschlossen wurde, mit if(file) fclose(file)). Oder auch mehrere myExit1 bis myExit5, um die ifs zu sparen.
-
wäre es eine möglichkeit, eine structur fest zu legen und das ganze per funktion
zu closen?in etwa so:
struct FILE_struct{ FILE* read; FILE* write; FILE* writeAndRead; }fileStruct; void CloseAll(void){ fclose(fileStruct.read); fclose(fileStruct.write); fclose(fileStruct.writeAndRead); }
ist das sinnvoll (in der art, ist nur so daumen mal pi) oder unaktzeptabel/unsauber?
-
SG1 schrieb:
volkard schrieb:
SeppJ schrieb:
Daumenregel
Faustregel.
Wo ist der Unterschied?
SeppJ hat sich als Englisch-Leser geoutet, nehme ich an. Kein Fehler, zum Beispiel "Programming Perls" (wo ich mir auch die Daumenregel angewöhnt hatte) ist auf englich so endgeil, ich würde abstreiten, daß man es einigermaßen erhaltend überhaupt übersetzen kann, wenn ich nicht "Gödel, Escher Bach" gelesen hätte. Aber Programmierbücher werden traditionell schlampig übersetzt.
http://en.wikipedia.org/wiki/Rule_of_thumbAuf Hochdeutsch ist es die
http://de.wikipedia.org/wiki/FaustregelAngeblich gibt es in den südlichen Grenzgebieten auch Dörfer wo auf "deutsch" Daumenregel üblich ist. Ich wäre an einer Klangprobe interessiert.
-
itedvo schrieb:
wäre es eine möglichkeit, eine structur fest zu legen und das ganze per funktion
zu closen?in etwa so:
struct FILE_struct{ FILE* read; FILE* write; FILE* writeAndRead; }fileStruct; void CloseAll(void){ fclose(fileStruct.read); fclose(fileStruct.write); fclose(fileStruct.writeAndRead); }
ist das sinnvoll (in der art, ist nur so daumen mal pi) oder unaktzeptabel/unsauber?
Erstmal schauen, WAS Du da machst.
Du faßt Objekte zu größeren Objekten zusammen und definierst dazu Funktionen. Du programmierst objektorientiert.
Das kann sinnvoll sein, muß aber nicht. Ich verweise dazu auf die unzähligen Threads C++ versus C. Wenn Du solche Zusammenfassungen magst, ist es vielleicht schlau, nach C++ zu wechseln. Dann würde man gleich Destruktoren benutzen, die von alleine aufräumen. Sehr lecker! Aber damit kaufst Du auch viel Ungemach ein. Weil schlechter C++-Code schlechter ist als normaler C-Code, und verdammt viele Folgerungen, auf die man nicht so von alleine kommt, aus dem Destruktor-Konzept erspringen, müßtest Du beim Umstieg eigentlich erstmal ein viertel Jahr anhalten und Kram lesen, bevor es mit gutem C++ weitergehen kann. Mit so einer Lesepause steigert man aber auch normalen C-Code zu gutem C-Code.
Daher wäre mir diese Zusammenfassung suspekt. Aber nicht undenkbar. Objektorientierte Programmierung geht ja auch ohne Destruktoren, wie C mit allen Objekten, die open()/close() haben beeindruckend zeigt. Warum nicht auch Zusammenfassen? Sobald es inhaltlich ok ist, nur zu!
Aber C braucht die Abstaktion nicht. Es fühlt sich an wie eine Abstraktion ohne großen Nutzen. C++ lebt davon, da wäre das (und noch viel mehr) eigentlich nötig. Unnütze Abstraktion fühlt sich schlecht an.
-
ach, n'viertel jahr mehr lernen oder weniger... aber interessant, jetzt weiss ich
wieso mein professor teilweise meinen stil nicht mag... ich programmiere schon
immer so, hat mir keiner gesagt was objekt orientiert ist und auf die frage ob
man mir das erklären könnte, kam nur die antwort: das lernen wir eh in 2 jahren,
also konzentrier dich auf das jetzige...
-
volkard schrieb:
SG1 schrieb:
volkard schrieb:
SeppJ schrieb:
Daumenregel
Faustregel.
Wo ist der Unterschied?
SeppJ hat sich als Englisch-Leser geoutet, nehme ich an.
Das hast du übrigens vollkommen Recht. Da wo ich herkomme, sagt man tatsächlich Faustregel. Aber ich lese und spreche so viel Englisch, dass ich immer häufiger mit solchen Redewendungen durcheinander komme. Wobei es mir hinterher peinlich ist, wenn es mir auffällt (die Daumenregel klingt jedoch lustig
). Auch die ganzen anderen typischen Verdreher wie "nicht wirklich" oder "das macht Sinn" mache ich dauernd. Die Daumenregel ist mal wieder etwas neues.
-
Nix substantiell Neues zu dem Thema, nur ein LOL:
It is often claimed that the term originally referred to a law that limited the maximum thickness of a stick with which it was permissible for a man to beat his wife.
Ich persönlich denke ja, daß der Ausdruck Daumenregel daher kommt, Enfernungen mit der ausgestreckten, zur Faust geballten Hand (mit erhobenenm Daumen) abzuschätzen.
-
Mehrere return Anweisungen sind wichtig, weil so etwas sonst nicht funktionieren würde:
./configure && make
oder, da das nur Scripte sind bei richtigen Programmen:
tar c bla blub.tar && gzip blub.tar
(oder so ähnlich)Wenn das tar funzt, dann liefert es return 0.
Wenn nicht, dann irgendeinen Error Code abweichend von 0 und gzip wird dann nicht mehr aufgerufen.
Deswegen sind mehrere returns in einem Programm notwendig.
-
EOP schrieb:
Ich persönlich denke ja, daß der Ausdruck Daumenregel daher kommt, Enfernungen mit der ausgestreckten, zur Faust geballten Hand (mit erhobenenm Daumen) abzuschätzen.
Aber das ist nur eine das Schätzen begleitende Geste.
Zum Einen wird sie z.B. bei Kraftfahrzeugschlossern zur Rechnungsbetragsermittlung verwendet, dabei mit den Worten "Pi mal Daumen" unterstützt. Na, das wars auch. Wobei der Daumen am ausgetreckten Arm gerne eine Sekunde lang zusammen dreimal zwischen senkrecht und 45-60 Grad nach links (beim Rechtshänder) dreht und wieder in die Ausgangslage geht.
Kein Mensch verwendet den Daumensprung noch als Maß.
Aber dabei ist es immer eine, im übertragenen Sinne, Daumenpeilung.
-
Ist notwendig schrieb:
Mehrere return Anweisungen sind wichtig, weil so etwas sonst nicht funktionieren würde:
./configure && make
oder, da das nur Scripte sind bei richtigen Programmen:
tar c bla blub.tar && gzip blub.tar
(oder so ähnlich)Wenn das tar funzt, dann liefert es return 0.
Wenn nicht, dann irgendeinen Error Code abweichend von 0 und gzip wird dann nicht mehr aufgerufen.
Deswegen sind mehrere returns in einem Programm notwendig.das hat aber mit dem Thema nichts zu tun.
-
Hm, warum mein Miniprogramm immer die selben Zufallszahlen an der selben Posi ausgibt, hat bis jetzt noch keiner erklärt.
& auf die Frage wie man Zufallszahlen initialisiert bzw was das für n Sinn hat, gibts auch noch keine Antwort...SeppJ hat auch noch immer nich geantwortet, was so 'Spagetti' an meinem Code sein soll??
Nur zur Info, der Code is die Buchvorlage, von daher kann ich mir fast nich vorstellen, dass die Buchschreiber-Jungs Spagetticode
drucken lassen.Tjou & der gut gemeinte lange Absatz von volkard auf page1 is für mich nur Bahnhof, weil ich leider noch nichts mit
- open-/close-Anweisungen,
- foo, fooSub & Co &
- schon gar nich mit irgendwelchen 'mystischen Wrapper-Tricks'
zu tun hatte....also bin ich jetzt noch genauso schlau wie vor der Erstellung dieses Threads...
Wenn ihr mir feedbackt, dann brauche ich bitte Anfänger-gerechte Feedbacks (hört sich zwar blöd an, is aber so)
& Antworten auf die Fragen, die ich im Threadverlauf stelle.
-
R3FRESH schrieb:
Hm, warum mein Miniprogramm immer die selben Zufallszahlen an der selben Posi ausgibt, hat bis jetzt noch keiner erklärt.
& auf die Frage wie man Zufallszahlen initialisiert bzw was das für n Sinn hat, gibts auch noch keine Antwort...SeppJ hat auch noch immer nich geantwortet, was so 'Spagetti' an meinem Code sein soll??
Nur zur Info, der Code is die Buchvorlage, von daher kann ich mir fast nich vorstellen, dass die Buchschreiber-Jungs Spagetticode
drucken lassen.Tjou & der gut gemeinte lange Absatz von volkard auf page1 is für mich nur Bahnhof, weil ich leider noch nichts mit
- open-/close-Anweisungen,
- foo, fooSub & Co &
- schon gar nich mit irgendwelchen 'mystischen Wrapper-Tricks'
zu tun hatte....also bin ich jetzt noch genauso schlau wie vor der Erstellung dieses Threads...
Wenn ihr mir feedbackt, dann brauche ich bitte Anfänger-gerechte Feedbacks (hört sich zwar blöd an, is aber so)
& Antworten auf die Fragen, die ich im Threadverlauf stelle.Nö, so nicht. Direkt im zweiten Posting hat f.-th. das mit dem Zufall gelöst. Manchmal kann man ein Wort nicht zuordnen, aber dann fragt man schnell mal google.
http://lmgtfy.com/?q=c+zufallszahlen+initialisieren
Das war ganz einfach und wird von Dir erwartet.