verlassen eines temporary scopes oder try blockes
-
hi Shade
das ist mir schon soweit klar. das aufsplitten in mehrere funktionen bietet sich meiner meinung aber nicht an. geht um folgendes:
ich muss (derzeit) 17 funktionen aufrufen die einen boolschen wert zurueck liefern. abhaengig davon ob false oder true zurueck kommt werden die funktionen hintereinander aufgerufen oder der darauffolgende code weiter abgearbeitet. sieht dann ungefaehr so aus:int func() { if(func1(...) == false) { ... code ... } else { if(func2(...) == false) { ... code ... } else { if(func3(...) == false) { ... code ... } else { if(.... usw. } } } //hier kommen noch 2-3 codezeilen die auf jeden fall immer abgeaerbeitet werden muessen }bei 17 verschachtelungen macht das keinen spass mehr und in einzelne funktionen was auslagern, ich weiß nicht.
da finde ich das dann so uebersichtlicher:
int func() { temporary_scope { if(func1(...) == false) { ... code ... break; } if(func2(...) == false) { ... code ... break; } if(func3(...) == false) { ... code ... break; } ... usw } noch paar codezeilen }oder wie wuerdest du das ueber mehrere funktionen loesen ?
Meep Meep
-
Tipp:
returngibt es auch noch.Was soll das denn werden, wenn's fertig ist? Du zeigst uns nur "deinen Ansatz" aber erzählst nichts vom Problem, was du mit deinem Ansatz zu lösen versuchst. Das nennt man "XY Problem" und ist leider sehr verbreitet.
-
Meep Meep schrieb:
das ist mir schon soweit klar. das aufsplitten in mehrere funktionen bietet sich meiner meinung aber nicht an. geht um folgendes:
ich muss (derzeit) 17 funktionen aufrufen die einen boolschen wert zurueck liefern. abhaengig davon ob false oder true zurueck kommt werden die funktionen hintereinander aufgerufen oder der darauffolgende code weiter abgearbeitet. sieht dann ungefaehr so aus:Prinzipiell ist das Konzept hier komisch. Warum gibt es voneinander unabhängige Funktionen die so bestimmte Reihenfolge vorgeben. Das klingt ein bisschen wie wenn Polymorphie eine gute Lösung sein könnte.
Oder aber eine bessere Datenstruktur.
-
Meep Meep schrieb:
ich muss (derzeit) 17 funktionen aufrufen die einen boolschen wert zurueck liefern. abhaengig davon ob false oder true zurueck kommt werden die funktionen hintereinander aufgerufen oder der darauffolgende code weiter abgearbeitet. sieht dann ungefaehr so aus:
das ist das problem. 17 funktionen einer fremdbibliothek die hintereinander aufgerufen werden muessen. es werden einige parameter uebergeben, die teilweise von den vorherigen funktionen abhaengig sind.
Meep Meep
-
int helperfunc() { if(func1(...) == false) { ... code ... } else { if(func2(...) == false) { ... code ... } else { if(func3(...) == false) { ... code ... } else { if(.... usw. } } } } int func(){ int r = helperfunc(); //hier kommen noch 2-3 codezeilen die auf jeden fall immer abgeaerbeitet werden muessen return r; }Jetzt kannst du in helperfunc return benutzen.
-
Meep Meep schrieb:
das ist das problem. 17 funktionen einer fremdbibliothek die hintereinander aufgerufen werden muessen. es werden einige parameter uebergeben, die teilweise von den vorherigen funktionen abhaengig sind.
Du kannst das noch 10 mal sagen, das ändert nichts.
Die Anforderung ist zu hinterfragen.Das können wir hier nur nicht, weil wir die details nicht kennen.
idR sind andere Datenstrukturen (zB ein decision tree) oder polymorphie die richtige Antwort auf die Frage.
Ohne konkretes Beispiel geht aber nicht mehr an Hilfe.
Ich kann dir nur sagen, dass ich noch nie in so einer Situation war, wo sowas notwendig war und es keine andere Lösung gab.Es gibt natürlich immer mal Ausnahmen wo es einfach nicht besser geht - aber idR ist nur etwas redesign notwendig damit der Code vernünftiger aussieht.
-
Ich würde es so machen (wenn umstrukturieren wirklich nicht geht):
bool b = true; b && b = f1(); b && b = f2(); b && b = f3(); b && b = f4(); // ...Wenn b am Ende true ist, war alles erfolgreich. Einzelne Fehlermeldungen sind so natürlich nicht möglich, aber es schreit ja eh nach Exceptions.
-
In deinem Beispiel kann man auch if/else verwenden:
int func() { { if(!func1(...)) { ... code ... } else if(!func2(...)) { ... code ... } else if(!func3(...)) { ... code ... } else { ... usw } } noch paar codezeilen }Wenn du mehr Kontrolle brauchst, spricht mMn nichts gegen ein
goto cleanup;. Das ist bei solchen Funktionen in C so üblich. Kannst es natürlich auch im Named Loop Idiom verstecken (das geht auch für Scopes).
-
Shade Of Mine schrieb:
Du kannst das noch 10 mal sagen, das ändert nichts.
Die Anforderung ist zu hinterfragen.Das können wir hier nur nicht, weil wir die details nicht kennen.
welche anforderung meinst du ? ich hab keinen plan was du wissen willst.
krümelkacker schrieb:
Was soll das denn werden, wenn's fertig ist? Du zeigst uns nur "deinen Ansatz" aber erzählst nichts vom Problem, was du mit deinem Ansatz zu lösen versuchst.
es gibt da ansich nichts zu diskutieren und auch kein problem das ich loesen will. ich wollte einfach nur wissen wie ich aus so nem scope oder einen try-block vorzeitig rauskomme. mehr nicht. wenn es keine moeglichkeit gibt dann muss ich entweder bei meinem workaround bleiben oder mit den if-verschachtelungen arbeiten.
btw: es geht um ein netzwerkprotokoll das man recht stumpfsinnig durcharbeiten muss. aehnlich wie bei den sockets:(o) socket erstellen (o) socket an ein interface binden (o) verbindung aufbauen (o) anfrage senden (o) antwort lesen (o) verbindung beendenhier hat man genauso abhaengigkeiten der functionen und man muss sie nacheinander aufrufen.
Meep Meep
-
Meep Meep schrieb:
Shade Of Mine schrieb:
Du kannst das noch 10 mal sagen, das ändert nichts.
Die Anforderung ist zu hinterfragen.Das können wir hier nur nicht, weil wir die details nicht kennen.
welche anforderung meinst du ? ich hab keinen plan was du wissen willst.
INFOS!
Du hast nur ein abstraktes Problem beschrieben.
Darauf gibt es nur eine abstrakte Antwort.Wenn du eine konkrete Antwort willst, musst du eine konkrete Problemstellung herzeigen.
es gibt da ansich nichts zu diskutieren und auch kein problem das ich loesen will. ich wollte einfach nur wissen wie ich aus so nem scope oder einen try-block vorzeitig rauskomme. mehr nicht. wenn es keine moeglichkeit gibt dann muss ich entweder bei meinem workaround bleiben oder mit den if-verschachtelungen arbeiten.
http://bash.org/?866112 schrieb:
<glyph> For example - if you came in here asking "how do I use a jackhammer" we might ask "why do you need to use a jackhammer"
<glyph> If the answer to the latter question is "to knock my grandmother's head off to let out the evil spirits that gave her cancer", then maybe the problem is actually unrelated to jackhammersPS:
btw: es geht um ein netzwerkprotokoll das man recht stumpfsinnig durcharbeiten muss. aehnlich wie bei den sockets:
(o) socket erstellen (o) socket an ein interface binden (o) verbindung aufbauen (o) anfrage senden (o) antwort lesen (o) verbindung beendenhier hat man genauso abhaengigkeiten der functionen und man muss sie nacheinander aufrufen.
Nein. Hier sieht der korrekte Code so aus:
Socket s; s.send(); string msg = s.receive();also komplett ohne if oder dergleichen.
So sollte dein Code am Ende auch aussehen. Und kann es mit großer wahrscheinlichkeit auch.
-
Die Antwort auf die Frage "wie komme ich vorzeitig aus einem Block heraus?" ist "mit goto," was dir schon zu denken geben sollte. Mit ziemlich hoher Wahrscheinlichkeit ist das, was du da versuchst, Spaghetticode der schlimmsten Sorte.
Wenn es dir nur um die Einrückung bei verschachtelten ifs geht: Ich benutze die Schreibweise
if(foo) { ... } else if(bar) { ... } else if(baz) { ... } else if(qux) { ... } else { ... }
-
Meep Meep schrieb:
da finde ich das dann so uebersichtlicher:
int func() { temporary_scope { if(func1(...) == false) { ... code ... break; } if(func2(...) == false) { ... code ... break; } if(func3(...) == false) { ... code ... break; } ... usw } noch paar codezeilen }oder wie wuerdest du das ueber mehrere funktionen loesen ?
Oh, jetzt erst den Code gesehen.
Das geht trivial:int func() { func2(); noch paar codezeilen } void func2() { if(func1(...) == false) { ... code ... return; } if(func2(...) == false) { ... code ... return; } if(func3(...) == false) { ... code ... return; } ... usw } }aber das kann ja nicht die frage gewesen sein, oder?
-
ja genau shade, darum gehts mehr oder weniger. ich wollte das mit der auslagerung nicht machen weil ich sonst echt viele parameter an die funktion mit uebergeben muss. wollte es halt in einer funktion lassen.
Meep Meep
-
Meep Meep schrieb:
ja genau shade, darum gehts mehr oder weniger. ich wollte das mit der auslagerung nicht machen weil ich sonst echt viele parameter an die funktion mit uebergeben muss. wollte es halt in einer funktion lassen.
Viele Parameter sind wiederum ein Indiz, dass die Funktion zu viel machen könnte. Das sollte dich nicht abschrecken, aufzuteilen - im Gegenteil.
Eventuell kann man ja einige Parameter zusammenfassen. Oder wenn das ganze einen Zustand hat, könntest du auch ein Klasse darum herum bauen, und Membervariablen abspeichern.
<
>
-
Meep Meep schrieb:
ja genau shade, darum gehts mehr oder weniger. ich wollte das mit der auslagerung nicht machen weil ich sonst echt viele parameter an die funktion mit uebergeben muss. wollte es halt in einer funktion lassen.
Ah, ok.
Dann ists trivial. Die Lösung heißt: Exception.Wenn ein Fehler auftritt, wirf eine Exception. Dann sind die if-kaskaden automatisch weg.
Das ganze lässt sicht, wenn du nicht unbedingt jede Funktion Kapseln willst, per macro (bzw. in c++ per varidic template mit perfect forwarding) lösen.
Korrektes Kapseln wäre toll, geht aber nicht immer. Wir haben bei WinAPI Funktionen dann immer so ein macro verwendet:
#define CHECKED(func) if(!(func)) throw SomeException(#func, GetLastError())und dann eben
CHECKED(Something(a,b,c)) CHECKED(Someother(d,a,f)); ...und schon war alles schön mit exception versehen.
-
nun ja, wenn ein false zurueck gegeben wird ist es kein fehler. daher will ich eigendlich keine exceptions dafuer verwenden. die funktionen die ich da aufrufen muss werfen naemlich bei einem fehler ne exception. true false ist nur dafuer da, damit ich weiß das ich die naechste funktion auch noch aufrufen muss.
wuerden sich da exception wirklich anbieten ?Meep Meep
-
Das kann man so nicht direkt beantworten. Wenn die Funktionen ein Socket erstellen und so weiter, dann wäre das durchaus ein Szenario, wo man eine Exception werfen könnte.
Wenn Read fehlschlägt, weil die Verbindung getrennt wurde, dann ist das fast eine Glaubensfrage, ob man eine Exception wirft oder nicht. Je nach Anwendungsfall kann das eine oder andere (mehr) Sinn machen.
Es ist aber definitiv einfacher folgendes zu schreiben:
try { MyWinsockInitializer winsockInitializer; // Würde z.B. in der main() erfolgen MySocketClass socket; socket.Listen(2500); MySocketClass client; socket.accept(client); client.WriteLine("Hello!"); std::cout << client.ReadLine() << std::endl; } catch (MySocketException& e) { std::cerr << e.what() << std::endl, }Anstatt
MyWinsockInitializer winsockInitializer; if (winsockInitializer.Ready()) { MySocketClass socket; bool error = false; if ((error = socket.Listen(2500))) { MySocketClass client; if ((error = socket.accept(client))) { if ((error = client.WriteLine("Hello!")) != 0) { std::string res = client.ReadLine(); if ((error = client.GetState()) != MySocketClass::Disconnected) std::cout << client.ReadLine() << std::endl; } } }Setz deine Idee einfach mal um und poste das konkrete Ergebnis. So könnte man dir am besten helfen und so lernst du auch viel mehr, als wenn man irgendwelche Verallgemeinerungen schreibt...
-
Ich hab bei der Variable error einen Denkfehler drinne, aber geht ja ums Prinzip und zeigt gleich einen weiteren Schwachpunkt, wenn man die Rückgabewerte dauernd kontrollieren muss. Da wundert man sich dann, warum die nächste Funktion nicht das tut, was sie soll. Denn sie wird erst gar nicht aufgerufen

-
Meep Meep schrieb:
nun ja, wenn ein false zurueck gegeben wird ist es kein fehler. daher will ich eigendlich keine exceptions dafuer verwenden. die funktionen die ich da aufrufen muss werfen naemlich bei einem fehler ne exception. true false ist nur dafuer da, damit ich weiß das ich die naechste funktion auch noch aufrufen muss.
Wieso musst du die naechste Funktion nicht aufrufen wenn eine Funktion false liefert?
-
Shade Of Mine schrieb:
Meep Meep schrieb:
nun ja, wenn ein false zurueck gegeben wird ist es kein fehler. daher will ich eigendlich keine exceptions dafuer verwenden. die funktionen die ich da aufrufen muss werfen naemlich bei einem fehler ne exception. true false ist nur dafuer da, damit ich weiß das ich die naechste funktion auch noch aufrufen muss.
Wieso musst du die naechste Funktion nicht aufrufen wenn eine Funktion false liefert?
weil wenn z.b. die 5te funktion ein eindeutiges ergebnis liefert, dann gibt sie false zurueck. true wenn ich die naechste funktion aufrufen muss.
das ergebnis bekomm ich ueber die funktions-parameter zurueck. ist ein recht grosses struct.Meep Meep