web-dev-qa-db-ja.com

Cプログラミングの場合とそうでない場合

Cには、forwhile、およびdo-whileの3つのループがあります。それらの違いは何ですか?

たとえば、ほとんどすべてのwhileステートメントをforステートメントに置き換えることができますよね?次に、whileを使用する利点は何ですか?

72
user355546

whileループは、常に最初に条件を評価します。

while (condition) {
  //gets executed after condition is checked
}

do/whileループは、常にdo{}最初にブロックしてから、条件を評価します。

do {
  //gets executed at least once
} while (condition); 

for loopを使用すると、カウンター変数、チェック条件、およびカウンターをすべて1行でインクリメントする方法を開始できます。

for (int x = 0; x < 100; x++) {
   //executed until x >= 100
}

結局のところ、それらはすべてループのままですが、実行方法に関してある程度の柔軟性を提供します。

ここでは、物事を明確にするのに役立つ可能性のあるさまざまな種類のループの使用の背後にあるreasoningの素晴らしい説明があります。ありがとう clyfe

forwhileの主な違いは語用論の問題です。通常、反復数がわかっている場合はforを使用し、反復数が事前にわからない場合はwhileコンストラクトを使用します。 while vs do ... while問題も実用的であり、2番目は開始時に1回命令を実行し、その後は単純なwhileと同じように動作します。


Forループは簡潔であるため、特に素晴らしいです。このforループのために

for (int x = 0; x < 100; x++) {
   //executed until x >= 100
}

whileループとして作成するには、次の手順を実行する必要があります。

int count = 0;
while (count < 100) {
  //do stuff
  count++;
}

この場合、さらに多くの情報があり、count++;はロジックで失われる可能性があります。これは、countがインクリメントされる場所と、ループのロジックの前または後にインクリメントされるべきかどうかによっては、面倒になる可能性があります。 forループでは、ループの次の反復の前にカウンター変数が常に増分され、コードにある程度の均一性が追加されます。


完全を期すために、ループ処理を行うときに役立つbreakおよびcontinueステートメントについてここで説明することはおそらく意味があります。

breakは、現在のループを即座に終了し、それ以上の反復は実行されません。

//will only run "do stuff" twice
for (int x = 0; x < 100; x++) {
  if (x == 2) {
    break;
  }
  //do stuff
}

continueは、現在の反復を終了し、次の反復に進みます。

//will run "do stuff" until x >= 100 except for when x = 2
for (int x = 0; x < 100; x++) {
  if (x == 2) {
    continue;
  }
  //do stuff
}

Forループでは、 'continue'は 'for(part1; part2; part3)'の 'part3'式を評価することに注意してください。対照的に、whileループでは、ジャンプしてループ条件を再評価するだけです。

154
Robert Greiner

速度とパフォーマンスに強い懸念がある場合、最善のアプローチは、アセンブリレベルでコンパイラによって生成されたコードを検証することです。

たとえば、次のコードは、「do-while」が少し高速であることを示しています。これは、「jmp」命令が「do-while」ループで使用されないためです。

ところで、この特定の例では、最悪の場合は「for」ループによって与えられます。 :))

int main(int argc, char* argv[])
{
    int i;
    char x[100];

    // "FOR" LOOP:
    for (i=0; i<100; i++ )
    {
        x[i] = 0;
    }

    // "WHILE" LOOP:
    i = 0;
    while (i<100 )
    {
        x[i++] = 0;
    }

    // "DO-WHILE" LOOP:
    i = 0;
    do
    {
        x[i++] = 0;
    }
    while (i<100);

    return 0;
}

//「FOR」ループ:

    010013C8  mov         dword ptr [ebp-0Ch],0
    010013CF  jmp         wmain+3Ah (10013DAh)

  for (i=0; i<100; i++ )
  {
      x[i] = 0;
    010013D1  mov         eax,dword ptr [ebp-0Ch]  <<< UPDATE i
    010013D4  add         eax,1
    010013D7  mov         dword ptr [ebp-0Ch],eax
    010013DA  cmp         dword ptr [ebp-0Ch],64h  <<< TEST
    010013DE  jge         wmain+4Ah (10013EAh)     <<< COND JUMP
    010013E0  mov         eax,dword ptr [ebp-0Ch]  <<< DO THE JOB..
    010013E3  mov         byte ptr [ebp+eax-78h],0
    010013E8  jmp         wmain+31h (10013D1h)     <<< UNCOND JUMP
  }

// "WHILE" LOOP:

  i = 0;
  010013EA  mov         dword ptr [ebp-0Ch],0
  while (i<100 )
  {
      x[i++] = 0;
    010013F1  cmp         dword ptr [ebp-0Ch],64h   <<< TEST
    010013F5  jge         wmain+6Ah (100140Ah)      <<< COND JUMP
    010013F7  mov         eax,dword ptr [ebp-0Ch]   <<< DO THE JOB..
    010013FA  mov         byte ptr [ebp+eax-78h],0
    010013FF  mov         ecx,dword ptr [ebp-0Ch]   <<< UPDATE i
    01001402  add         ecx,1
    01001405  mov         dword ptr [ebp-0Ch],ecx
    01001408  jmp         wmain+51h (10013F1h)      <<< UNCOND JUMP
  }

