Switch, Funktionsaufruf und Cout



  • Hallo, ich habe eine Frage zu einem Problem das mich sehr verwundert, und zudem ich keine richtige Erklärung finde.

    Es geht um Folgenden Code:

    #include <iostream>
    #include <conio.h>
    
    void funktion();
    void otherFunktion();
    
    int main (void)
    {
      funktion();
    
    return 0;
    }
    
    void funktion()
    {
      char charInput;
      std::cout << ">";
    
      charInput = getch();
    
      switch(charInput)
      {
        case '1': otherFunktion();
                  std::cout << "\nBack ";
                  break;
      }
    }
    
    void otherFunktion()
    {
      std::cout << "otherFunktion()\n";
      funktion();
    }
    

    Ich gebe in das Programm drei mal den Wert 1 ein und dann, irgend ein Wert zum abrechen des Programms.

    Was mich erstaunt ist die Ausgabe zu der ich keine Erklärung finde:

    >otherFunktion()
    >otherFunktion()
    >otherFunktion()
    >
    Back
    Back
    Back
    

    Was mich erstaunt sind die "Back"-Ausgaben. Das es eine gibt, erstaunt mich, dass es aber gleich drei Ausgaben sind, umso mehr. Es ist immer genau die Menge an Ausgaben wie eingeben des Wertes 1.

    Meine Frage ist, wie es überhaupt möglich ist, dass "Back" ausgegeben wird. Nach meinen Verständnis dürfte "Back" von Zeile 14 eigentlich gar nicht drankommen... Die nächste Frage wäre, warum dann die Ausgaben erst am Ende des Programms, "in einem Zug" erscheinen. Wo bleiben die cout Ausgaben gespeichert. Etwa im Puffer?

    Ich bin gespannt auf die Antworten.

    Viele Grüße und Danke!



  • @GMgenia sagte in Switch, Funktionsaufruf und Cout:

    Nach meinen Verständnis dürfte "Back" von Zeile 14 eigentlich gar nicht drankommen.

    Warum?



  • @GMgenia sagte in Switch, Funktionsaufruf und Cout:

    Ich gebe in das Programm drei mal den Wert 1 ein und dann, irgend ein Wert zum abrechen des Programms.
    Was mich erstaunt ist die Ausgabe zu der ich keine Erklärung finde:

    >otherFunktion()
    >otherFunktion()
    >otherFunktion()
    >
    Back
    Back
    Back
    

    Was mich erstaunt sind die "Back"-Ausgaben. Das es eine gibt, erstaunt mich, dass es aber gleich drei Ausgaben sind, umso mehr. Es ist immer genau die Menge an Ausgaben wie eingeben des Wertes 1.
    Meine Frage ist, wie es überhaupt möglich ist, dass "Back" ausgegeben wird. Nach meinen Verständnis dürfte "Back" von Zeile 14 eigentlich gar nicht drankommen... Die nächste Frage wäre, warum dann die Ausgaben erst am Ende des Programms, "in einem Zug" erscheinen. Wo bleiben die cout Ausgaben gespeichert. Etwa im Puffer?

    main() ruft function() auf.
    function() gibt > aus.
    Du gibst 1 ein.
    function() ruft otherFunction() auf.
    otherFunction() gibt otherFunction()\n aus.
    otherFunction() ruft function() auf.
    Die von otherFunction() aufgerufene function() gibt > aus.
    Du gibts 1 ein.
    Die von otherFunction() aufgerufene function() ruft otherFunction() auf.
    Die otherFunction() die von der von otherFunction() aufgerufenen function() aus aufgerufen wurde gibt otherFunction\n aus.
    Die otherFunction() die von der von otherFunction() aufgerufenen function() aus aufgerufen wurde ruft function() auf.
    ...

    merkst was?



  • @GMgenia sagte in Switch, Funktionsaufruf und Cout:

    Meine Frage ist, wie es überhaupt möglich ist, dass "Back" ausgegeben wird. Nach meinen Verständnis dürfte "Back" von Zeile 14 eigentlich gar nicht drankommen...

    Dann ist dein Verständnis davon was bei einem Funktionsaufruf passiert vermutlich falsch.

    Die nächste Frage wäre, warum dann die Ausgaben erst am Ende des Programms, "in einem Zug" erscheinen. Wo bleiben die cout Ausgaben gespeichert. Etwa im Puffer?

    Irgendein Puffer ist hier kein Thema. Die Ausgaben erscheinen in der Reihenfolge in der sie vom Programm gemacht werden.



  • @hustbaer sagte in Switch, Funktionsaufruf und Cout:

    Dann ist dein Verständnis davon was bei einem Funktionsaufruf passiert vermutlich falsch.

    Ja, entspricht einem goto.

    @GMgenia

    Wahrscheinlich willst du so was ähnliches:

    #include <iostream>
    #include <conio.h>
    
    void foo() { std::cout << "foo()\n\n"; }
    void bar() { std::cout << "bar()\n\n"; }
    void qux() { std::cout << "qux()\n\n"; }
    
    bool menu()
    {
        std::cout << "[1] foo\n[2] bar\n[3] qux\n-------\n[0] exit\n\n> ";
    
        int input;
        while ((input = _getch()) < '0' || '3' < input)
            std::cerr << "Input Error!\n";
    
        switch (input) {
        case '0':
            return false;
        case '1':
            foo();
            break;
        case '2':
            bar();
            break;
        case '3':
            qux();
            break;
        }
        return true;
    }
    
    int main()
    {
        while (menu());
        std::cout << "bye.\n\n";
    }
    


  • @Swordfish sagte in Switch, Funktionsaufruf und Cout:

    Wahrscheinlich willst du so was ähnliches:

    Ich bedanke mich, aber, es geht mir nicht um einen anderen Code. Ich will nur verstehen was in dem Beispiel passiert.



  • @manni66 sagte in Switch, Funktionsaufruf und Cout:

    @GMgenia sagte in Switch, Funktionsaufruf und Cout:

    Nach meinen Verständnis dürfte "Back" von Zeile 14 eigentlich gar nicht drankommen.

    Warum?

    Weil in Zeile 23 die Funktion 29 aufgerufen wird. Das Programm springt auf Zeile 29. Zeilen 24 und 25 kommen nicht dran.

    Bei nächsten Aufruf läuft das Programm wieder bis auf Zeile 23 und springt nochmals auf Zeile 29. In welchen Moment kommen Zeile 24 und 25 ins Spiel?



  • @GMgenia

    Bei einem Funktionsaufruf wird sich der Punkt gemerkt, wo zu der Funktion verzweigt wird.
    Eine Funktion läuft bis zum return oder Ende.
    Dann wird zu dem Aufrufspunkt zurückgekehrt.

    Egal wie oft die Funktion aufgerufen wird.

    Ein Funktiosaufruf ist kein goto



  • @hustbaer sagte in Switch, Funktionsaufruf und Cout:

    Dann ist dein Verständnis davon was bei einem Funktionsaufruf passiert vermutlich falsch.

    In welchem Moment werden Zeilen 24 und 25 abgespielt? Nach meinem Verständnis springt das Programm von Zeile 23 auf Zeile 29. Und dann von neuem, von Zeile 23 auf 29. Und wenn am Ende des Programms irgend ein anderer Wert eingegeben wird, dürfte case '1' nicht einmal drankommen. In welchen Moment wird das cout aufgerufen?



  • Deine Funktion otherfunction wird ja irgendwann beendet. Und zwar genau so oft, wie sie aufgerufen wird. Und wenn sie beendet wird, läuft das Programm an der Stelle weiter, von wo otherfunction vorher aufgerufen wurde, und an der Stelle wird 'back' ausgegeben ...

    Das 'back' soll ja vermutlich genau das dokumentieren, nämlich 'ich bin zurück aus der Funktion otherfunction', oder?
    Naja, und da Du sie oben dreimal aufgerufen hast (darüber wunderst Du Dich ja nicht?), wird sie auch dreimal beendet ...



  • @DirkB sagte in Switch, Funktionsaufruf und Cout:

    @GMgenia

    Bei einem Funktionsaufruf wird sich der Punkt gemerkt, wo zu der Funktion verzweigt wird.
    Eine Funktion läuft bis zum return oder Ende.
    Dann wird zu dem Aufrufspunkt zurückgekehrt.

    Egal wie oft die Funktion aufgerufen wird.

    Ein Funktiosaufruf ist kein goto

    Diese Antwort bringt mich etwas näher zum Verständnis, aber nicht so sehr.

    Wenn ich das richtig verstanden haben, sind die Aufrufspunkte Zeile 23 und Ziele 32. Aber wie ich verstehe, sind Zeile 24 und Zeile 25 nicht Teil der Aufrufspunkte.... Müsste also nicht über diese Zeilen hinweg aufgerufen werden?



  • @GMgenia
    Was meinst du wo es weiter geht, wenn die Ausführung an dieser Stelle

    void otherFunktion()
    {
      std::cout << "otherFunktion()\n";
      funktion();
    } // <---------------------------
    

    angekommen ist?



  • @GMgenia sagte in Switch, Funktionsaufruf und Cout:

    aber, es geht mir nicht um einen anderen Code. Ich will nur verstehen was in dem Beispiel passiert.

    Deswegen habe ich dir ja aufgeschrieben was passiert.



  • @GMgenia

    Du kannst das Programm mal mit Zettel und Stift durchspielen.
    Nimm dir so einen 8x8 Notizblock.

    Funktionen sind wie Arbeitsanweisungen.
    Du befolgst nacheinander die Anweisungen.
    Bei einem Funktionsaufruf schreibst du die aktuelle Zeilennummer auf einen Zettel legst ihn neben dich und machst mit der aufgerufenen Funktion weiter.
    Bei einem return oder der letzten } der Funktion nimmst du den obersten Zettel von dem Stapel und machst an der notierten Zeile im Programm weiter. Den Zettel schmeißt du weg.

    PS: bei einem neuen Aufruf einer Funktion gibt es auch neue lokale Variablen.



  • @DirkB sagte in Switch, Funktionsaufruf und Cout:

    die aktuelle Zeilennummer

    Ne, eben nicht. Dann kappiert er verschachtelte Funktionsaufrufe wieder nicht.



  • @hustbaer sagte in Switch, Funktionsaufruf und Cout:

    @GMgenia
    Was meinst du wo es weiter geht, wenn die Ausführung an dieser Stelle

    void otherFunktion()
    {
      std::cout << "otherFunktion()\n";
      funktion();
    } // <---------------------------
    

    angekommen ist?

    Genau darum geht es in meiner Frage. Warum kommt das Funktionsende erst zum Abschluss des Programmablaufs? Wenn eine Ausgabe nach dem Funktionsaufruf steht, kommt auch dieser erst zum Ende des Programmablaufs.



  • Da, ich habs dir aufgemalt:

    +--- main() ----+     +--- function() ------------------+
    | function(); --|---->|  std::cout << ">";              |
    | return 0; <---|--+  |  switch(_getch()) { *)          |
    +---------------+  |  |  case '1':                      |     +--- otherFunction() -----------------+
                       |  |      otherFunction(); ----------|---->|  std::cout << "otherFunction()\n";  |      +--- function() ------------------+
                       |  |      std::cout << "\nBack "; <--|--+  |  function(); -----------------------|----->|  std::cout << ">";              |
                       |  |      break;                     |  +--|--[return;] <------------------------|--+   |  switch(_getch()) { *)          |
                       |  |  }                              |     |                                     |  |   |  case '1':                      |     +--- otherFunction() -----------------+    
                       +--|--[return;]                      |     +-------------------------------------+  |   |      otherFunction(); ----------|---->|  std::cout << "otherFunction()\n";  |     +--- function() ----------------------+
                          |                                 |                                              |   |      std::cout << "\nBlack "; <-|--+  |  function(); -----------------------|---->|  std::cout << ">";                  |
                          +---------------------------------+                                              |   |      break;                     |  +--|--[return;] <------------------------|--+  |  switch(_getch()) { *)              |
                                                                                                           |   |  }                              |     |                                     |  |  |      case '1':                      |      +--- otherFunction() -----------------+
                                                                                                           +---|--[return;]                      |     +-------------------------------------+  |  |          otherFunction(); ----------|----->|  std::cout << "otherFunction()\n";  |     +--- function() -------------------+
                                                                                                               |                                 |                                              |  |          std::cout << "\nBack "; <--|--+   |  function(); -----------------------|---->|  std::cout << ">";               |
                                                                                                               +---------------------------------+                                              |  |          break;                     |  +---|--[return;] <---------------------------+  |  switch(_getch()) { ----[ input != 1 ]---+
                                                                                                                                                                                                |  |  }                                  |      |                                     |  |  |  case '1':                       |       |
                                                                                                                                                                                                +--|--[return;]                          |      +-------------------------------------+  |  |      otherFunction();            |       |
                                                                                                                                                                                                   |                                     |                                               |  |      std::cout << "\nBack ";     |       |
                                                                                                                                                                                                   +-------------------------------------+                                               |  |      break;                      |       |
                                                                                                                                                                                                                                                                                         |  |  }                               |       |
                                                                                                                                                                                                                                                                                         +--|--[return;] <---------------------|-------+
                                                                                                                                                                                                                                                                                            |                                  |
                                                                                                                                                                                                                                                                                            +----------------------------------+
    
    

    * ) Eingabe ist '1'.



  • This post is deleted!


  • So, jetzt sollt's stimmen.



  • @Swordfish sagte in Switch, Funktionsaufruf und Cout:

    So, jetzt sollt's stimmen.

    Oh, das Bild ist supper! Jetzt habe ich verstanden!!
    Erst ab der Eingebe !=1 kehrt der Programmablauf zurück und die Ausgabe der cout wird auf dem Bildschirm ausgegeben! Darauf wäre ich nicht gekommen.... Vielen Dank für diese super Erklärung!!


Log in to reply