「do…while」と「while」


86

重複の可能性:
Whileと
DoWhileいつwhileループの代わりにdo-whileを使用する必要がありますか?

私はしばらくプログラミングをしていて(2年間の仕事+ 4。5年の学位+ 1年間の大学入学前)、プログラミング入門コースで強制される以外にdo-whileループを使用したことはありません。こんなに根本的なことに出くわしたことがなければ、プログラミングが間違っていると感じるようになります。

正しい状況に遭遇しなかったということでしょうか?

しばらくではなくdo-whileを使用する必要があるいくつかの例は何ですか?

(私の学校教育はほとんどすべてC / C ++で行われ、私の仕事はC#で行われているため、do-whileの動作が異なるため、絶対に意味のある別の言語がある場合、これらの質問は実際には当てはまりません。)

明確にするために...私はawhileとaの違いを知っていdo-whileます。終了条件をチェックしてからタスクを実行します。do-whileタスクを実行してから、終了条件を確認します。


43
価値のあることとして、私のキャリアとして10年のプログラミングを行った後、私は1回か2回のようなdo-whileループを使用しました。
マットグリア2010

@ Matt-それで気分が良くなります。少なくともそれは私が一人ではないことを意味します。
mphair 2010

2
マットを2番目に追加し、さらに10年ほど追加します。do-whileループもめったに使用しません。
quentin-starin 2010

多くの重複。ここでは一つだというそれらの束へのリンク:stackoverflow.com/questions/3094972/...
gnovice

3
正しい「マスターの質問」はstackoverflow.com/questions/224059/の
Donal Fellows

回答:


116

ループを常に少なくとも1回実行する必要がある場合。それは一般的ではありませんが、私は時々それを使用します。それを使用したい場合の1つのケースは、再試行が必要になる可能性のあるリソースにアクセスしようとすることです。

do
{
   try to access resource...
   put up message box with retry option

} while (user says retry);

3
だから、これは「私はそのような状況に遭遇したことはない」の下で続くと思います。
mphair 2010

7
正直なところ、do..while ..を使用する必要がある状況に遭遇することはめったにありません。–
Stan R.

1
少し短いかもしれませんが、ボブは正しいです。コードブロックを少なくとも1回実行する場合は、do / whileを使用する必要があります。一度でも実行したいかどうかわからない場合は、whileループを使用する必要があります。そうは言っても、約15年の開発経験で、do / whileループよりもwhileループを何倍も使用してきました。
ConsultUtah 2010

1
まれですが、私も時々それらを使用しました。少し経つと、通常、通常のwhileループにもリファクタリングされます。これは、周囲の領域が変更されて実行されたためです...最初よりも不器用です。
ジョシュア

2
それはかなり一般的です。しかし、あなたの例でwhileループを使用しない理由はわかりません。そして、なぜこの答えが賛成されているのかわかりません。

65

コンパイラが最適化に対応していない場合は、do-whileの方が適しています。do-whileには、条件付きジャンプと無条件ジャンプがあるforとwhileとは対照的に、条件付きジャンプは1つだけです。パイプライン化され、分岐予測を行わないCPUの場合、これはタイトループのパフォーマンスに大きな違いをもたらす可能性があります。

また、ほとんどのコンパイラはこの最適化を実行するのに十分賢いので、逆コンパイルされたコードで見つかったすべてのループは通常do-whileです(逆コンパイラが後方のローカルgotoからループを再構築することさえわざわざする場合)。


5
ループ形式の選択に関連する技術情報を追加するための+1。
quentin-starin 2010

2
時期尚早であるだけでなく、役に立たない。あなたが本当に0回を反復処理する能力、すなわち、whileループを望んでいた場合、あなたはその中でジャンプバックをもたらした場合にループを囲む必要があります。
JeremyP

3
@ジェレミー:あなたが話すジャンプはループの外にあり、N回実行されていません。
Ben Voigt 2010

1
Duffのデバイスでのdo-whileの古典的な使用法(whileループが展開されたdo-whileに変換され、より大きなステップと残りを処理するためのジャンプテーブルが含まれる)も検討してください。これにより、ループのオーバーヘッドが大幅に削減されます。 memsetを、memcmp、それは10倍のスループット増加させることができるのmemcpy
ベンフォークト

それがなっています-私はあなたのコメントは、今では十年古いですが、ダフのデバイスは非常に重要な警告なしに言及すべきではありません知っている@BenVoigt少ない現代のコンパイラで効率的な、近代的なコンパイラは通常、インテリジェントアンロール簡単なターゲットマシンに最適なように自分自身をループすることができますので、 、彼らは一般的にダフのデバイスの意図を理解するためのロジックを持っていないため、それをほぼ最適化することはできません。これは、抽象的な「十分に高度なオプティマイザー」ではなく、一部のターゲットマシンのコードを最適化することについての素晴らしいレッスンです。
mtraceur

12

これをTryDeleteDirectory関数で使用しました。こんな感じでした

do
{
    try
    {
        DisableReadOnly(directory);
        directory.Delete(true);
    }
    catch (Exception)
    {
        retryDeleteDirectoryCount++;
    }
} while (Directory.Exists(fullPath) && retryDeleteDirectoryCount < 4);

いいね。これは、do ... whileにラップすることが実際に理にかなっている最初の例です。
ジョシュア

4
なぜ/どのようにこれが標準よりも優れているのwhileですか?
Josh Stodola 2010

ループは常に1回実行されるため、何かを実行して、失敗した場合は再試行することをお勧めします。通常のwhileループを使用する場合は、最初の反復で実行する前に、失敗するかどうかを確認します。
nibblyPig 2010

1
@SLCしかし、とにかくディレクトリが事前に存在するかどうかを確認したくないですか?
Josh Stodola 2010

1
@Joshこの例では、はい。ただし、ビジー状態のサーバーへの接続を開こうとした場合は、最初に接続して、応答が「ビジー」であったかどうかを確認します。もしそうなら、あなたはあきらめる前に数回再試行するでしょう。
nibblyPig 2010

11

Do whileは、何かを少なくとも1回実行したい場合に役立ちます。do whileとwhileを使用する良い例として、次のようにしたいとします。電卓。

ループを使用し、各計算の後に、その人がプログラムを終了したいかどうかを確認することで、これに取り組むことができます。これで、プログラムが開かれると、その人が少なくとも1回はこれを実行したいと考えていると想定できるため、次のことが可能になります。

do
{
    //do calculator logic here
    //prompt user for continue here
} while(cont==true);//cont is short for continue

2
実際、あなたがそれについて言及したので、どんな種類のコンソールベースのメニュー駆動型インターフェースもdo ... whileループでうまくいくでしょう。たとえば、オプションの入力を求め(一度に1つのキー)、続行または終了を選択した場合にのみ終了します。
ジョシュア

7
continueキーワードです; D
Thomas Eding 2010

Atrinithis:笑...私は滑った。そこで私を訂正してくれてありがとう。

== true必要ありません。cont == truecontがtrueの場合、trueを返します。それはまったく役に立たない。
Mr.DeleteMyMessages

11

これは一種の間接的な答えですが、この質問は私にその背後にある論理について考えさせました、そしてこれは共有する価値があるかもしれないと思いました。

他の誰もが言っdo ... whileているように、少なくとも1回は本体を実行する場合は、ループを使用します。しかし、どのような状況でそれをしたいですか?

さて、私が考えることができる最も明白なクラスの状況は、チェック条件の初期(「プライミングされていない」)値が終了したいときと同じである場合です。つまり、ループ本体を1回実行して、条件を存在しない値にプライミングしてから、その条件に基づいて実際の繰り返しを実行する必要があります。プログラマーがとても怠け者だったので、誰かがこれを制御構造にまとめることに決めました。

したがって、たとえば、タイムアウト付きのシリアルポートから文字を読み取ると、次の形式になります(Pythonの場合)。

response_buffer = []
char_read = port.read(1)

while char_read:
    response_buffer.append(char_read)
    char_read = port.read(1)

# When there's nothing to read after 1s, there is no more data

response = ''.join(response_buffer)

コードの重複に注意してください: char_read = port.read(1)。Pythonにdo ... whileループがある場合は、次を使用した可能性があります。

do:
    char_read = port.read(1)
    response_buffer.append(char_read)
while char_read

ループの新しいスコープを作成する言語の追加の利点:char_read関数の名前空間を汚染しません。ただし、これを行うためのより良い方法があることにも注意してください。それは、PythonのNone値を使用することです。

response_buffer = []
char_read = None

while char_read != '':
    char_read = port.read(1)
    response_buffer.append(char_read)

response = ''.join(response_buffer)

だからここに私のポイントの核心があります:null許容型の言語では、状況initial_value == exit_valueははるかに少ない頻度で発生します、そしてそれはあなたがそれに遭遇しない理由かもしれません。関数がNone有効な状態を示すために戻ることがまだあるので、私はそれが決して起こらないと言っているわけではありません。しかし、私の急いで簡単に考えた意見では、使用した言語が意味する値を許可していなかった場合、これはさらに多く発生します。この変数はまだ初期化されていません。

これは完全な推論ではありません。実際には、null値が一般的であるため、変数が取ることができる有効な値のセットのもう1つの要素を形成するだけです。しかし実際には、プログラマーは、変数が適切な状態にあること(ループ終了状態を含む場合があります)と、初期化されていない状態にあることを区別する方法があります。


これは私がここで読んだより興味深い回答の1つです。素晴らしい貢献。
ボブ・ムーア

2つのバージョンは同等ではありません。最初の読み取りでが返されたNone場合、whileバージョンは応答バッファーに何も正しく追加しませんが、doバージョンは常に何かを追加します。
デビッドストーン

@DavidStoneread()が戻ることはありませんNone。使用しているライブラリを使用している場合、前提は適用されません(つまり、番兵の値が可能なチェック値のセットに含まれていない)。
2016

あなたの最新の編集で、私が言うべきだったことがの''代わりであることがわかりますNone。falseと評価されるある種の値。Pythonのread機能に慣れていないところまでチョークで書きます。
デビッドストーン

@DavidStoneわかりません。をread()返す場合''、文字列には何も追加されず、空になります。
2016

7

学校に通っていたときはかなり使っていましたが、それ以降はあまり使いませんでした。

理論的には、終了条件チェックの前にループ本体を1回実行する場合に役立ちます。問題は、最初にチェックを望まないいくつかの例では、通常、終了チェックをループ本体の最後ではなく中央置きたいということです。その場合、私は体のどこかでよく知られfor (;;)ているものを使用することを好みif (condition) exit;ます。

実際、ループの終了条件に少し不安がある場合はfor (;;) {}、必要に応じて終了ステートメントを使用してループを記述し始めると便利な場合があります。完了したら、「」であるかどうかを確認できます。forの括弧内に初期化、終了条件、および/またはインクリメントコードを移動することによって「クリーンアップ」します。


5
好奇心から...なぜ「while(true)」ではなく「for(;;)」なのか?
mphair 2010

4
たぶん味だけ。私はfor(;;)「無限ループ」と同等に成長しましたwhile(true)が、立ち止まって考えなければなりません。おそらくそれは、が存在する前にCをコーディングしていたためtrueです。当時はTRUEマクロとしてしかありませんでしたが、何かバグがある場合は、マクロが0何らかの形で再定義されていないことを確信する必要がありました(それは起こりました!)。そのfor(;;)可能性はありません。あなたがwhileフォームを主張するなら、私はほとんどむしろ見たいwhile (1)です。もちろん、その後、いくつかのかもしれないと不思議のそれは手紙リットルでない場合...
TED

1
@mphair:ええ、イタリック体codeifyテキストを入力するときにエディターが入力するテキストに注意すれば、コメントフィールドに直接入力するだけです。ハイパーリンクを張っている人を見たことがありますが、それは私には少しハードコアすぎます。
TED 2010

2
@TED:loop-until-explicit-exitの私の好みの表記法は「do {} while(1);」です。ちなみに、組み込みシステムの動作では、私の通常のループパラダイムは「i = 10; do {} while(-i);」です。タイトなループの場合、これは通常のfor()よりもはるかに高速です。パフォーマンスが重要でない場合にfor()を任意に使用するよりも、アップカウントが不要な場合にループパターンとして一貫して使用する方が読みやすいと思います。
スーパーキャット2010

2
while(1)とfor(;;)の使用に加えて、everが;;と定義されたfor(EVER)を使用するコードを見てきました。
asr 2010

6

コードの一部を常に1回実行する必要があり、その結果によっては、場合によってはそれ以上実行する必要がある状況。通常のwhileループでも同じことができます。

rc = get_something();
while (rc == wrong_stuff)
{
    rc = get_something();
}

do
{
    rc = get_something();
}
while (rc == wrong_stuff);

6

do whileコードブロックを少なくとも1回実行する場合です。while一方、指定された基準によっては、常に実行されるとは限りません。


5

それはそれと同じくらい簡単です:

前提条件と事後条件

  • while(cond){...}-前提条件、チェック後にのみコードを実行します。
  • do {...} while(cond)-事後条件、コードは少なくとも1回実行されます。

今あなたは秘密を知っている..それらを賢く使う:)


