Iteration mit size_t 0 als Randbedingung

Lesezeit: 3 Minuten

Was ist der “richtige” Weg, um eine abnehmende Schleife mit einem size_t-Wert und einer Randbedingung zu schreiben. Beispiel fehlerhafte Implementierung:

for (size_t elemNum = listSize-1; elemNum >= 0; --elemNum) { /* ... */ }

Wenn es Null erreicht, wird es auf den Maximalwert umlaufen, anstatt als Randbedingung zu fungieren. Es ist notwendig, die Schleife rückwärts zu durchlaufen. Es scheint ein Problem zu sein, das eine Defacto-Standardlösung hätte, aber ich kann nicht finden, was es ist.

Der prägnanteste Ansatz ist die Verwendung von Post-Increment:

for (size_t i = listSize; i--;) ...

  • ähm, das verhält sich nicht anders als –i?

    – James

    28. August 2011 um 22:37 Uhr

  • ach, ich verstehe, die Erhöhung ist in der Bedingung. Mein Fehler

    – James

    28. August 2011 um 22:39 Uhr

  • Ich denke, es funktioniert, aber imo ist die Verwendung einer While-Schleife wie von pmg vorgeschlagen einfacher zu verstehen als auf diese Weise zu “missbrauchen”.

    – Medo42

    28. August 2011 um 22:40 Uhr

  • @ Medo42: Inwiefern ist der While-Loop-Ansatz weniger “Missbrauch”? Außerdem erweitert es den Umfang der Schleifenvariablen über die Schleife hinaus, was schlechtes Karma ist.

    – Marcelo Cantos

    28. August 2011 um 22:43 Uhr

  • Diese Lösung gefällt mir am besten. Solange der im anderen Kommentar erwähnte “goes to”-Operator verstanden wird, kann ich es noch deutlicher machen: for (size_t i = listSize; i --> 0;) { /* ... */ }

    – Markus Langen

    29. August 2011 um 19:52 Uhr


elemNum = listsize;
while (elemNum--) {
    /* work with elemNum varying from `listsize - 1` down to `0` */
}

  • Einige Compiler unterstützen den speziellen “goes to”-Operator, while (elemNum --> 0) { /* ... */ } für diesen Zweck.

    – Kerrek SB

    28. August 2011 um 22:50 Uhr

  • @Kerrek: Ich denke, du meinst alle Standard-konformen Compiler 🙂

    – pmg

    28. August 2011 um 22:53 Uhr

  • @pmg, ein kleiner Nitpick hier: the elemNum wird danach nicht 0 sein (es wird unmittelbar nach der letzten Iteration einen Umlauf geben). Seit dem Fragesteller for Schleife nicht einmal gemacht elemNum außerhalb der Schleife sichtbar ist, spielt es wahrscheinlich keine Rolle, aber es ist (sehr geringfügig) sauberer, das Dekrement als erste Zeile innerhalb der Schleife auszuführen.

    – Branko Dimitrijević

    28. August 2011 um 23:05 Uhr

  • @Branko Ich finde das ist kein kleiner Nitpick, sondern ein echtes Gegenargument. Lokale Indexvariablen in for Schleifen haben einen Grund, daher ist diese Antwort hier nicht angemessen.

    – Jens Gustedt

    29. August 2011 um 7:03 Uhr

Ich kenne keinen Standardweg, aber das sollte funktionieren:

for (size_t elemNum = listSize-1; elemNum < listSize; --elemNum) { /* ... */ }

  • Das ist eine ziemlich nette Art, es zu tun.

    – James

    28. August 2011 um 22:34 Uhr

  • nein, es ist ein ziemlich verschleierter Weg. Es ist so hässlich, dass ich es gerne ablehnen würde. : /

    – Karoly Horvath

    28. August 2011 um 22:37 Uhr


  • Nun, ich sehe es überhaupt nicht schwierig. Ich sehe es sehr elegant und intelligent.

    – Diego Sevilla

    28. August 2011 um 22:40 Uhr

  • Ich denke, die Lösung von pmg ist bisher die beste und würde sie meiner empfehlen.

    – Medo42

    28. August 2011 um 22:42 Uhr


  • Dieser Ansatz ist zerbrechlich. Der Typ der Schleifenvariablen könnte sich später ändern (z. B. könnte ein Wartungsprogrammierer dies tun, um Typvergleichswarnungen aufzulösen, und könnte es versäumen, den Code richtig zu inspizieren), und dann sind alle Wetten abgeschlossen.

    – Marcelo Cantos

    28. August 2011 um 22:46 Uhr


Sie könnten stattdessen zwei Variablen verwenden:

size_t count = 0;
for (size_t elemNum = listSize-1; count < listSize; ++count, --elemNum) { /* ... */ }

for (size_t counter = listSize; counter > 0; --counter) { 
     size_t index = counter-1;

    /* ... use `index` as an index ... */ 
}

Benutzeravatar von Branko Dimitrijevic
Branko Dimitrijević

size_t elemNum = listSize;
while (elemNum > 0) {
    --elemNum;
    // Do your work here.
}

Benutzeravatar von James
James

Sie könnten dies als Bedingung verwenden:

elemNum != (size_t)-1

Oder Sie könnten hochzählen und etwas für Ihren Index rechnen (was der Compiler wahrscheinlich sowieso optimieren wird):

for (size_t i = 1; i <= listSize; i++) {size_t elemNum = listSize-i; /* */}

1432820cookie-checkIteration mit size_t 0 als Randbedingung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy