do {...} while ( ) ループが必要ですか?

はい、do while ループを while ループに書き換えることができることに同意しますが、常に while ループを使用する方がよいという点には同意しません。 do while 常に少なくとも 1 回は実行され、これは非常に便利なプロパティです (最も典型的な例は (キーボードからの) 入力チェックです)

#include <stdio.h>

int main() {
    char c;

    do {
        printf("enter a number");
        scanf("%c", &c);

    } while (c < '0' ||  c > '9'); 
}

もちろん、これは while ループに書き直すことができますが、これは通常、はるかに洗練されたソリューションと見なされます。


do-while は事後条件付きのループです。ループ本体が少なくとも 1 回実行される場合に必要です。これは、ループ条件を適切に評価する前に何らかのアクションが必要なコードに必要です。 while ループを使用すると、2 つのサイトから初期化コードを呼び出す必要がありますが、do-while を使用すると、1 つのサイトからしか呼び出すことができません。

もう 1 つの例は、最初の反復の開始時に有効なオブジェクトが既にあるため、最初の反復の開始前に何も実行したくない (ループ条件の評価を含む) 場合です。例として、FindFirstFile/FindNextFile Win32 関数があります。エラーまたは最初のファイルへの検索ハンドルを返す FindFirstFile を呼び出してから、エラーが返されるまで FindNextFile を呼び出します。

擬似コード:

Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
   do {
      process( params ); //process found file
   } while( ( handle = FindNextFile( params ) ) != Error ) );
}

do { ... } while (0) マクロを適切に動作させるための重要な構成要素です。

実際のコードでは重要ではありませんが (必ずしも同意するわけではありません)、プリプロセッサの欠陥の一部を修正するためには重要です。

編集:今日、自分のコードで do/while がずっときれいな状況に遭遇しました。私はペアになった LL/SC 命令のクロスプラットフォームの抽象化を行っていました。これらは次のようにループで使用する必要があります:

do
{
  oldvalue = LL (address);
  newvalue = oldvalue + 1;
} while (!SC (address, newvalue, oldvalue));

(専門家は oldvalue が SC 実装で使用されていないことに気付くかもしれませんが、この抽象化を CAS でエミュレートできるように含まれています。)

LL と SC は、do/while が同等の while フォームよりも大幅にクリーンな状況の優れた例です。

oldvalue = LL (address);
newvalue = oldvalue + 1;
while (!SC (address, newvalue, oldvalue))
{
  oldvalue = LL (address);
  newvalue = oldvalue + 1;
}

このため、Google Go が do-while 構文を削除することを選択したという事実に、私は非常に失望しています。