// "DO-WHILE" LOOP:

i = 0;
.  0100140A  mov         dword ptr [ebp-0Ch],0
  do
  {
      x[i++] = 0;
    01001411  mov         eax,dword ptr [ebp-0Ch]   <<< DO THE JOB..
    01001414  mov         byte ptr [ebp+eax-78h],0
    01001419  mov         ecx,dword ptr [ebp-0Ch]   <<< UPDATE i
    0100141C  add         ecx,1
    0100141F  mov         dword ptr [ebp-0Ch],ecx
    01001422  cmp         dword ptr [ebp-0Ch],64h   <<< TEST
    01001426  jl          wmain+71h (1001411h)      <<< COND JUMP
  }
  while (i<100);
15
psanzani

読みやすくするために

10
hoang

それらはすべて交換可能です。 1つのタイプを選択して、それ以外は永遠に使用できますが、通常は特定のタスクに便利です。 「なぜスイッチがあるのか​​、たくさんのifステートメントを使用できる」と言っているようなものです。しかし、変数の値のセットをチェックする一般的なパターンであれば、言語機能があれば便利で読みやすいです。それをするために

10
Michael Mrozek

特定の反復回数ではなく、条件が真である間にループを実行したい場合、他の誰かがはるかに簡単に理解できます。

while (cond_true)

このようなものより:

for (; cond_true ; )
8
Justin Ethier

forループは本質的には派手なwhileループであることに注意してください。 それらは同じものです。

while <some condition is true> {
   // do some stuff
   // possibly do something to change the condition
}


for ( some var, <some condition is true>; increment var ) {

}

Forループの利点は、誤って無限ループを実行するのが難しいことです。むしろ、最初のステートメントにループ変数を配置するのが一般的であるため、1つを行うとより明確になります。

whileループは、標準の増分パターンを実行していない場合により明確になります。例えば:

int x = 1;
while( x != 10 ) {
  if ( some condition )
     x = 10;
  else 
     x += 5;
}
5
Armstrongest

私が見たwith while/forループのよくある誤解の1つは、効率が異なることです。 Whileループとforループは同等に効率的です。高校のコンピューターの先生が、数値をインクリメントする必要がある場合、forループの方が反復に効率的だと言っていたことを覚えています。そうではありません。

Forループは単純に 構文的にシュガー化whileループであり、反復コードの記述を高速化します。

コンパイラーがコードを取得してコンパイルするとき、コンピューターがより低いレベル(アセンブリー)で理解し、実行しやすい形式に変換します。この変換中に、while構文とfor構文の微妙な違いが失われ、まったく同じになります。

4
Cam

このようなループを使用する必要があります。これは、ニーズに最も完全に適合しています。例えば:

for(int i = 0; i < 10; i++)
{
    print(i);
}

//or

int i = 0;
while(i < 10)
{
    print(i);
    i++;
}

明らかに、そのような状況では、「for」は「while」よりも良く見えます。また、ループの状態がチェックされる瞬間の前にいくつかの操作を既に実行する必要がある場合は、「do while」を使用する必要があります。

私の悪い英語でごめんなさい)。

4
abespalov

forは、このスキームのインデックスまたはバリアントを使用した固定反復を提案します。

whileおよびdo... whileは、毎回チェックする必要がある条件があるときに使用する構造です(インデックスに類似した構造は別として、上記を参照)。条件チェックの最初の実行が実行されるタイミングは異なります。

どちらの構造も使用できますが、ユースケースに応じて長所と短所があります。

3
Pieter

Forループは一般的にwhileループよりも多くのマシン命令を生成することに少し前に気付きました。ただし、私の観察結果を反映した例をよく見ると、違いは2つまたは3つの機械語命令であり、あまり考慮する必要はありません。

また、WHILEループの初期化子は、コードにベイクすることで削除できることに注意してください。 g .:

static int intStartWith = 100;

Static修飾子は初期値をコードに焼き付け、(ドラムロール)one MOV命令を保存します。より重要なのは、変数を静的としてマークすると、変数がスタックフレームの外側に移動することです。 MOV命令とそのオペランドは、たとえば整数、ブール値、または文字値(ANSIまたはUnicode)よりも多くのスペースをとるため、変数アライメントも許可します。

ただし、変数が8バイト境界で整列している場合、共通のデフォルト設定、int、bool、またはコードにベイク処理されたTCHARには、MOV命令と同じバイト数がかかります。

3
David A. Gray

彼らは彼らが行う仕事においてすべて同じです。それらのいずれかを使用して同じことを行うことができます。しかし、読みやすさ、使いやすさ、利便性などのために、それらは異なります。

2
rahmivolkan

Whileとdo-whileの違いは、whileがループ条件をチェックし、これが真の場合、本体が実行され、条件が再度チェックされることです。 do-whileは本体の実行後に条件をチェックするため、do-whileでは本体が少なくとも1回実行されます。

もちろん、whileループをdo-whileおよびvvとして作成できますが、これには通常、コードの重複が必要です。

