以前从未见过 C + + for 循环

我正在把一个 C + + 算法转换成 C # 。 我遇到了这个 for 循环:

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

它在 C + + 中没有给出错误,但在 C # 中有(不能将 int 转换为 bool)。 我真的不能算出这个 for 循环,条件是什么?

有人能解释一下吗?

另外,只是检查一下,把矢量调整到一个列表就可以了 B. back () 符合 B [ b 计数 -1] 我不知道你在说什么

17045 次浏览

在 C 语言中,所有非零值在“布尔”上下文中都是 true,例如循环结束条件或 If判断语句。在 C # 中,您必须使该检查显式化: u-- != 0

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

如果 u--;的值不同于0,它将被解释为 true(即隐式转换为布尔值 true)。如果它的值为0,则它将被强制转换为 false

这是 非常糟糕的代码

更新: 我讨论了在这个 博客文章中编写“ for”循环。它的建议可以总结如下段落:

For 循环是实用的、可读的(一旦您习惯了它) ,并且 但是你需要很好地使用它。因为它不常用 语法,以一种过于想象的方式使用它不是一个好主意。

For 循环的所有部分都应该简短易读 应该选择使它容易理解。

这个例子明显违反了这些建议。

for循环的条件位于两个分号 ;之间的中间。

在 C + + 中,可以将几乎任何表达式作为条件: 任何计算结果为零的表示 false; 非零表示 true

在您的示例中,条件是 u--: 当您转换到 C # 时,只需添加 != 0:

for (u = b.size(), v = b.back(); u-- != 0; v = p[v])
b[u] = v; //                     ^^^^ HERE

这个条件是 u--的结果,u--u减少之前的值。

在 C 和 C + + 中,通过隐式地进行 != 0比较,int 可以转换为 bool (0是 false,其他的都是 true)。

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

u = b.size(), v = b.back()

是初始化。

u--

就是条件。

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();

许多准确的答案,但我认为值得写出等价的 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 + + 具有隐式转换为布尔值的事实意味着条件是 u--,如果值为非零,则为真。

值得补充的是,你有一个错误的假设问“在哪里的条件”。在 C + + 和 C # (以及其他类似的语法语言)中,都可以使用空条件。在这种情况下,它总是计算为 true,因此循环将永远继续下去,或者直到某个其他条件退出(通过 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(;;)的人,所以了解它的含义是值得的。

C # 本身遇到的错误消除了疑问

假的

如我们所知,

(BOOL) FALSE = (int)0

但是 C # 不能像 C + + 那样自己处理这个问题

你..

但是必须在 C # 中显式地给出条件

U —— ! = 0

或者

U-> 0

但是仍然尽量避免这种编码实践

While 循环

上述答案是你的简化版本之一

循环。

所有答案均正确无误:-

For loop 可以通过以下各种方式使用:

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.

如果你已经习惯了 C/C + + ,这段代码并不难读,尽管它非常简洁,并不是很好的代码。那么让我来解释一下哪些部分比其他任何部分都更具有顺式思维。首先,C for 循环的一般语法如下:

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

初始化代码运行一次。然后在每个循环之前测试条件,最后在每个循环之后调用增量。在你的例子中,你会发现条件是 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 循环的每个部分只做它的工作,没有其他任何事情。在原始代码中,条件是修改变量。增量部分是做一些应该在代码块中的事情等等。

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

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

会打印出2。

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

在上面的代码中,使用 b.size()b.back()初始化 uv

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

u变成 0时,for循环将退出。