【问题标题】:What does this for-loop mean?这个for循环是什么意思?
【发布时间】:2021-01-14 22:23:27
【问题描述】:

我偶然发现了一个代码示例中的语法,这是我以前在 PHP 中的 for 循环中从未见过的语法。

这是做什么的? 我为什么要使用它?

for(;$i<$max;){
    $i++;
    //code..
}

我发现它不一样

for($i=0;$i<$max;$i++) {
    //code...
}

我不明白上面两个例子的区别。

如果更具体地说明我的想法。 如果我们有这段代码(取自adventofcode的解决方案):https://www.reddit.com/r/adventofcode/comments/kdf85p/2020_day_15_solutions/

<?php
$cap = 2020;
$bits = [5,1,9,18,13,8,0];
$i=0;
$time = [];
foreach($bits as $bit) {
    $i++;
    $time[$bit] = $i;
    $say = 0;
}

for(;$i<$cap-1;){
    $i++;
    if(isset($time[$say])) {
        $last = $time[$say];
    }
    else {
        $last = $i;
    }
    $time[$say] = $i;
    $say = $i - $last;
}
echo $say;
?>

并将其与以下内容进行比较:

<?php
$cap = 2020;
$bits = [5,1,9,18,13,8,0];
$i=0;
$time = [];
foreach($bits as $bit) {
    $i++;
    $time[$bit] = $i;
    $say = 0;
}

for($i=0;$i<$cap-1;$i++){
    if(isset($time[$say])) {
        $last = $time[$say];
    }
    else {
        $last = $i;
    }
    $time[$say] = $i;
    $say = $i - $last;
}
echo $say;
?>

我在 $say.(376 in first example and 38 in last example) 中得到了不同的结果。 为什么我会得到不同的值?

