int sum1000( int n ) { int s = 0; while ( n > 0 ) { if ( n % 2 != 0 ) { n = n - 1; continue; } s = s + n; n = n - 1; if ( s > 1000 ) break; } return s; }

So viel erst einmal zum Thema Verzweigungen und Schleifen. Der nächste Artikel wird wieder etwas technischer, da wir uns da etwas mit den Geheimnissen des Stacks beschäftigen werden.

1 / 2 / 3

Kommentare (23)

  1. #1 Dr. Webbaer
    April 23, 2013

    Wobei “WHILE”, “DO” & “FOR” nur “IF” ist, der Bedinungsblock oder die bedingte Abfrage den Programmfluss steuert.

    Faszinierend, oder?

    MFG
    Dr. W

  2. #2 Sabine
    Berlin
    April 23, 2013

    Hallo,
    an der Stelle ein Kompliment und vielen Dank an Marcus Frenkel. Die Artikel haben mir tatsächlich DEN Schubs gegeben, um mit dem Programmieren-lernen anzufangen. Allerdings bin ich (faule Socke) von C++ weg und habe mich Python zugewandt. Deshalb verabschiede ich mich als Kommentierende und lese nur mehr still weiter mit – immerhin verstehe ich noch, worum es geht, auch wenn die Umsetzung nun konkret anders ist. Also nochmal: Danke!!

  3. #3 Stefan W.
    https://demystifikation.wordpress.com
    April 24, 2013

    Für Fortgeschrittene die Frage, wann der erste Code ein falsches Ergebnis zurückliefert.

    Außerdem gesucht: Einfache Beispiele, die einen sinnvollen Gebrauch von break und continue zeigen, der nicht eleganter anders gelöst werden kann.

    Für Überflieger: Wie bringt man Markus vom unseeligen “sogenannt” weg? Könnte eine Kontrollstruktur helfen – ein Verließ? 😉 Vielleicht mit dem YAGNI des pragmatischen Programmierers?

    Außerdem schreit dieses Zitat nach dem DRY-Principle:

    dass die Anweisungen in der Schleife wenigstens ein mal auf jeden Fall ausgeführt werden – unabhängig von der Bedingung.

    Es wird 3x das gleiche gesagt.

    Mir fehlt etwas das switch/case-Statement, oder wurde das abgeschafft?
    Außerdem ist die for-Schleife als Zählschleife profanisiert worden. Tatsächlich besteht sie – neben dem womöglich auszuführenden body – aus 3 Elementen,

    for (init; cond; incr) {
    body;
    }

    dem initial ausgeführten statement, welches leer sein kann und welches aus mehreren, durch Komma getrennten Statements bestehen kann – Du korrigierst mich, Marcus? – zweitens, einer Bedingung, die leer sein kann, und die eine Kombination mehrerer Bedingungen sein kann. Es kann ein Zufallsgenerator aufgerufen werden, der recht willkürlich die Schleife terminiert. Und dann der incr.-Teil, der jedesmal zum Schleifenende aufgerufen wird.

    for (a=4, b=5; 3*a<b+100; a+=2, ++b) {
    body;
    }

    wäre etwa eine ebenso gültige for-Schleife wie
    for (;true;) {
    // eine Endlosschleife
    body;
    }

    Man kann eine for-Schleife wie oben umschreiben in

    {
    init;
    while (cond) {
    body;
    incr;
    }
    }

    wobei die äußeren, geschweiften Klammern nötig sind, weil im init-Teil Variablen deklariert werden können, die außerhalb der for-Schleife nicht sichtbar sind.

    Durch diesen Aufbau ist die for-Schleife zwar als Zählschleife geeignet, aber andere Einsatzgebiete sind ebenso legitim

    for (fileopen; not end of file; read char) {
    do something with the character
    }

  4. #4 michael
    April 24, 2013

    @StefanW
    Es kommt nur zwei mal das Wort ‘sogenannt’ vor. Wo ist das Problem ?

  5. #5 MartinB
    April 24, 2013

    Ich finde ja die abs-Variante mit dem n=-n ziemlich unschön – du verlässt dich darauf, dass ein call-by-value verwendet wird, aber zum Lesen ist das in meinen Augen problematisch, weil ich beim Lesen des Programms selbst zum Funktionsaufruf zurückgucken muss.

  6. #6 Marcus Frenkel
    April 24, 2013

    @StefanW

    Mir fehlt etwas das switch/case-Statement, oder wurde das abgeschafft?

    Alles zu seiner Zeit.

    Außerdem ist die for-Schleife als Zählschleife profanisiert worden.

    Um mich mal selber zu zitieren:

    Diese erlaubt (unter anderem), eine Schleife eine festgelegte Anzahl von Malen zu durchlaufen.

    Das hier ist ein Einführungsartikel. Weiterführende Konzepte kommen noch.

    @MartinB
    call-by-value oder call-by-reference sind in C++ zum Glück nicht implizit in den Parametern versteckt, sondern müssen immer explizit hingeschrieben werden; damit ist ein call-by-value recht leicht zu erkennen. Bei so einer kurzen Funktion ist das auch kein Problem; bei längeren Funktionen aber, da stimme ich gern zu, sollte man nicht unbedingt auf den Parametern direkt operieren.

  7. #7 CM
    April 24, 2013

    Total esoterisch, aber im neuen Standard ist:

    include

    float n = 0;
    n =-n;

    Dann ergäbe “std::copysign(1, n)” -1. Also sollte die Abfrage eher
    if ( n >= 0 )
    lauten.

    Aber wie gesagt, dass ist total esoterisch (weil nahezu ohne Relevanz) und den “>=”-Operator kennen wir auch noch nicht.

    Möglicherweise ist es das, was StefanW meinte?

    (Wie gibt man in Kommentaren Codeblocks am besten an? Der HTML-Code der Seite ist mir zu umständlich, um das für ‘nen schnelles Kommentar zu verwenden.)

  8. #8 Marcus Frenkel
    April 24, 2013

    @CM

    Beim include fehlt wohl etwas…die Zeichen müssen auch da immer mit dem entsprechenden HTML-Code angegeben werden. Das ist manchmal etwas frustrierend, dass hier keine BB-Codes verwendet werden, aber leider wohl nicht zu ändern.

    Aber ja: die Unterscheidung, ob man eine 0 negiert oder nicht, kann schon bei Gleitkommazahlen von Interesse sein, übrigens nicht erst seit dem neuen Standard. Die Bitmuster von +0 und -0 können sich unterscheiden, je nach dem, wie der benutzte C++-Compiler Gleitkommazahlen implementiert.

    Für Codeblöcke gibt es nicht wirklich gute Tags, fürchte ich. Man könnte es mit
    <pre><code> Code </code></pre>
    probieren, falls der Editor nicht die Leerzeichen entfernt…

    Experiment:

    Dies
      ist
        ein
          Test
    
  9. #9 Marcus Frenkel
    April 24, 2013

    Ja,
    <pre><code> Code </code></pre>
    geht einigermaßen.

  10. #10 CM
    April 24, 2013

    ups, Danke! Da sollte
    #include
    stehen.
    Und
    copysign()
    sowie
    signbit()
    gibt es doch erst mit C++11? Aber da war ich in der Tat viel zu undeutlich.

  11. #11 Marcus Frenkel
    April 24, 2013

    Fehlt bei include immer noch etwas? 😉
    Und ja, die genannten sind glaube ich neu, die Unterscheidung zwischen +0 und -0 ist aber schon uralt.

  12. #12 CM
    April 24, 2013

    math.h! Natürlich, ich will “math.h”! 😉
    Eckige Klammern funktionieren trotz des Code-Tags nicht. Das könnte noch lustig werden …

  13. #13 DeLuRo (Der Lustige Robot)
    April 24, 2013

    @alle:
    Schreibt für … folgendes (ohne Leerzeichen, Semikoln beachten):
      spitze Klammer Auf, kleiner-als:     &­lt;
      spitze Klammer ZU, größer-als:     &­gt;

    Leerzeichen links lassen sich auch durch &­nbsp; darstellen.

  14. #14 Marcus Frenkel
    April 24, 2013

    @CM
    Auch die müssen per HTML-Code dargestellt werden.

    #include <math.h>

    Dann geht es. 😉

  15. #15 CM
    April 24, 2013

    Entschuldigt – eigentlich “kann” ich ganz gut HTML. Bin aber zu faul / zu verwöhnt, um das stets per Hand zu tippen – nur für ein Kommentar. Und bei etwas komplexeren Code würde es auch ziemlich fehleranfällig. Asche auf mein Haupt!
    (Vielleicht sollte ich ein SB-Blog-Skript zur Umwandlung schreiben? 😉 )

  16. #16 Stefan W.
    https://demystifikation.wordpress.com/2013/04/09/balkentrager/
    April 30, 2013

    Was ergibt dieser Code mit obiger abs-Funktion?

    cout << abs (-2147483648) << endl;

  17. #17 m
    Mai 3, 2013

    @CM: https://tohtml.com

    @Stefan W: das hängt davon ab wie int gespeichert wird 🙂
    – 16 bis 31 bit 1-er-, 2-er-Komplement oder Vorzeichen-Betrag, oder 32 bit 1-er-Komplement oder Vorzeichen-Betrag: -2147483648 ist long int oder long long int, das Ergebnis der Konvertierung zu int ist dann implementation defined.
    – bei 32 bit 2-er-Komplement: bei C wären wir über die trap representations tief im Sumpf der implementation definedness; für C++ habe ich es nicht herausfinden können :-(.
    – mehr als 32 bit: 2147483648

  18. #18 michael
    Mai 3, 2013

    @m

    Ist in der ersten Antwort hier beschrieben.

  19. #19 m
    Mai 3, 2013

    Danke, michael.
    Und der Vollständigkeit halber: abs(INT_MIN) wäre über Kapitel 5, Absatz 4 oder 5 (je nach Ausgabe) undefined

    Sollte mich einer meiner Freunde fragen, weshalb ich das letzte mal einen Sprachstandard gelesen habe: ich würde vermutlich lügen 🙂

  20. #20 Dieter
    Mai 23, 2013

    Zuerst mal danke für die C++ Serie. Finde ich sehr gut gemacht. Zwei Fragen zu den beiden letzten Beispielen dieser Folge:

    Woher kommt die Variable sum?

    Werden im letzten Beispiel nicht die ungeraden statt der geraden Zahlen summiert?

  21. #21 Marcus Frenkel
    Mai 23, 2013

    @Dieter

    Woher kommt die Variable sum?

    Magie. 😉
    Nein, Spaß, Fehler meinerseits. Sollte natürlich s heißen, ich habe es korrigiert.

    Werden im letzten Beispiel nicht die ungeraden statt der geraden Zahlen summiert?

    Auch hier mein Fehler; es sollte n % 2 != 0 heißen. Ist korrigiert.

    Danke für die Hinweise.

  22. #22 yohak
    Juli 21, 2013

    Mir scheint im letzten Code-Beispiel wird eine Endlosschleife
    produziert. Die Anweisung “n=n-1” befindet sich ja hinter dem
    “continue”-Befehl, d.h. wenn n ungerade ist, und “continue”
    aufgerufen wird, kommt es gar nicht mehr zur Ausführung
    von “n=n-1” sodass die Zählvariable n bis in alle Ewigkeit
    bei demselben ungeraden Wert bleibt und man in einer Endlosschleife landet. Oder übersehe ich da was?

  23. #23 Marcus Frenkel
    Juli 21, 2013

    @yohak
    Natürlich, danke. Ist korrigiert.