2011-06-04 60 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