1
私が言ったように、私はそれらがどのように機能するかを知っています、私はどちらの場合に一方が他方よりも理にかなっているのかわかりませんでした。
mphair 2010

ループを少なくとも1回通過する必要があることが確実にわかっている場合は、do {}を使用するのが論理的です。たとえば、配列内の要素を検索する関数があり、以前にif array.IsEmpty()を配置したことがある場合のように、return; 。そのチェックに合格した場合は、do {} whileを安全に使用できます。do-whileは、繰り返しのループとして考えるのも簡単です。「満足するまで食べる」は、do {eat();} while(!satisfied();)に変換されます。ループの前に条件をテストする方が安全であると考えられているため、より頻繁に使用されます。
ioan Paul Pirau 2010

4

この質問には適切に回答されているようですが、この非常に具体的なユースケースシナリオを追加したいと思います。do ...をもっと頻繁に使い始めるかもしれません。

do
{
   ...
} while (0)

多くの場合、複数行の#definesに使用されます。例えば:

#define compute_values     \
   area = pi * r * r;      \
   volume = area * h

これは次の場合に問題なく機能します。

r = 4;
h = 3;
compute_values;

-しかし-以下の落とし穴があります:

if (shape == circle)  compute_values;

これが拡大すると:

if (shape == circle) area = pi *r * r;
volume = area * h;

do ... while(0)ループでラップすると、適切に単一のブロックに展開されます。

if (shape == circle)
  do
  {
    area = pi * r * r;
    volume = area * h;
  } while (0);

2

これまでの回答は、do-whileの一般的な使用法を要約しています。しかし、OPは例を求めたので、ここに1つあります:ユーザー入力を取得します。ただし、ユーザーの入力が無効である可能性があります。入力を求め、検証し、有効な場合は続行し、そうでない場合は繰り返します。

do-whileを使用すると、入力が無効なときに入力を取得します。通常のwhileループでは、入力を1回取得しますが、無効な場合は、有効になるまで何度も取得します。ループの本体がより複雑になった場合、前者がより短く、よりエレガントで、保守がより簡単であることを理解するのは難しいことではありません。


私がこれにそれらを使用したことがない理由は、私が通常、ユーザーに入力の何が問題だったかを伝えることになってしまうからだと思います。つまり、条件はループの中心にありbreak、入力が正しい場合に限ります。
mphair 2010

@mphair:実際、そのような状況では、「do {} while(0);」を使用する傾向がある場合があります。「続行」を使用してループします。ユーザーの入力が受け入れられない場合。問題とメッセージが1つしかない場合は、「do {} while(1);」を使用します。と「休憩」。うまく機能しますが、再入国を要求する理由が複数ある場合は、「続行」してください。コンストラクトはよりうまく機能します。
スーパーキャット2010

2

同じ構造を複数回読み取るリーダーに使用しました。

using(IDataReader reader = connection.ExecuteReader())
{
    do
    {
        while(reader.Read())
        {
            //Read record
        }
    } while(reader.NextResult());
}

1

do whileファイルの先頭で番兵の値を読み取るときにを使用しましたが、それ以外は、この構造があまり一般的に使用されていないことは異常ではないと思います。これdo-whileは実際には状況に応じたものです。

-- file --
5
Joe
Bob
Jake
Sarah
Sue

-- code --
int MAX;
int count = 0;
do {
MAX = a.readLine();
k[count] = a.readLine();
count++;
} while(count <= MAX)

1

ほとんどの人(私を含む)がwhile(){}ループをdo {} while()よりも好む理由は次のとおりです。while(){}ループは、do..while()ループのように簡単に調整できます。真実ではない。whileループは、ある意味で「より一般的」です。また、プログラマーはパターンを把握しやすいのが好きです。whileループは、開始時にその不変条件が何であるかを示します。これは素晴らしいことです。

これが私が「より一般的な」ことについて意味することです。これを行う..whileループ:

do {
 A;
 if (condition) INV=false; 
 B;
} while(INV);

これをwhileループに変換するのは簡単です。

INV=true;
while(INV) {
 A;
 if (condition) INV=false; 
 B;
}

ここで、モデルのwhileループを取得します。

while(INV) {
     A;
     if (condition) INV=false; 
     B;
}

そして、これをdo..whileループに変換すると、この怪物が生まれます。

if (INV) {
 do
 {
         A;
         if (condition) INV=false; 
         B;

 } while(INV)
}

これで、両端に2つのチェックがあり、不変条件が変更された場合は、2か所で更新する必要があります。ある意味では、do..whileは、ツールボックス内の専用のドライバーのようなものであり、標準のドライバーが必要なすべてを実行するため、使用することはありません。


1
「do {} while(x);」を置き換える 「while(x);」にループします ループでは、Xが簡単に「プライミング」できる条件であるか、最初のパスで「自然に」真である必要があります。私にとって、ループの前のプライミングステートメントは、ループ内の何かがプライミングを必要とすることを意味し、while(x){}; "ループは、ループがゼロ回実行される可能性があることを意味します。少なくとも1回実行されるループが必要な場合は、 "(X)ながらん{};"使用ループ。
supercat

1

私は約12年前にプログラミングを行っていますが、わずか3か月前に、do-whileを使用すると非常に便利な状況に遭遇しました。条件を確認する前に、常に1回の反復が必要でした。だからあなたのビッグタイムが先にあると思います:)。


1
ほぼ毎回、問題の理解が不足していて、ひどいハッキングが発生したためです。例外はありますが、一般的に言って、やることがあれば...その間、自分がしていることを再考する必要があります... :-)
Brian Knoblauch 2010

2
もしあなたが正しいなら、プログラマーを混乱させないために、do-whileはすべてのプログラミング言語から除外されます:)。
ナレク2010

@Narek:これを書いてから7年近く経ちましたdo whileが、後悔のないより良い解決策があった状況はもっとありましたか?
chqrlie 2017年

はい、おそらくもう一度:D
Narek 2017

1

do...whileループを使わずにこれほど長く進んだことは想像できません。

現在、別のモニターに1つあり、そのプログラムにはそのようなループが複数あります。それらはすべて形式です:

do
{
    GetProspectiveResult();
}
while (!ProspectIsGood());

1

これは、サーバー/コンシューマーで非常に一般的な構造です。

DOWHILE (no shutdown requested)
   determine timeout
   wait for work(timeout)
   IF (there is work)
      REPEAT
          process
      UNTIL(wait for work(0 timeout) indicates no work)
      do what is supposed to be done at end of busy period.
   ENDIF
ENDDO

REPEAT UNTIL(cond)Ado {...} while(!cond)

場合によっては、work(0)の待機はCPUの面で安価になることがあります(タイムアウトの計算を排除しても、到着率が非常に高い場合は改善される可能性があります)。さらに、忙しい時期に提供される数を重要な統計にする多くの待ち行列理論の結果があります。(たとえば、クラインロック-第1巻を参照してください。)

同様に:

DOWHILE (no shutdown requested)
   determine timeout
   wait for work(timeout)
   IF (there is work)
      set throttle
      REPEAT
          process
      UNTIL(--throttle<0 **OR** wait for work(0 timeout) indicates no work)
   ENDIF
   check for and do other (perhaps polled) work.
ENDDO

どこcheck for and do other work効率的にサポートしていませんメインループまたはおそらくカーネルに入れて法外に高価かもしれwaitany(waitcontrol*,n)優先順位キューが他の作業を餓死かもしれないし、飢餓コントロールとしてスロットル使用されているタイプの操作や、おそらく状況を。

