11

ループで使用すると無限ループに入る傾向があるのにcontinuewhileループでは問題なく動作するのはforなぜですか?
ループカウンターのインクリメントは、後で使用するとループ内i++で無視されますが、ループ内では機能します。whilecontinuefor

後続のcontinueステートメントを無視する場合、カウンターのインクリメントを含むループの 3 番目のステートメントを無視しないのはなぜですか? ループの 3 番目のステートメントがループ本体の後に実行されることを考えると、ループの 3 番目のステートメントも同様であり、無視されるべきではありませんか?fori++forcontinuefor

while(i<10)   //causes infinite loop
{
    ...
    continue
    i++
    ...
}

for(i=0;i<10;i++)  //works fine and exits after 10 iterations
{
    ...
    continue
    ...
}
4

8 に答える 8

28

continueループの最初に戻るからです。ではfor、後処理i++はループ制御の不可欠な部分であり、ループ本体が再起動する前に実行されます。

while場合、i++はループ本体のもう 1 つのステートメント ( のようなものと変わりません) であり、到達する前にa = bスキップされます。continue

于 2013-05-16T22:06:16.980 に答える
11

その理由は、continueステートメントがループ本体でそれに続くステートメントをショートサーキットするためです。ループの書き方はwhile、ステートメントの後にインクリメント ステートメントがあるため、continueショート サーキットになります。whileこれは、ループを変更することで解決できます。

多くの教科書は次のように主張しています。

for (i = 0; i < N; ++i) {
    /*...*/
}

次と同等です。

i = 0;
while (i < N) {
    /*...*/
    ++i;
}

しかし、実際には、次のようになります。

j = 0;
while ((i = j++) < N) {
    /*...*/
}

または、もう少し衒学的に言うと:

i = 0;
if (i < 10) do {
    /*...*/
} while (++i, (i < 10));

whileの本体に が含まれているcontinue場合でも、 の場合と同様にインクリメントが発生するため、これらはより同等forです。後者の選択肢は、反復が完了した後にのみインクリメントを実行しますfor(前者は、反復の前にインクリメントを実行し、反復の後まで保存を延期しiます)。

于 2013-05-16T22:26:15.510 に答える
3

あなたのインクリメントiは継続後なので、実行されることはありません

while(i<10)   //causes infinite loop
{
.........
continue
i++
......
}
于 2013-05-16T22:05:05.490 に答える
2

どのループでも、continue は実行をループの先頭に戻し、continue ステートメントの後に他の命令を実行しません

この場合、for ループの定義は (標準 C ごとに) 常に実行されますが、i++; は常に実行されます。ステートメントは、continue ステートメントの後に来るため、実行されません。

于 2013-05-16T22:05:31.387 に答える
0

continueループの条件が満たされた場合、残りのブロックをバイパスし、ブロックの先頭から再開します。

次の質問は、「では、どうすればいいですか?」私が考える答えは2つあります。

例:

void foo ()
{
    size_t i = 0;
    do
    {
        /*...*/
        if ( /*...*/ )
        {
            /*...*/
            continue;
        }
        /*...*/
        i++;
    } while ( /* loop conditional */ );
}

解決策 #1:手動でインクリメントする

void foo ()
{
    size_t i = 0;
    do
    {
        /*...*/
        if ( /*...*/ )
        {
            /*...*/
            i++;
            continue;
        }
        /*...*/
        i++;
    } while ( /* loop conditional */ );
}

解決策 #2:goto *の一意に有効なアプリケーション

void foo ()
{
    size_t i = 0;
    do
    {
        /*...*/
        if ( /*...*/ )
        {
            /*...*/
            goto foo_next;
        }
        /*...*/
foo_next:
        i++;
    } while ( /* loop conditional */ );
}

goto2 つの場所でのインクリメントは技術的には同じ命令であるため、この場合は有効です。このソリューションは、反復ごとの揮発性変数がより複雑な場合に特に関連します。たとえば、複数の変数を設定したり、方程式や関数を使用して値を変更したりします。

単一のインクリメントまたはデクリメント ステートメントの場合、解決策 #1 が有利であることが判明する可能性があります。ただし、そのような実装の後にコードが変更された場合は、ステートメントの両方のインスタンスを更新することを忘れないでください (特に長期間の後に変更が行われた場合、バグが発生する可能性があります** )。したがって、解決策 2 を強くお勧めします。

goto*悪い習慣のあらゆる使用を検討する人もいます。自分で決めて、これを残すことをお勧めします:「c goto bad」のグーグル

**この必要性を思い出させるコメントで十分かもしれませんが、私のアドバイスに従った場合、反復ごとの揮発性変数は単一のステートメントに制限されます。そして私は引用します:

1 行にコメントする理由はありません

-Linus Torvalds (出典: http://yarchive.net/comp/linux/coding_style.html )

于 2015-04-03T05:30:44.903 に答える