在C ++ for循环之前从未见过
我正在将C ++algorithm转换为C#。 我碰到这个循环:
for (u = b.size(), v = b.back(); u--; v = p[v]) b[u] = v;
它在C ++中没有提供任何错误,但它在C#中(不能将int转换为bool)。 我真的不知道这个循环,条件在哪里?
有人可以解释吗?
PS。 只是为了检查,为了使一个VECTOR适应一个LIST,b.back()是否对应于b [b.Count-1]?
for
循环的条件在中间 – 在两个分号之间;
。
在C ++中,几乎所有expression式都可以作为一个条件来使用:任何计算结果为零的表示都是false
; 非零意味着true
。
在你的情况下,条件是:当你转换为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()格式。 在我看来,它是更清晰,更less的新程序员的陷阱,同样高效。
正如其他人已经指出的 – 但是为了让我的答案完整 – 使它在C#中工作,你需要改变while(u--)
while(u-- != 0)
。
…或者while(u-- >0)
,以防万一你开始消极。 (OK, b.size()
永远不会是负面的 – 但考虑一个可能还有别的东西被初始化的一般情况)。
或者,为了更清楚:
u = b.size(); v = b.back(); while(u>0) { u--; b[u] = v; v = p[v]; }
明确要比简洁明了更好。
条件是u--;
,因为它在for指令的第二位。
如果u--;
的值u--;
不同于0,它将被解释为true
(即,隐含地转换为布尔值true
)。 相反,如果它的值是0,它将被转换为false
。
这是非常糟糕的代码 。
更新:我在本博文中讨论了“for”循环的写法。 其build议可以概述如下:
for循环是一个实用的,可读的(一旦你习惯了)和简洁的构造,但你需要使用它。 由于其不常用的语法,以过于想象的方式使用它并不是一个好主意。
for循环的所有部分都应该简短易读。 应该selectvariables名称以便于理解。
这个例子显然违反了这些推荐。
这将是你的循环的C#forms。
// back fetches the last element of vector in c++. for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) { b[u] = v; }
只需replacesize()和back()即可。
它所做的是颠倒列表并存储在一个数组中。 但是在C#中,我们直接拥有系统定义的function。 所以你也不需要写这个循环。
b = b.Reverse().ToArray();
这个条件是u--
的结果,这是u
在递减之前的值。
在C和C ++中,通过隐式地执行!= 0
比较(0为false
,其他所有内容都为true
), int
可以转换为bool。
当size() != 0
时, b.back()
是容器中的最后一个元素,即b[b.size() - 1]
。
u = b.size(), v = b.back()
是初始化。
u--
是条件。
v = p[v]
是迭代
在C语言中,“布尔”上下文中的所有非零值都是true
,例如循环结束条件或条件语句。 在C#中,你必须明确地检查: u-- != 0
。
正如其他人所说的那样,C ++具有隐式转换为布尔值的事实意味着条件是u--
,如果该值不为零,则该值为true。
值得一提的是,在询问“条件在哪里”时,你有一个错误的假设。 在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(;;)
有利。 我这样做是因为尽pipewhile(true)
比较受欢迎,但我认为这是“直到真理结束为真”,这听起来有些启示性,而我相当于“永远”。
这是品味的问题,但是因为我不是世界上唯一喜欢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.
在C#中遇到的错误本身就消除了疑问。 for-loopsearch一个
假
条件终止。 而且据我们所知,
(BOOL)FALSE =(int)0
但是C#不能像C ++那样自行处理。 所以你正在寻找的条件是
u–
但是你必须明确地给出C#中的条件
你 – != 0
要么
你 – > 0
但是仍然试图避免这种编码实践。 该
while循环
上面所说的答案是你最简单的版本之一
for循环。
如果你已经习惯了C / C ++,这段代码就不那么难读了,尽pipe它非常简洁,并不是那么棒的代码。 所以让我解释一下比Cism更多的部分。 首先,C for循环的一般语法如下所示:
for (<initialization> ; <condition>; <increment>) { <code...> }
初始化代码运行一次。 然后在每个循环之前testing条件,最后在每个循环之后调用增量。 所以在你的例子中,你会发现条件是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] }
原因是,至less对我来说,这是更清楚的。 for循环的每个部分都是它的工作,没有别的。 在原始代码中,条件是修改variables。 增量部分正在做一些应该在代码块中的东西
逗号运算符也可能会把你扔到一个循环中。 在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;
在上面的代码中,u和v是用b.size()和b.back初始化的。
每次检查条件,它都会执行递减语句,即u–。
当你将变成0时,for循环将会退出。