C++ Direkt bis zu bestimmten Punkt springen?

T_55

Lieutenant
Registriert
Feb. 2013
Beiträge
643
Hallo,

kann man im Codeablauf wenn eine bestimmte Bedingung erfüllt ist direkt an eine bestimmten Stelle springen so dass die dazwischenliegenden Codezeilen überprungen werden?

ZB:

Code:
// Code
if(ijk == true)
{
   springe zu Codestelle A
}
// Code
// Code
if(abc == true)
{
   springe zu Codestelle A
}
// Code
// Code
if(xyz == true)
{
   springe zu Codestelle A
}
// Code
// Code

Codestelle A // Springe wenn oben true direkt hierher

Gruß
 
Bevor man (mMn) goto verwendet, sollte man seinen Code überdenken.

​Gibt es denn nicht die Möglichkeit, "Codestelle A" in einer eigene Methode auszulagern?
 
Goto ist ein wenig verpöhnt. Ansonsten kannst du auch noch eine Schleife basteln und diese per break verlassen (und somit direkt an das Ende der Schleife springen).
 
Bitte beachten, dass man goto tunlichst vermeiden sollte, weil es den Code schwer wartbar macht.
 
Microsoft MSDN schrieb:
Zu Programmierzwecken wird empfohlen, wann immer möglich die Anweisungen break, continue und return anstelle der goto-Anweisung zu verwenden.

Kann ich so unterschreiben. In der Praxis ist goto verpönt, da es in den meisten Fällen immer eine bessere und saubere Lösung gibt.
Wenn du nur üben willst, ist das näturlich okay.

Btw, kleiner Tipp am Rande:
Bei boolischen Variablen musst du im Gutfall nicht explizit mit true vergleichen. Es reicht wenn du schreibst
Code:
if(abc)
{
   springe zu Codestelle A
}
oder im Schlechtfall
Code:
if( ! abc)
{
   springe zu Codestelle A
}
 
Zuletzt bearbeitet:
Ok dann wäre eine Schleife mit einem Durchlauf und break zum rausspringen die beste Lösung?
 
Ja, break zum beenden, continue um vor dem Durchlauf in den nächsten zu springen.
 
Wäre es so ok?

Code:
int i = 1;
while(i == 1)
{
   i = 0;

    // Code
    if(ijk)
    {
       break; // springe zu Codestelle A
    }
    // Code
    // Code
    if(abc)
    {
       break; // springe zu Codestelle A
    }
    // Code
    // Code
    if(xyz)
    {
       break; // springe zu Codestelle A
    }
    // Code
    // Code
}
 Codestelle A // Springe wenn oben true direkt hierher
 
Ja es soll auch keine Wiederholungen geben, es geht mir ja nur um das Überspringen sobald eine der if Bedingungen true ist. Oder geht es noch besser?
Ergänzung ()

Oder kann man eigentlich einfach mit break aus blöcken rausspringen? dann könnte man den Schleifenkram weglassen

{
// code
break;
// code
}
Ergänzung ()

-

Ne das klappt nicht: break statement not within loop or switch

Wenn goto so unbeliebt ist dann ist doch eine einmal durchlaufende Schleife mit break die einzige Möglichkeit...
 
​Ich denke du solltest einfach eine Methode basteln.
Code:
class MyClass
{
  public void main()
  {
    if(abc)
    {
      this.MyMethod();
    }
    if(def)
    {
      this.MyMethod();
    }
    if(hij)
    {
      this.MyMethod();
    }
  }

  public void MyMethod()
  {
    //...do something here
  }
}

Ist natürlich nur ein Bespiel ohne Rücksicht auf die Syntax.
 
Ich wuerde an deiner Stelle eine Konstruktion aus if und else Bloecken nehmen oder ein switch-case statement.
 
SparkMonkay schrieb:
Ich wuerde an deiner Stelle eine Konstruktion aus if und else Bloecken nehmen oder ein switch-case statement.

Wenn es zB sehr viele if Abfragen sind, wo das Abfragen aller weiteren if Abfragen hinfällig wird sobald nur eine "die Bedingung zu überspringen" erfüllt, dann müsste man alle if Abfragen ausführen obwohl vielleicht schon bei der ersten feststeht, dass die folgenden gar nicht mehr gecheckt werden müssen.
 
Da bietet sich ein switch-case Konstrukt an. Das funktioniert allerdings nicht mit allen Datentypen.
 
"Goto ist verpönt" ist so ein sinnloses Dogma. Sicher kann man damit üblen Scheiß machen, aber gerade für OPs Problem halte ich es für absolut legitim, goto zu benutzen.