このタイプのバランシングはハックのように見えるかもしれませんが、必要になる場合があります。スレッドプールをブラインドで使用すると、世話人スレッドではなくスレッドプールを使用するとスレッドセーフな実装が必要になるため、更新率の高い複雑なデータ構造のプライベートキューで世話人スレッドを使用することによるパフォーマンス上の利点が完全に失われます。

疑似コード(たとえば、要求されたシャットダウンをUNTILでテストする必要があるかどうか)や世話人スレッドとスレッドプールについて議論したくありません。これは、特定のユースケースのフレーバーを提供することを目的としています。制御フロー構造。


1

これは私の個人的な意見ですが、この質問は経験に根ざした答えを求めています。

  • 私はCで38年間プログラミングを行っており、通常のコードでdo/whileループを使用することはありません。

  • この構成の唯一の説得力のある使用法は、マクロで、複数のステートメントを1つのステートメントにラップできることです。 do { multiple statements } while (0)

  • 偽のエラー検出や冗長な関数呼び出しを伴うdo/whileループの例を無数に見ました。

  • この観察についての私の説明は、プログラマーはdo/whileループの観点から考えると問題を誤ってモデル化する傾向があるということです。彼らは重要な終了条件を見逃しているか、最後に移動する初期条件の失敗の可能性を見逃しています。

これらの理由から、私は/ループがあるところにバグがあるとdowhile信じるようになり、私は定期的に初心者プログラマーにdo/を見せてくれるように挑戦しています。while近くのバグを見つけることができないループます。

このタイプのループは簡単に回避できます。aを使用しfor (;;) { ... }、必要に応じて必要な終了テストを追加します。このようなテストが複数必要になることはよくあることです。

これが典型的な例です:

/* skip the line */
do {
    c = getc(fp);
} while (c != '\n');

ファイルが改行で終わっていない場合、これは失敗します。このようなファイルの簡単な例は、空のファイルです。

より良いバージョンはこれです:

int c;  // another classic bug is to define c as char.
while ((c = getc(fp)) != EOF && c != '\n')
    continue;

あるいは、このバージョンはc変数も非表示にします。

for (;;) {
    int c = getc(fp);
    if (c == EOF || c == '\n')
        break;
}

検索してみてください while (c != '\n');任意の検索エンジンで検索しと、次のようなバグが見つかります(2017年6月24日取得):

ftp://ftp.dante.de/tex-archive/biblio/tib/src/streams.c、機能getword(stream,p,ignore)、持ってdo/whileと案の定、少なくとも2個のバグを:

  • c以下のように定義されるcharと、
  • 潜在的な無限ループがあります while (c!='\n') c=getc(stream);

結論:do/whileループを回避し、バグが見つかったら探します。


1
while() {}ループは初期チェックの点でより安全であるため、ループを避けることを好みます。そのため、「頭を悩ませる」傾向があり、より良いアルゴリズムを考えるのが面倒になり、不要なエラーチェックが大量に発生するなどです。「do{}while()使用不足」は悪い(頭の悪い)または初心者のプログラマーの兆候は、低品質で遅いコードを生成します。だから私は最初に「厳密にwhile(){}の場合ですか?」と自問します。そうでない場合-より多くの思考と入力データの精度が必要になる可能性があるにもかかわらず、do whileループを書き込もうとします
xakepp 3519

私はあなたの答えを理解していますが、これが実際に良くなるいくつかの可能なシナリオを考えることができます。while:prnt.sc/v2zy04またはdo while:prnt.sc/v2zykaをご覧ください。私はあなたがいる限りプログラマーではありませんでしたが、そこにバグを見つけることができませんでした。ループに入るのにwhileの追加チェックを必要としないので、dowhileがよりクリーンであることはかなり明らかです。コードの最適化について話しているなら、それはかなりクリーンだと思います。
RoyBerris20年

@RoyBerris:あなたの例は興味深いものです。Cプログラムでは、ループ内で使用される関数は、失敗しないことを確認するために追加のテストが必要になります。これにより、余分な混乱breakreturnステートメントが追加されます。ターニングdo/whileにループをfor(;;)ループすると、より一貫性の私見であること。この声明に対する私の陶片追放は、それが適切なツールであるというまれな場合strncpy() でも使用を拒否することに似ています。これらの構造はほとんどの場合、見つけるのが難しいバグの原因であるため、カジュアルな読者に無害だと思わせないでください。 。
chqrlie