2
muksie

Forループ(少なくともC99を考慮)は、増分された変数のスコープを制限するため、whileループよりも優れています。

条件が一部の入力に依存している場合、Do whileループが役立ちます。これらは、3つのループタイプの中でほとんど使用されません。

2
helpermethod

for and while:whileは初期化も更新ステートメントも必要ないため、見栄えが良く、エレガントになります。 forには、1つまたは2つまたはすべてのステートメントが欠落している可能性があります。そのため、ループの前に初期化、ループ条件、および「更新」が必要な場合に最も柔軟で明白です。ループ条件(ループの最初でテストされる)のみが必要な場合、whileはよりエレガントです。

for/whileとdo-whileの間:in do-while条件はループの最後で評価されます。ループを少なくとも1回実行する必要がある場合は、より快適です。

2
ShinTakezou

より柔軟です。 FORは、適用される場合により簡潔です。

FORは、次のような何らかのカウンタを持つループに最適です。

for (int n=0; n<max; ++n)

もちろん、他の人が指摘したように、WHILEで同じことを達成できますが、初期化、テスト、および増分は3行に分割されています。ループの本文が大きい場合は、おそらく3行に分けられています。これにより、読者が何をしているのかを見るのが難しくなります。結局のところ、「++ n」はFORの非常に一般的な3番目の要素ですが、それが唯一の可能性ではないことは確かです。 「n + = increment」またはより複雑な式を記述するループを多数作成しました。

もちろん、FORはカウンター以外のものでもうまく機能します。好む

for (int n=getFirstElementFromList(); listHasMoreElements(); n=getNextElementFromList())

等。

しかし、「次回のループ処理」ロジックがより複雑になると、FORが故障します。考慮してください:

initializeList();
while (listHasMoreElements())
{
  n=getCurrentElement();
  int status=processElement(n);
  if (status>0)
  {
    skipElements(status);
    advanceElementPointer();
  }
  else
  {
    n=-status;
    findElement(n);
  }
}

つまり、処理中に発生した条件に応じて進行プロセスが異なる場合、FORステートメントは実用的ではありません。はい、時には十分に複雑な式、三項の?:演算子などを使用して動作させることもできますが、通常はコードを読みやすくするのではなく読みにくくします。

実際には、私のループのほとんどは、ある種の配列または構造をステップスルーしています。その場合、FORループを使用しています。または、データベースからファイルまたは結果セットを読み込んでいます。その場合、WHILEループ( "while(!eof())"またはそのようなもの)を使用します。

2
Jay

do whileの特徴の1つは、完了するまでにセミコロンが必要なことです。多くの場合、マクロの影響を抑制しながら複数のステートメントを一度だけ実行するためにマクロ定義で使用されます。マクロがブロックとして定義されている場合、解析エラーが発生する可能性があります。

特に1つの説明

2
LB40

do-whileループ以外はほぼ同じです。 forループは、counter種類の変数がある場合に適しています。それは明らかです。 whileループは、以下に示すようにフラグがチェックされている場合に意味があります。

while (!done) {
   if (some condtion) 
      done = true;
}
2
fastcodejava

whileおよびforステートメントは、両方ともプログラミングのループに使用できます。 whileループを使用するか、forループを使用するかは、プログラマーに依存します。 whileループの使用に慣れている人もいれば、forループを使用している人もいます。

好きなループを使用してください。しかし - do...whileループは、Cプログラミングでは多少注意が必要です

0
Ranjit Bhatta

/ * whileループ

5ドル

1チョコレート= 1ドル

while my money is greater than 1 bucks 
  select chocolate
  pay 1 bucks to the shopkeeper
  money = money - 1
end

家に来て、買い物中に行くことはできません。なぜなら私のお金= 0ドル* /

#include<stdio.h>
int main(){
  int money = 5;

  while( money >= 1){   
    printf("inside the shopk and selecting chocolate\n");
    printf("after selecting chocolate paying 1 bucks\n");
    money = money - 1 ;  
    printf("my remaining moeny = %d\n", money);
    printf("\n\n");
  }

  printf("dont have money cant go inside the shop, money = %d",  money);

  return 0;
} 

無限のお金

while( codition ){ // condition will always true ....infinite loop
  statement(s)
}

よりよく理解するためにこのビデオをご覧ください https://www.youtube.com/watch?v=eqDv2wxDMJ8&t=25s

/ * forループ

5ドル

for my money is greater than equal to 1 bucks   0      money >= 1
  select chocolate
  pay 1 bucks to the shopkeeper
  money = money - 1  1-1 => 0
end

* /

#include<stdio.h>
int main(){

  int money = 5;
  for( ; money >= 1; ){     0>=1  false 
    printf("select chocolate \n");
    printf("paying 1 bucks to the shopkeeper\n");
    money = money - 1;    1-1 = 0
    printf(" remaining money =%d\n", money);
    printf("\n\n");
  }

  return 0;
}

理解を深めるために、 https://www.youtube.com/watch?v=_vdvyzzp-R4&t=25s をご覧ください。

0
sandeep bairwa