Was findet der geneigte Leser besser?

Variante 1:
Code:
void *a = NULL, *b = NULL, [...];

if((a = malloc(x)) == NULL) return 0;
if((b = malloc(y)) == NULL) {
    free(a);
    return 0;
}
if((c = malloc(z)) == NULL) {
    free(b);
    free(a);
    return 0;
}
[.....]
if((r = malloc(xyz)) == NULL) {
    free(q);
    free(p);
    free(o);
[...]
    free(a);
    return 0;
}
[...]
return 1;

oder eher Variante 2:

Code:
void *a = NULL, *b = NULL, [...];

if((a = malloc(x)) == NULL) goto fail;
if((b = malloc(y)) == NULL) goto fail;
if((c = malloc(z)) == NULL) goto fail;
[...]
if((r = malloc(xyz)) == NULL) goto fail;
[...]
return 1;
fail:
free(r);
free(q);
free(p);
[...]
return 0;

€: Habe sogar einen Meinungsverstärker gefunden! Der lustige Linus meint:

http://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/
 
Zuletzt bearbeitet: (kleinkram)
Die 3 Sprünge sind gleich, wenn du später eine Änderung am Sprung durchführst, musst du dann in dem Beispiel schon 3 mal ändern.

Besser wäre:
Code:
int main(){
    if(ijk || abc || xyz ) 
        functionWithCode(); //Funktionsaufrufe sind Sprünge auf Assembler Ebene
}

functionWithCode() {
     //Codestelle A 
}
 
Der Aspekt der Performance war auch ein Grundgedanke dabei nicht etliche Abfragen zu haben.

Wenn Beispielsweise über 100 Bedingungen abgefragt werden und nur eine ist true dann müssten die Restlichen nicht mehr abgefragt werden und daher wäre ein Sprung schon von Vorteil.
Wenn ZB bei 100 Abfragen die zwanzigste Abfrage true ist könnte man sich die letzten 80 Abfragen sparen. Daher die Frage nach dem Sprung auch im Bezug auf Performance.
 
xliq schrieb:
//Funktionsaufrufe sind Sprünge auf Assembler Ebene

Nein, es sind CALLs und die springen nach RET wieder dahin, wo das Programm vorher war. Offensichtlich nicht, was OP will.
 
@asdfman Dein Beispiel ist aber auch reinrassiges C, wo Fehlerbehandlung und Aufräumarbeiten auf andere Art und Weise schwierig werden. In C++ hat man Exceptions und Destruktoren für sowas.

Das Beispiel oben ist jedenfalls äquivalent zu
Code:
if (!ijk) {
  // Code
  if (!abc) {
    // Code
    if (!xyz) {
      // Code
    }
  }
}
// Codeteil A

Das ist natürlich auch nicht besonders lesbar, und sorgt eher für zusätzliche Unklarheit, wenn da noch mehr Abbruchkriterien dazu kommen.
Wenn es sich anbietet, kann man eher noch sowas schreiben:

Code:
void f(...) {
  if (ijk)
    return;
  // Code
  if (abc)
    return;
  // Code
  if (xyz)
    return;
  // Code
}

void g(...) {
  f(...);
  // Codeteil A
}

Hat gegenüber goto den Vorteil, dass man nicht erst das Label finden muss (bei nem 'return' ist ziemlich klar, was passiert), kann aber auch unpraktikabel sein, wenn f außerhalb von g keine klare Bedeutung hat. In solchen Fällen gibt es aber ebenfalls Abhilfe, die dominic.e oben schon vorgeschlagen hat:

Code:
SomeType f(...) {
  // Codeteil A
}

SomeType g(...) {
  if (ijk)
    return f(...);
  // Code
  if (abc)
    return f(...);
  // Code
  if (xyz)
    return f(...);
}

Das ist genau dann sinnvoll, wenn f sowieso aufgerufen werden soll und g nur als Lieferant für Argumente dient, sprich: wenn f nicht den vollen Kontext von g benötigt. Bei reinen Aufräumarbeiten ist das wie gesagt nicht der Fall, aber falls es tatsächlich Aufräumarbeiten sind, sollte Codeteil A im Normalfall gar nicht existieren (außer wir reden hier von einem C++-Wrapper für eine C-Library o.ä.).

Aber wie immer: Unterschiedliche Lösungen für unterschiedliche Probleme. @T55 kannst du etwas konkreter werden mit deinem Beispiel?
 
Zuletzt bearbeitet:
Zurück
Oben