@chqrlieが元の答えを見たのは、どちらの答えでもうまくいくと思うC言語に関するものでした。C#は、その前身よりもはるかに「節約」されているため、技術的にはdowhileを使用すると高速になります。
ロイベリス

0

whileループはループの前に条件をチェックし、ループはdo...whileループの後に条件をチェックします。これは、ループの実行による副作用に基づいて条件を設定する場合、または他のポスターが述べているように、ループを少なくとも1回実行する場合に役立ちます。

私はあなたがどこから来たのか理解していますが、do-whileそれはほとんど使用されないものであり、私は自分自身を使用したことがありません。あなたはそれを間違ってやっていない。

あなたはそれを間違ってやっていない。これは、byteプリミティブを使用したことがないため、誰かが間違っていると言っているようなものです。それほど一般的に使用されているわけではありません。


0

do/whileループを使用する場合に遭遇する最も一般的なシナリオは、いくつかの入力に基づいて実行され、ユーザーが好きなだけ繰り返す小さなコンソールプログラムです。明らかに、コンソールプログラムを何度も実行することは意味がありません。しかし、最初の時を超えて、それはユーザー次第です-したがって、do/whileだけではなくwhile

これにより、ユーザーは必要に応じてさまざまな入力を試すことができます。

do
{
   int input = GetInt("Enter any integer");
   // Do something with input.
}
while (GetBool("Go again?"));

最近では、ソフトウェア開発者が使用するdo/while少なくなっているのではないかと思います。今では、事実上すべてのプログラムに何らかのGUIがあります。指示を提供したり、ユーザーに新しい情報を表示したりするために出力を継続的に更新する必要があるため、コンソールアプリの方が理にかなっています。対照的に、GUIを使用すると、その情報をユーザーに提供するテキストはフォームに表示されるだけで、プログラムで繰り返す必要はありません。


0

ファイルを読み込むときは、常にdo-whileループを使用します。ヘッダーにコメントを含む多くのテキストファイルを使用しています。

# some comments
# some more comments
column1 column2
  1.234   5.678
  9.012   3.456
    ...     ...

do-whileループを使用して、「column1 column2」行まで読み取り、目的の列を検索できるようにします。擬似コードは次のとおりです。

do {
    line = read_line();
} while ( line[0] == '#');
/* parse line */

次に、whileループを実行して、ファイルの残りの部分を読み取ります。


どこでもファイルにコメントを支えるあなただけ置けば些細なこと(および全体的なコードを簡素化する)だろうif (line[0]=='#') continue;右後read_line...あなたのメインのwhileループで呼び出し
R .. GitHubのSTOPはICE手助け

ヘッダーを見つけるための提案をどのように実装するかわかりません。(ダン、コメントのコードをフォーマットする方法を理解できません、plzヘルプ!)header = false; while(!ヘッダー){line = read_line(); if(line [0] == '#')続行; ヘッダー= true; }これはあなたにとってより明確/単純ですか?
2010

0

ギーザープログラマーである私の学校のプログラミングプロジェクトの多くは、テキストメニュー主導のインタラクションを使用していました。事実上すべてがメイン手順に次のロジックのようなものを使用しました:

do
    display options
    get choice
    perform action appropriate to choice
while choice is something other than exit

学生時代から、whileループをより頻繁に使用することがわかりました。


0

結果セットを見ると、私が見たアプリケーションの1つはOracleにあります。

結果セットを取得したら、最初にその結果からフェッチし(do)、その時点から..フェッチが要素を返すかどうかを確認します(要素が見つかっている間..)..他の "にも同じことが当てはまる可能性があります。フェッチのような」実装。


0

utf-8文字列の次の文字位置を返す関数で使用しました。

char *next_utf8_character(const char *txt)
{
    if (!txt || *txt == '\0')
        return txt;

    do {
        txt++;
    } while (((signed char) *txt) < 0 && (((unsigned char) *txt) & 0xc0) == 0xc0)

    return (char *)txt;
}

この関数は心から書かれており、テストされていないことに注意してください。重要なのは、とにかく最初のステップを実行する必要があり、状態を評価する前にそれを実行する必要があるということです。