【问题讨论】:

    标签: php for-loop


    【解决方案1】:

    基于 PHP 文档: https://www.php.net/manual/en/control-structures.for.php

    for 循环是 PHP 中最复杂的循环。他们的行为就像他们的 C 同行。 for 循环的语法是:

    for (expr1; expr2; expr3) 声明

    同时:

    每个表达式可以为空或包含多个表达式 用逗号分隔。

    所以当你的 for 循环的第一个表达式是“明显的”时,它只是一种“保存代码”的方法,所以不要提及默认的明显表达式 - 你只需“跳过”它。

    根据你的例子:

    for(;$i<$cap-1;)
    

    我们跳过了第一个表达式 (expr1),因为 $i 在代码块的前面已经定义为 0 ($i = 0;),因此它是“可跳过的”。不影响代码。

    但是,第三个表达式:

    在每次迭代结束时,都会评估(执行)expr3。

    由于我们没有在循环中提及它,我们负责处理循环本身中 $i 的“增加”(在这种情况下)。

    但是 - 代码中的主要区别在于,如果您提到第三个表达式 - 它会在 每次迭代结束时进行评估,但在代码块(您的示例)中 - 我们会增加 $i代码开头的变量。

    【讨论】:

    • 我已经更新了我的代码,希望现在我的意思更清楚了:-)
    • 非常感谢!您基本上可以(从我的示例中)键入 for($i=7;$i
    • $i = 7 因为在开始 for 循环时是 7。
    • 与其说是“一种保存代码的方法”,不如说这是一个没有意识到他们可以改用while($i&lt;$max) 的人的错误。鉴于 PHP 循环没有自己的作用域,在第三个位置没有表达式的 for 循环是毫无意义的。
    【解决方案2】:

    两个块之间的主要区别(假设$ifor(;$i&lt;$max;){ 循环之前被初始化为0)是第一个循环递增$i 运行循环代码之前,其中第二个循环递增$i 运行循环代码之后。举个简单的例子:

    function code($i) {
        echo "$i\n";
    }
    
    $max = 3;
    $i = 0;
    for(;$i<$max;){
        $i++;
        code($i);
    }
    
    for($i=0;$i<$max;$i++) {
        code($i);
    }
    

    第一个循环的输出是:

    1
    2
    3
    

    while第二个循环的输出是:

    0
    1
    2
    

    注意(正如@IMSoP 所指出的),条件子句在循环开始时执行,并且可能会产生副作用,因此您也可以使用以下代码模拟第一个循环:

    for($i=0;$i++<$max;) {
        code($i);
    }
    

    【讨论】:

    • 非常感谢!您基本上可以(从我的示例中)键入 for($i=7;$i ?(我只是好奇)
    • 否;标准for 循环中的增量子句始终在循环中的所有代码之后执行。但是,您可以在循环之前增加 $i 并将结束条件更改为 $i &lt; $cap 以产生相同的效果
    • @Nick “增量子句”(第三个表达式)总是在每次迭代结束时计算,但“条件子句”(第二个表达式)在每次迭代开始时计算,可以有副作用,并且可以是表达式列表。所以如果你想在每次迭代开始时增加,你可以把它扔进去。
    • @IMSoP 你当然是对的,我在答案中添加了一条注释,显示了使用副作用实现循环的另一种方法。
    【解决方案3】:

    C 风格的for 循环是一种相当奇特的语法。它们实际上由三个表达式组成,其中任何一个都可以为所欲为,甚至可以为空:

    • 一个表达式,在循环开始前执行一次,因为它的副作用
    • 在每次迭代开始时计算的表达式,以查看循环是否应该终止
    • 在每次迭代结束时执行其副作用的表达式

    使用它们最常见的方式是:

    • 初始化某种计数器
    • 检查计数器是否达到某个值
    • 递增或递减计数器

    但是这些根本没有内置到语言中,并且保留其中一个表达式不会应用任何默认行为,它什么也不做 - 除了将第二个表达式留空始终计算为 true

    例如:

    • for(;true;) 是一个无限循环:它什么也不做,检查true,然后什么也不做
    • for(;;)是同一个无限循环,因为中间的空表达式被认为是true
    • for($i=0;;) 只是同一个无限循环,但在运行之前将 $i 初始化为 0
    • for(;true;foo()) 是同一个循环,但函数 foo() 在每次迭代结束时运行

    在您的情况下,循环是 for(;$i&lt;$max;) 分解为:

    • 在开始循环之前,什么都不做
    • 在每次迭代开始时,如果表达式 $i&lt;$max 恰好为假,则终止
    • 在每次迭代结束时,什么都不做

    它不会做任何事情来控制 $i$max 在循环之前或循环期间的值。

    事实上,它与while($i&lt;$max) 相同,如果这样写可能会更清晰。

    显示的示例似乎以这种方式结束,因为作者想将 $i++ 移动到每次迭代的开头,而不是结尾(尽管他们为什么也遗漏了 $i=0 我不确定)。但是for 语法也支持这一点!实际上,您可以在三个位置中的任何一个位置中包含 多个 表达式,并在它们之间添加逗号;如果它们在第二个位置,则最后一个决定循环是否退出。

    所以你可以这样做:

    for($i=0; $i++,$i<=$max; )
    

    现在,$i 将在循环的开始处递增;由于它会在测试之前递增,因此您还必须将条件从 &lt; 调整为 &lt;= 以确保它可以再运行一次迭代。

    对于这种特殊情况,还有另一种方法:增加一个变量会返回一个值。如果你写++$i它返回值after递增,如果你写$i++它返回值before递增。所以这两个也可以工作:

    for($i=0; ++$i <= 10; ) echo $i, PHP_EOL;
    for($i=0; $i++ < 10; ) echo $i, PHP_EOL;
    

    【讨论】:

    • 啊。多谢!是的,无论如何,while循环对我来说似乎更“自然” :-) 只是出于好奇......没有办法处理 for 子句中的 $i++ (例如 for ($i=0;$i
    • @bestprogrammerintheworld 实际上,是的,请参阅我编辑的额外示例。
    【解决方案4】:

    在您的第一个示例中,$i 之前已在某处注册。所以 $i 可以是 0 或其他零,因为如果你使用类似的代码

    for(;$i<$max;){
        $i++;
        //code..
    }
    

    你得到了错误未定义的变量 $i,后来 $i 被注册了。

    /* example 1 */
    
    for ($i = 1; $i <= 10; $i++) {
        echo $i;
    }
    
    /* example 2 */
    
    for ($i = 1; ; $i++) {
        if ($i > 10) {
            break;
        }
        echo $i;
    }
    
    /* example 3 */
    
    $i = 1;
    for (; ; ) {
        if ($i > 10) {
            break;
        }
        echo $i;
        $i++;
    }
    

    https://www.php.net/manual/en/control-structures.for.php

    你的意思是什么?

    【讨论】:

      猜你喜欢
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-07-11
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多