可能な重複:
forループまたはwhileループで繰り返しますか?
Cのループ-for()またはwhile()-どちらがベストですか?
for
ループの代わりにwhile
ループを使用する場合
次のループは、構文を除いて同一であると思います。もしそうなら、なぜ一方を他方よりも選ぶのですか?
int i;
for (i = 0; i < arr.length; i++) {
// do work
}
int i = 0;
while (i < arr.length) {
// do work
i++;
}
あなたの場合、for
ループのコードを1行少なくすること以外はあまり得られません。
ただし、次のようにループを宣言する場合:
for(int i = 0; i < x; i++)
i
をループのスコープ内に保持し、コードの残りの部分にエスケープさせるのではありません。
また、whileループでは、変数宣言、条件、および増分が3つの異なる場所にあります。 forループを使用すると、すべてが1つの便利で読みやすい場所にあります。
最後の考え:
もう1つの重要な注意事項。 2つの間に意味的な違いがあります。一般に、ループは無限の反復回数を持つことを意図しています。 (つまり、ファイルが読み込まれるまで..その中に何行あるかに関係なく)、forループには、より明確な反復回数が必要です。 (コレクション内のすべての要素をループします。コレクションのサイズに基づいてカウントできます。)
for
よりもwhile
を選択する理由は1つあります:可読性。
for
ループを使用することで、初期化、「ステップ」操作、および完了条件を必要とする何らかのタイプの操作を実行することが意図されていることを明確に示しています。
一方、while
を使用すると、完了条件が必要だと言っているだけです。
カウンタが必ずしも必要ではない場合、たとえばファイルから読み込んでEOFに到達するのを待っている場合は、「while」を使用します。この場合、「for」は最良の選択肢ではないかもしれません。配列の項目を通過するときは、意図をよりよく伝えるために「for」を使用します。
For()ループとwhile()ループの大きな違いの1つは、while()ループの「continue」ステートメントがループの先頭に分岐し、for()ループの1つが3番目の部分に分岐することです。 for()節[通常、変数をバンプするために使用される条件の後のもの]。
先生として、私はこれをさまざまな形や形で熟考してきました。私の提案は常に
for
- loopsはカウント用です。カウントアップ、カウントダウン。while
/_do-while
_コンストラクトは、他のすべての条件用です。 _c!=EOF
_、_diff<0.02
_など。イテレータ/列挙子は、forループに非常に適したカウンタです。すなわち、あなたのint=0; while( ... )
は私の目に恐ろしいです。
ペプシよりもコーラを選ぶ理由
WHILEループとFORループの間では、それらを同じ意味で使用できます。純粋主義者になるためには、条件の性質に基づいて決定することができます。カウントベースのループを実行している場合、FORループが最も意味があります。
for( cur = 0; cur < myList.Length; cur++ ){
doSomething( myList[cur] );
}
ロジックベースのループを実行している場合、WHILEは最もクリーンな実装を実現します
Iterator i = myObject.getIterator();
while( i.hasNext() ){
doSomething( i.next() );
}
あなたが言うように、理由はパフォーマンスではなく意味論的で審美的です(コンパイルされたコードは非常に似ている傾向があります)。
とはいえ、for
は、既知の反復回数を持つサイクルでは一般的ですが、while
は、条件がサイクル内で実行していることと必ずしも相関していないことを意味します。初めに何回の反復があるかわかりません。
一般に、ループが単一の場所に維持されるので、ループがカウントとは無関係の場合でも、常にループを好みます。 FORループを使用している場合、他の誰かがループを追加/変更することを決定するとき、FOR式内の項目を混乱させない限り、変更を行う人は一般的にそれを確信できます、ループ内の反復を中断しません。
ただし、whileループのようなものでは、プログラマーがループ本体を完全に解析し、繰り返しの方法を理解して、ループメンテナンスコードを変更せず、変更時に正しい順序に保つ必要があります。
したがって、I onlyは、FORの中間部分のみを効果的に必要とする場合にWHILEを使用します。
これらは機能的には同じですが、すべてのループ機能が一緒にあるため、forループのエラーが少ないと言えます。 iの宣言、while宣言、およびインデックスイテレータを分離する複数の行がある場合、その使用方法を忘れたり混乱したりする可能性があります。もちろんこれはすべて主観的なものです。
通常は、同じ最終結果にコンパイルされます。私は、ほとんどの場合、forまたはfor-eachを好みます。書き込み
for (;x<5;x++){
//do work
}
それほど不吉ではないが、書く
while(x<5){
x++
//do work
}
の代わりに
while(x<5){
//do work
x++
}
一部の人々を混乱させ、1つずつのエラーを引き起こす可能性があります。
Pascalのような言語では、forとwhileコンストラクトに異なるアプリケーションがありました。 Pascalでforループを次のように記述します。
for i := 1 to 5 do
begin
{ some code here }
end
したがって、iは1ずつ増加することを明示的に指定します。ここでは、明示的に終了条件を指定することはありません。したがって、実際のループ実行が開始される前に、ループが特定の所定回数実行されることがわかっている場所でのみforループを使用できます。一方、whileループの場合は、明示的な終了条件を指定できます。
i:=0;
while (i<>5) do
begin
{ some code here }
i:=i+1;
end
したがって、whileループはより柔軟です。 Cが開発された後、forおよびwhileがサポートされましたが、for構文の意味が変わり、ブール演算子を使用して明示的な終了条件を追加できました。したがって、CおよびCに似た言語のwhileおよびforの能力は同じであるため、使いやすさの問題よりも読みやすさの問題になります。
プログラミングの初期には、一般的なデータ構造は線形配列(ベクトル)であり、繰り返しパターンは配列の各要素を横断して使用することでした。このシナリオが普通だったため、言語にはこのパターンの特定の構文forループが含まれていました。この歴史的遺産とは別に、whileループを使用できます(最近ではF#のような関数型言語ではList.mapまたはList.foldを使用したいです;-)
それは主に読みやすさの問題です。通常、反復する値の範囲が定義されている場合はforループを使用します。繰り返し処理を行っていない場合、または終了条件がいつ真になるかわからない場合は、whileループを使用します。
Javaの観点から、forループはコレクションに非常に便利です。
for (Object o : objects){
o.process();
}
以下よりも読みやすいです:
int i=0;
while(i < objects.size()){
objects.get(i).process();
i++;
}
他の(非常に良い)答えに目をやると、私には見られなかったポイントがあります。 (それができた場合、私はそれを見逃して謝罪します。)
意味的には一見同じコードのスニペットを2つ紹介します。
スニペット#1:
for (int a = 0; a < arr.length; a++) {
/* do some work here */
}
スニペット#2:
int b = 0;
while (b < arr.length) {
// do work
b++;
}
彼らは同じことをしているように見えますよね?次に、各スニペットに1行追加して、何が起こるか見てみましょう。
スニペット#3:
for (int c = 0; c < arr.length; c++) {
/* do some work here */
}
printf("%d\n", c);
スニペット#4:
int d = 0;
while (d < arr.length) {
// do work
d++;
}
printf("%d\n", d);
そのため、これら4つのスニペットが埋め込まれたジャンクファイルをコンパイルすると(さらに、arr.lengthを意味する接着剤も)、次のエラーが発生します。
$ clang junk.c
junk.c:20:17: error: use of undeclared identifier 'c'
printf("%d\n", c);
^
1 diagnostic generated.
for
ループを使用すると、ダミーカウンター変数などにより局所性を持たせることができます。これにより、潜在的なシャドウイングを犠牲にして、変数名を再利用する際に衝突の可能性が大幅に減ります。 )。
for
ループとwhile
ループには意味的な違いがあります。 for
ループでは、反復回数が事前に定義されていますが、while
ループでは必要ありません。
一部の言語(Adaなど)は、for
ループカウンターをループ本体内の定数にすることでこれを強制します。したがって、たとえば次のように言うことは違法です。
for i in values'range loop
...
i := i + 1; -- this is illegal, as i is a constant within the loop body
end if;
ただし、この意味の違いは、for
ループカウンターを定数として扱わないほとんどの言語ではそれほど明確ではありません。
いずれかを決定し、プロジェクト全体でコピーして貼り付け/調整します。より少ない決定、より少ない入力、より速いコーディング。わずかなパフォーマンスの違い。
また、ジャスティンはi
をループのスコープに入れておらず、var aL = array.length
ループ外でも。次に、i
ループコンストラクター内でaL
とfor
を使用して、各ヒットで配列の長さを再計算しないようにします(varの作成を何度も繰り返します;)) 。再び否定。非常に大きなアレイが飛び回らない限り、実際にはパフォーマンス(私の答えの最初のビットを参照)。事前に配列の長さがわかっている場合は、最初に固定長で開始します(安っぽいブラウザでのメモリ割り当てのわずかな助け;)これがクライアント側であり、大量のデータがある場合)。
<script>
var i=0;
var myArray = ["D","R","Y"];//literal style will do for now;)
var aL=myArray.length; //or use 3 if known upfront
for(i;i<aL;i++){/*always do DRY things here*/}
</script>
また、条件が満たされていることを確認し、「ループ全体を完了する必要がありますか?」そうでない場合は、できるだけ早くループから抜け出すことを忘れないでください。
一般的に、whileループとforループの違いは構文であり、パフォーマンスに関連するものではありません。とはいえ、この質問はすでにJavaで対処されているようです。 Java forループvs. whileループ。パフォーマンスの違い?
簡単に言えば:
「for」ループは、反復使用に使用される傾向があります。配列を反復処理する必要があります。さまざまな理由で1〜100(または他の範囲)の数字が必要です。
「while」ループは、条件付きループになる傾向があります。条件が偽になるまで何かを続けたいと思う。 「トースト」というクラスがあり、トーストが焼けるまでトーストを調理したい場合、次のようなものになります。
while (!toast.isToasted) cook(toast);
ほとんどの場合(できない例は考えられません)、forループをwhileループとして、whileループをforループとして記述できますが、通常は最初に状況に応じて最適なものを選択します。上記のポイント。
関連トリビア:
Googleの新しい Go言語 では、whileステートメントを含めないことを決定しました。代わりに、条件句のみを持つ forステートメント を記述できます。したがって、
while (a < b) { ... }
ただ
for a < b { ... }
可読性は非常に重要なポイントですが、両方の方法で機能します。 forループをwhileループに変換します。カウンター変数を使用している場合や、そうでなければ「自然」に使用できる場合でも、そのように読みやすい場合は。これは、forの3つの部分または複数のカウンター(複雑であることに関連する)のいずれかに長い式または複雑な式がある場合に一般的です。
Knuthのloop-and-a-half は、いくつかの言語で、forループではなく、ブレークのある無限ループとしても機能します。
ただし、非常に重要な意味上の違いがあります。
for (int i = 0; i < arr.length; i++) {
if (filter(arr[i])) continue;
use(arr[i]);
}
int i = 0;
while (i < arr.length) {
if (filter(arr[i])) continue;
use(arr[i]);
i++;
}
読みやすさ。そして昔からVB 6日間wendしばらく見たら泣きたい。
ループを使用するとよい場合もあります。 true/falseを返すオブジェクトの関数を呼び出しますが、そのオブジェクト内の値を繰り返します。
C#のDataReaderの例:
List<string> strings = new List<string>();
while(DataReader.Read())
{
strings.Add(DataReader["foo"].ToString());
}
Forループを使用すると、作業を関数内にカプセル化でき、メモリ管理が向上します。また、whileループにエラーがあると、制御不能ループに陥り、すべての生命を脅かす可能性があります。
bool keepGoing = true;
while(keepgoing)
{
try
{
//something here that causes exception, fails to set keepGoing = false;
keepGoing = false;
}
catch(Exception)
{
//Do something, but forget to set keepGoing.
//maybe there is always an exception...
}
}
また、それは単なる一般的な慣行だと思います。建設のように。釘を使用して、屋根に平らな部分をスタッドに置きます。ネジを「使用」することもできますが、ネジは同じ仕事をしますが、それは一般的な習慣ではありません。
誰もそれが間違っていると言っているのではなく、私たちは「コーディングの世界を機能させ続けるためにあなたの仲間の圧力の下で折りたたんでください」と言っています。
後者は1つのライナーになる可能性があるため、while(++ i <arr.length){//動作する}
私のロジックは、イタレーションの正確なカウントを知っているときに一般的にforループを使用し、一般的に条件をチェックしたいときにwhileループを使用します。それ以外の場合は、両方とも同じ動作を示します。
適切な場合はforループを使用します。 whileソリューションには構文上の欠点があり(長い)、ループ内で呼び出しを続ける前にiをインクリメントすることを確認する必要があります。
好み。私にとって、すべてのループロジックはforステートメントに組み込まれているため、カウンター変数を宣言したり、実際のループでインクリメント/デクリメントを行う必要はありません。また、カウンター/インデックスをforステートメントに対してローカルに宣言することもできます。
理由の1つは、whileの条件が文字列になる可能性があることです。
また、「Do」をミックスに追加すると、現在の状態に関係なく、操作を少なくとも1回実行するときにdo whileループを使用できます。
以下のように定義されたwhileループ
while(condition)
このプログラミングパターンを表します。
1:
if(!condition) goto 2;
...
goto 1;
2:
一方、forループは、
for(var i = seed; condition; operation)
このパターンを表します。
var i = seed
1:
if(!condition) goto 2;
...
operation;
goto 1;
2:
両方のパターンは非常に一般的に使用されているため、名前が付けられ、言語に組み込まれています。
ループを制御するためにカウンターを定義する必要がある場合は、forループを使用します。そうでない場合は、whileループを使用します。
多くの場合、forループは並列化が簡単です。プログラムは、実行される反復回数とイテレータの値を任意の時点で事前に通知できるため、OpenMPなどのAPIを使用した並列化は簡単です。もちろん、中断して続行し、反復子を手動で変更すると、この利点はなくなります。