はい、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 構文を削除することを選択したという事実に、私は非常に失望しています。