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在两个分号之间;

在 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)以防万一你开始消极。(好的,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

条件是u--;, 因为它在for指令的第二个位置。

如果 的值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++ 中,anint 可以通过隐式进行比较转换为 bool != 0(0 是false,其他都是true)。

b.back()是容器中的最后一个元素,即b[b.size() - 1], when size() != 0

于 2012-07-31T11:23:13.063 回答
11

在 C 语言中,所有非零都true位于“布尔”上下文中,例如循环结束条件或条件语句。在 C# 中,您必须明确地进行检查:u-- != 0.

于 2012-07-31T11:20:49.683 回答
6

正如其他人所说,C++ 隐式转换为布尔值的事实意味着条件 is u--,如果值非零,则为真。

值得补充的是,您在询问“条件在哪里”时有一个错误的假设。在 C++ 和 C#(以及其他类似语法的语言)中,您可以有一个空的条件。在这种情况下,它总是评估为真,因此循环将永远继续,或者直到某些其他条件退出它(通过returnbreakthrow)。

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中的任何一个或多个都可以省略。

因此,一些人赞成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;

在上面的代码中,uandvb.size()and初始化b.back()

每次检查条件时,它也会执行减量语句,即u--

当变成时,for循环将退出。u0

于 2016-08-03T09:33:52.403 回答
3

C#中遇到的错误本身就解决了这个疑问。for 循环搜索一个

错误的

终止的条件。正如我们所知,

(BOOL) FALSE = (int) 0

但与 C++ 不同,C# 无法自行处理。所以你正在寻找的条件是

你——

但您必须在 C# 中明确给出条件

u-- != 0

或者

u--> 0

但还是尽量避免这种编码做法。这

while 循环

上面的回答是您最简化的版本之一

for循环。

于 2012-08-23T07:22:21.883 回答
3

如果您习惯于 C/C++,那么这段代码并不难阅读,尽管它非常简洁,而且代码也不是那么好。所以让我解释一下比其他任何东西都更像 Cism 的部分。首先,C for 循环的一般语法如下所示:

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

初始化代码运行一次。然后在每个循环之前测试条件,最后在每个循环之后调用增量。所以在你的例子中你会发现条件是u--

为什么u--在 C 而不是 C# 中作为条件工作?因为 C 隐式地将很多东西转换为 bools 并且可能会导致麻烦。对于一个数字,任何非零都是真,零是假。所以它会从 b.size()-1 倒数到 0。在条件中有副作用有点烦人,最好把它放在 for 循环的增量部分,尽管有很多 C代码做到这一点。如果我写它,我会这样做:

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

原因是,至少对我来说,它更清楚。for 循环的每个部分都完成了它的工作,仅此而已。在原始代码中,条件是修改变量。增量部分正在做一些应该在代码块等中的事情。

逗号运算符也可能会让您陷入循环。x=1,y=2在 C中,就编译器而言,类似的东西看起来像是一条语句,并且适合初始化代码。它只是评估每个部分并返回最后一个部分的值。例如:

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

会打印出 2。

于 2012-08-27T17:39:00.667 回答