2011-06-04 42 views
1

我已经用goto命令编写了一个脚本,但是在我想执行脚本的服务器上有一个以前的PHP版本(< 5.3),所以我必须更改代码。代码的结构是这样的:php中的goto循环问题

for($i = 0; $i < 30; $i++) // print 30 articles 
{ 
    $x = 0; 
    // choose a a feed from the db 
    // parse it 

    a: 
    foreach($feed->get_items($x, 1) as $item) 
    { 
     // create a unique id for the article of the feed 

     if($id == $dbid) 
     { 
      // if this id exists in the db, take the next article of the same feed which is not in the db 
      $x++; 
      goto a; 
     } 
     else 
     { 
      // print the original article you grabbed 
     } 

    } // end of foreach 
} // end of for 

我已经测试了一切。你有什么想法,我怎么能不用goto转换这个代码,以便正确执行?

+0

不得不删除我的第一个答案原来的代码是后编辑 – james 2011-06-04 16:51:57

+2

这就是为什么GOTO是邪恶的。 IT总是很难确定工作流程 – dynamic 2011-06-04 16:52:13

+1

@ yes123:强制性的:http://xkcd.com/292/ – damianb 2011-06-04 16:56:00

回答

1

如果不知道->get_items()电话的行为,你可以代替转到开关的使用穷举法:

for($i = 0; $i < 30; $i++) 
{ 
    $x = 0; 


    $a = 1; 
    while ($a--) 
    foreach($feed->get_items($x, 1) as $item) 
    { 

     if($id == $dbid) 
     { 
      $x++; 
      $a=1; break; 
     } 
     else 
     { 
     } 

    } // end of foreach 
} // end of for 

标签被替换为while和自我实现的停止条件。并且goto变成休息并且重置$a停止条件。

+0

作品像一个魅力,伙计!!!谢谢你! – olaf36 2011-06-04 18:05:49

+1

此代码仍然与您发布的代码一样被混淆。你可能已经删除了goto,但它并没有在精神上消失。即使你现在看起来很清楚,代码对其他人来说也是如此(甚至在几个月后)。标准的做法是使用一个标记,标记是否在db中找到了匹配的id。 – 2011-06-04 18:16:38

+0

@Anupam:的确如此。这只是goto的原始音译。 (然而,这个简化的语法结构的目的在于示例)。但是,如果不知道'$ i'和'$ x'和' - > get_item'行为的确切关系,就很难对它进行标记和重构。 – mario 2011-06-04 18:19:55

0

像这样的东西可能会工作...

function loop(){ 
    foreach($feed->get_items($x,1) as $item){ 
    if($id==$dbid){ 
     $x++; 
     loop(); 
    }else{ 

    } 
    } 
} 
for($i=0;$i<30;$++){ 
    $x=0; 
    loop(); 
} 

对不起,我删除了所有的评论,他们是讨厌。

+0

我要测试它,我会告诉你它是否工作..我尝试了这样的if语句,但它没有正常工作。 – olaf36 2011-06-04 16:56:55

+0

要注意递归。深度过多,你会导致PHP出现段错误。 (尽管它的确需要很多层) – damianb 2011-06-04 17:00:10

+0

您需要将$ x声明为全局。 – 2011-06-04 18:20:14

0

移动声明的$ x的外部for循环和休息后替换您的标签/ GOTO组合,像这样......

$x=0; 
    for($i=0;$i<30;$++) //print 30 articles 
    { 
    foreach($feed->get_items($x,1) as $item) 
    { 
     // create a unique id for the article of the feed 
     if($id==$dbid) 
     { 
     //if this id exists in the db,take the next article of the same feed which is not in the db 
      $x++; 
      continue; 
     } 
     else 
     { 
     //print the original article you grabbed 
     } 

    } // end of foreach 
    }//end of for 
+0

另外,关于使用goto:http://xkcd.com/292/ – damianb 2011-06-04 16:56:25

+0

@odsidian:我不是-1,因为我喜欢你,但打破;应该继续; ^^ – dynamic 2011-06-04 17:01:37

+0

@obsidian:是的,但通过这样做,脚本不会尝试从数据库中获取另一个Feed,如果文章不在数据库中......您在答案中省略的注释。 – olaf36 2011-06-04 17:02:20

-1

与未设置同意 - 利用突破将打破,如果循环,并保持通过迭代for循环

+0

http://us3.php.net/manual/en/control-structures.break.php中断不会影响如果块。 – damianb 2011-06-04 17:01:46

+0

对不起,我的坏黑曜石感谢清理 – tejash 2011-06-04 17:05:02

2

这个问题说明了为什么要避免goto。它可以让你在没有足够思考算法的情况下离开。

标准的做法是用一个标志。我想你也不能指望“herezthecode kthxbai”之类的答案,但在这种情况下,解释它是写代码的最佳方式 -

for($i=0;$i<30;$++){ 
    $x=0; 
    do { 
    $found = false; 
    foreach($feed->get_items($x,1) as $item){ 
     // get $id 
     if($id==$dbid){ 
     $found = true; 
     break; 
     }else{ 
     // other things 
     } 
    } 
    $x++; 
    } while($found); 
} 
+0

嗨,我的朋友。是的,这个代码有一个类似的结构与马里奥的建议。很明显,goto同时是一个祝福和诅咒。主要是一种诅咒。它可以让事情变得更容易,但这并不好。这会让程序员变得更加懒惰。 – olaf36 2011-06-06 22:23:21