【问题标题】:How do recursive function calls work in loops?递归函数调用如何在循环中工作?
【发布时间】:2011-03-18 16:52:03
【问题描述】:

我有一个函数,其中有一个调用函数的循环。

function displayItem(item, isChild)
{
    if (isChild)
    {
        writeOutput('<li>' & item.name & '</li>');
    }
    else
    {
        writeOutput('<li>' & item.name);
    }
    try
    {
        if (item.hasChild)
        {
            writeOutput('<ul>');
            numberOfItems = item.numChildren;
            for (x=1;x LT numberOfItems;x++)
            {
                displayItem(item.child[x], true);
            }
            writeOutput('</ul>');
        }
    }
    catch(Exception e){}
    writeOutput('</li>');
} 

函数执行后,循环继续执行该次执行时的 x 值,而不是从之前停止的地方继续。

例如:x 为 3。displayItem 被传递“item.child[3]”并且为真。它通过函数工作,进入循环,执行循环直到 x = 4,然后退出循环。函数结束并且(据我所知)返回到 x 应该为 3 的点。它不是从 3 中拾取,加一(使其为 4)然后再次执行循环,而是从 4 中拾取(值来自递归调用的“内部”循环)。

我知道这听起来不连贯,但我想不出任何其他方式来解释它。

是我做错了什么,还是这只是生活中的一个事实,我必须解决一些问题?

更新: 仔细观察后,似乎最早的循环提前退出了。为“x”使用局部变量修复了计数问题,但如果查看前面的示例,循环只会在 4 处退出。它在满足条件之前离开。有什么想法吗?

【问题讨论】:

    标签: loops coldfusion recursion for-loop


    【解决方案1】:

    您忘记将 x 设为函数的局部变量。

    不要使用全局变量。 像瘟疫一样避开它们。

    【讨论】:

    • 理想情况下(如“如果您的语言支持”),您希望尽可能将 x 的范围限制在 for 循环周围的最小区域。这是 Ada 做对的地方之一:for 循环索引变量的范围就是循环本身。在 C++ 中,你会写“for(unsigned x=1; ...”。还要注意 hasChild 可能是多余的:numChildren > 0 可以做同样的事情。(或者是 (item.hasChild && (item.numChildren == 0)) 是一个有意义的条件?)
    • 我明白范围界定很重要,而全局变量很危险。我只是不知道语法!
    • 如果您使用的是 CF9,请在 x=1 前添加“var”。如果您使用的是 CF8 或更早版本,请将“var x = 0”添加到函数的第一行。
    • 不幸的是,这并没有改变函数的行为。 :( 我仍然得到相同的结果。从好的方面来说,我不再使用全局变量了!
    【解决方案2】:

    试试这个

    function displayItem(item, isChild)
    {
       var x = 0;
       var numberOfItems = 0;
    
       if (isChild).......................
    } 
    

    【讨论】:

    • 深思熟虑:在 cf9 中,您可以使用“本地”范围而不是 varing。 local.x = 0;
    【解决方案3】:

    问题出在这一行:

    numberOfItems = item.numChildren;
    

    从第二次调用返回时,此值不会更改回正确的值。所以如果numberOfItems在函数被自己调用的时候设置为4,在它完成并返回到函数的原始实例之后,numberOfItems仍然是4。

    此代码有效:

    function displayItem(item, isChild)
    {
        var x = 1;
        if (isChild)
        {
            writeOutput('<li>' & item.name & '</li>');
        }
        else
        {
            writeOutput('<li>' & item.name);
        }
        try
        {
            if (item.hasChild)
            {
                writeOutput('<ul>');
                for (x=1;x LT item.numChildren;x++)
                {
                    displayItem(item.child[x], true);
                }
                writeOutput('</ul>');
            }
        }
        catch(Exception e){}
        writeOutput('</li>');
    } 
    

    【讨论】:

      猜你喜欢
      • 2018-01-23
      • 2012-05-15
      • 2022-01-15
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 2018-08-23
      • 2019-09-09
      • 2014-03-15
      相关资源
      最近更新 更多