我正在将 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] ?
循环的条件for
在两个分号之间;
。
在 C++ 中,几乎可以将任何表达式作为条件:任何计算结果为零的东西都意味着false
; 非零意味着true
。
在您的情况下,条件是u--
:当您转换为 C# 时,只需添加!= 0
:
for (u = b.size(), v = b.back(); u-- != 0; v = p[v])
b[u] = v; // ^^^^ HERE
很多准确的答案,但我认为写出等效的 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];
}
清晰比简洁好。
这将是循环的 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();
u = b.size(), v = b.back()
是初始化。
u--
是条件。
v = p[v]
是迭代
条件是 的结果,它是递减之前u--
的值。u
在 C 和 C++ 中,anint
可以通过隐式进行比较转换为 bool != 0
(0 是false
,其他都是true
)。
b.back()
是容器中的最后一个元素,即b[b.size() - 1]
, when size() != 0
。
在 C 语言中,所有非零都true
位于“布尔”上下文中,例如循环结束条件或条件语句。在 C# 中,您必须明确地进行检查:u-- != 0
.
正如其他人所说,C++ 隐式转换为布尔值的事实意味着条件 is u--
,如果值非零,则为真。
值得补充的是,您在询问“条件在哪里”时有一个错误的假设。在 C++ 和 C#(以及其他类似语法的语言)中,您可以有一个空的条件。在这种情况下,它总是评估为真,因此循环将永远继续,或者直到某些其他条件退出它(通过return
、break
或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中的任何一个或多个都可以省略。
因此,一些人赞成for(;;)
无限循环。我这样做是因为虽然它更受欢迎,但我将其读作“直到真相结束为真”,与我的读 作“永远”while(true)
相比,这听起来有点世界末日。for(;;)
这是一个品味问题,但因为我不是世界上唯一喜欢for(;;)
它的人,所以值得知道它的含义。
所有答案都是正确的:-
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.
for (u = b.size(), v = b.back(); u--; v = p[v])
b[u] = v;
在上面的代码中,u
andv
用b.size()
and初始化b.back()
。
每次检查条件时,它也会执行减量语句,即u--
。
当变成时,for
循环将退出。u
0
C#中遇到的错误本身就解决了这个疑问。for 循环搜索一个
错误的
终止的条件。正如我们所知,
(BOOL) FALSE = (int) 0
但与 C++ 不同,C# 无法自行处理。所以你正在寻找的条件是
你——
但您必须在 C# 中明确给出条件
u-- != 0
或者
u--> 0
但还是尽量避免这种编码做法。这
while 循环
上面的回答是您最简化的版本之一
for循环。
如果您习惯于 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。