164

私はC++アルゴリズムをC#に変換していました。私はこのforループに出くわしました:

for (u = b.size(), v = b.back(); u--; v = p[v]) 
b[u] = v;

C ++ではエラーは発生しませんが、C#ではエラーが発生します(intをboolに変換できません)。私は本当にこれをforループで理解できません、条件はどこにありますか?

誰か説明してもらえますか?

PS。確認するために、VECTORをLISTに適合させるには、b.back()はb [b.Count-1]に対応しますか?

4

12 に答える 12

321

ループの状態はfor、2つのセミコロンの間の真ん中にあります;

C ++では、ほとんどすべての式を条件として指定できます。ゼロと評価されるものはすべて、false;を意味します。ゼロ以外の意味はtrue

あなたの場合、条件はu--次のとおりです。C#に変換するときは、単に!= 0:を追加します。

for (u = b.size(), v = b.back(); u-- != 0; v = p[v]) 
    b[u] = v; //                     ^^^^ HERE
于 2012-07-31T11:22:39.317 に答える
165

正確な答えはたくさんありますが、同等のwhileループを書き出す価値があると思います。

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

と同等です:

u = b.size();
v = b.back();
while(u--) {
   b[u] = v;
   v = p[v];
}

C#に変換するときに、while()形式へのリファクタリングを検討することもできます。私の意見では、それはより明確で、新しいプログラマーにとっての罠ではなく、同様に効率的です。

他の人が指摘しているように-しかし私の答えを完全にするために-それをC#で機能させるには、に変更する必要がありwhile(u--)ますwhile(u-- != 0)

...またはwhile(u-- >0)uがネガティブに始まった場合に備えて。(OK、b.size()決して否定的ではありません-しかし、おそらく何か他のものがuを初期化した一般的なケースを考えてみてください)。

または、さらに明確にするために:

u = b.size();
v = b.back();
while(u>0) {
   u--;
   b[u] = v;
   v = p[v];
}

簡潔にするよりも明確にするほうがよい。

于 2012-07-31T16:20:44.387 に答える
66

for命令u--;の2番目の位置にあるため、条件はです。

の値がu--;0と異なる場合は、次のように解釈されますtrue(つまり、ブール値に暗黙的にキャストされますtrue)。代わりに、その値が0の場合、にキャストされfalseます。

これは非常に悪いコードです。

更新:このブログ投稿で「for」ループの記述について説明しました。その推奨事項は、次の段落に要約できます。

forループは、実用的で読みやすく(慣れれば)簡潔な構造ですが、うまく使用する必要があります。構文が一般的ではないため、想像力に富んだ方法で使用することはお勧めできません。

forループのすべての部分は短く、読みやすいものにする必要があります。変数名は、理解しやすいように選択する必要があります。

この例は明らかにこれらの推奨事項に違反しています。

于 2012-07-31T11:22:15.907 に答える
23

これは、ループのC#形式になります。

// back fetches the last element of vector in c++.
for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) 
{      
  b[u] = v;      
}

size()とback()に相当するものを置き換えるだけです。

リストを逆にして配列に格納します。しかし、C#では、このためのシステム定義関数が直接あります。したがって、このループも作成する必要はありません。

b = b.Reverse().ToArray();
于 2012-07-31T11:28:37.767 に答える
15
u = b.size(), v = b.back()

初期化です。

u--

条件です。

v = p[v]

反復です

于 2012-07-31T11:23:19.460 に答える
14

条件は、デクリメントされる前u--の値であるの結果です。u

CおよびC++では、暗黙的に比較を行うことにより、anをboolに変換できます(0はint その他はすべて)。!= 0falsetrue

b.back()はコンテナ内の最後の要素です。つまりb[b.size() - 1]、の場合size() != 0です。

于 2012-07-31T11:23:13.063 に答える
11

Cでは、ゼロ以外のすべてはtrue、ループ終了条件や条件ステートメントなどの「ブール」コンテキストにあります。C#では、そのチェックを明示的にする必要がありますu-- != 0

于 2012-07-31T11:20:49.683 に答える
6

他の人が述べているように、C ++がブール値への暗黙のキャストを持っているという事実は、条件がu--であるということを意味します。これは、値がゼロ以外の場合に真になります。