それは厄介な書き方*(unsigned char *)txt-0x80U<0x40です。
R .. GitHub STOP HELPING ICE 2010

0

あらゆる種類のコンソール入力は、最初にプロンプ​​トを表示し、入力の検証が失敗するたびに再プロンプトを表示するため、do-whileで適切に機能します。


0

ここにはたくさんの答えがありますが、私の考えです。それはすべて最適化に帰着します。1つがもう1つよりも速い2つの例を示します。

ケース1: while

string fileName = string.Empty, fullPath = string.Empty;

while (string.IsNullOrEmpty(fileName) || File.Exists(fullPath))
{
    fileName = Guid.NewGuid().ToString() + fileExtension;
    fullPath = Path.Combine(uploadDirectory, fileName);
}

ケース2: do while

string fileName = string.Empty, fullPath = string.Empty;

do
{
    fileName = Guid.NewGuid().ToString() + fileExtension;
    fullPath = Path.Combine(uploadDirectory, fileName);
}
while (File.Exists(fullPath));

したがって、2つはまったく同じことをします。ただし、基本的な違いが1つあります。それは、whileを入力するには、whileに追加のステートメントが必要なことです。これは醜いです。なぜならGuid、1つのバリアントを除いて、クラスのすべての可能なシナリオがすでに実行されているとしましょう。これは、私が5,316,911,983,139,663,491,615,228,241,121,400,000時間をループする必要があることを意味します。whileステートメントの最後に到達するたびに、string.IsNullOrEmpty(fileName)チェックを行う必要があります。したがって、これには少し時間がかかり、CPU作業のごく一部になります。しかし、この非常に小さなタスクは、Guidクラスが持つ可能性のある組み合わせの時間であり、時間、日、月、または余分な時間について話しているのでしょうか?

もちろん、これは極端な例です。これは、本番環境ではおそらく見られないためです。しかし、YouTubeのアルゴリズムについて考えると、すでにいくつかのIDが取得されているIDの生成に遭遇する可能性が非常に高くなります。つまり、大きなプロジェクトと最適化に帰着します。



-1

私は、自分が抱えている状況に使用する適切なループを調査しているときに、これに遭遇しました。これは、do .. whileループがwhileループよりも優れた実装であるという一般的な状況を完全に満たすと思います(C#言語、それが仕事の主要なものであると述べたため)。

SQLクエリの結果に基づいて文字列のリストを生成しています。私のクエリによって返されるオブジェクトはSQLDataReaderです。このオブジェクトには、オブジェクトをデータの次の行に進め、別の行があった場合にtrueを返すRead()という関数があります。別の行がない場合はfalseを返します。

この情報を使用して、各行をリストに戻し、返すデータがなくなったら停止します。Do ... Whileループは、別の行があるかどうかを確認する前にリストへの項目の追加が確実に行われるため、この状況で最適に機能します。while(condition)をチェックする前にこれを行う必要がある理由は、チェックすると、それも進むためです。この状況でwhileループを使用すると、その特定の関数の性質により、最初の行がバイパスされます。

要するに:

これは私の状況では機能しません。

    //This will skip the first row because Read() returns true after advancing.
    while (_read.NextResult())
           {
               list.Add(_read.GetValue(0).ToString());
           }

   return list;

この意志。

    //This will make sure the currently read row is added before advancing.
    do
        {
            list.Add(_read.GetValue(0).ToString());
        } 
        while (_read.NextResult());

    return list;

SQLDataReaderの使用法は、ネストされたループになります。Read()最初のRead()呼び出しは最初の行にアクセスするため、内側の呼び出しはwhileループである必要があります。NextResult()最初の結果データセットは最初のNextResult()呼び出しの前にアクティブであるため、外側の1つは呼び出し、do-whileである必要があります。特にコメントがコードと一致せず、間違っているため、コードスニペットはあまり意味がありません。
BenVoigt19年

-1
Console.WriteLine("hoeveel keer moet je de zin schrijven?");
        int aantal = Convert.ToInt32(Console.ReadLine());
        int counter = 0;

        while ( counter <= aantal)
        {
            Console.WriteLine("Ik mag geen stiften gooien");
            counter = counter + 1;

自分の質問に、他の人の質問に答えるかのように答える必要があります。説明とコードが含まれています
Simon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.