「条件付きはどこにあるのか」と尋ねる際に誤った仮定をしていることを付け加える価値があります。C ++とC#(および他の同様の構文の言語)の両方で、空の条件を設定できます。この場合、常にtrueと評価されるため、ループは永久に、または他の条件が終了するまで(、、、またはを介してreturnbreak継続しますthrow

for(int i = 0; ; ++i)
  doThisForever(i);

実際、forステートメントのどの部分も省略できます。その場合、実行されません。

一般的に、for(A; B; C){D}またはfor(A; B; C)D;になります:

{A}
loopBack:
if(!(B))
  goto escapeLoop;
{D}
{C}
goto loopBack;
escapeLoop:

A、B、C、またはDのいずれか1つ以上を省略できます。

for(;;) この結果として、無限ループを好む人もいます。私がそうしているwhile(true)のは、人気がありますが、それを「真実が真実で終わるまで」と読んでいるからfor(;;) です。

それは好みの問題ですが、それが好きなのは私だけではないので、for(;;)それが何を意味するのかを知る価値があります。

于 2012-08-01T03:04:54.080 に答える
4

すべての答えは正しいです:-

forループは、次のようにさまざまな方法で使用できます。

Single Statement inside For Loop
Multiple Statements inside For Loop
No Statement inside For Loop
Semicolon at the end of For Loop
Multiple Initialization Statement inside For
Missing Initialization in For Loop
Missing Increment/Decrement Statement
Infinite For Loop
Condition with no Conditional Operator.
于 2012-08-23T09:25:10.010 に答える
4
for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

上記のコードでuv、、はとで初期化されb.size()ますb.back()

条件がチェックされるたびに、デクリメントステートメントも実行されますu--

になるとforループは終了します。u0

于 2016-08-03T09:33:52.403 に答える
3

C#自体で発生したエラーは、疑問を解消します。forループは

FALSE

終了する条件。そして私たちが知っているように、

(BOOL)FALSE =(int)0

ただし、C ++とは異なり、C#はこれを単独で処理することはできません。だからあなたが探している条件は

u--

ただし、C#で条件を明示的に指定する必要があります。

u--!= 0

また

u-> 0

ただし、この種のコーディング方法は避けてください。ザ

whileループ

上記の回答は、あなたの最も単純化されたバージョンの1つです。

forループ。

于 2012-08-23T07:22:21.883 に答える
3

C / C ++に慣れている場合、このコードはそれほど読みにくいものではありませんが、かなり簡潔で、それほど優れたコードではありません。それでは、何よりもCismである部分について説明しましょう。まず、Cforループの一般的な構文は次のようになります。

for (<initialization> ; <condition>; <increment>)
{
    <code...>
}

初期化コードは1回実行されます。次に、条件はすべてのループの前にテストされ、最後に増分がすべてのループの後に呼び出されます。したがって、あなたの例では、条件は次のようになります。u--

u--C#ではなくCで条件として機能するのはなぜですか?Cは暗黙のうちに多くのことを変換しすぎて、問題を引き起こす可能性があるためです。数値の場合、ゼロ以外のものはすべて真であり、ゼロは偽です。したがって、b.size()-1から0までカウントダウンします。条件に副作用があるのは少し面倒で、forループのインクリメント部分に配置することをお勧めしますが、Cはたくさんあります。コードはこれを行います。私がそれを書いているなら、私はそれをもっとこのようにするでしょう:

for (u = b.size() - 1, v = b.back(); u>=0; --u) 
{
    b[u] = v;
    v = p[v]
}

この理由は、少なくとも私にとっては、より明確だからです。forループの各部分は、それが仕事であり、他には何もしません。元のコードでは、条件は変数を変更していました。インクリメント部分は、コードブロックなどにあるべきことを実行していました。

コンマ演算子もループをスローしている可能性があります。Cx=1,y=2では、コンパイラに関する限り、次のようなものが1つのステートメントのように見え、初期化コードに適合します。各パーツを評価し、最後のパーツの値を返すだけです。したがって、たとえば:

std::cout << "(1,2)=" << (1,2) << std::endl;

2を印刷します。

于 2012-08-27T17:39:00.667 に答える