2012-02-07 81 views
3

我對c#很新穎,而且我試圖做一個函數來檢查某個數字是否在列表中,並且我想爲1-10000之間的每個數字運行函數。 目前看起來像這樣,但我得到System.StackOverflowException所以沒有人知道如何正確地做到這一點?循環功能中的堆棧溢出錯誤

int number = 1; 
int maxnumber = 10000; 
void LoadFavorites() 
{ 

    if (number <= maxnumber) 
    { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
     { 
      this.listBox1.Items.Add(number); 
     } 
    } 

    // Increases number by 1 and reruns 
    number = number + 1; 
    LoadFavorites(); // problem is probably here 
} 
+1

你正在遞歸嗎?那真的是你想要的嗎?或者你只是想使用一個簡單的循環? – Jason 2012-02-07 01:52:52

回答

1

你應該在循環中做這件事,而不是使用遞歸。每次你遞歸它將添加信息到堆棧,並最終你會用完堆棧空間。在這種情況下,你無限遞歸。(如果number> maxnumber,你不會阻止它的遞歸)。

void LoadFavorites() 
{ 
    int number = 1; 
    int maxnumber = 10000; 
    while (number <= maxnumber) 
    { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
     { 
      this.listBox1.Items.Add(number); 
     } 
     number = number + 1; 
    } 
} 

編輯:關於「‘‘+數+附加註釋’’」去掉)

+0

非常感謝,我會用它來代替。雖然「'」+數字+「'」就是這樣,因爲我做了最喜歡的保存系統,以避免它,例如認爲有一個最喜歡的23號時,真的有一個在7236或什麼 – user1071461 2012-02-07 01:59:09

+0

好吧,我會然後刪除其餘的信息。 – rein 2012-02-07 02:12:35

2

你是對的。你有一個沒有合適的停止條件的遞歸函數。也許你需要一個從1到100000的循環,而你需要調用函數loadFavorites()。由於您無限次地調用loadFavorites(),最終導致堆棧空間用完,導致出現stackoverflow。

例如

for(int i=number; i<maxNumber; i++) 
    { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+i+"'")) 
      { 
       this.listBox1.Items.Add(i); 
      } 

    } 
1

你要移到增加數到if語句中的一部分:

int number = 1; 
    int maxnumber = 10000; 
    void LoadFavorites() 
    { 

     if (number <= maxnumber) 
     { 
      if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
      { 
       this.listBox1.Items.Add(number); 
      } 

      // Increases number by 1 and reruns 
      number = number + 1; 
      LoadFavorites(); // problem is probably here 
     } 
    } 
1

您遞歸調用LoadFavorites沒有任何規則來結束遞歸。只是,把它放在你的內部,如果陳述...但你爲什麼不寫這樣的:

int number = 1; 
int maxnumber = 10000; 
void LoadFavorites() 
{ 
    for(var i = number; i <= maxnumber; i++) 
    { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
     { 
      this.listBox1.Items.Add(number); 
     } 
    } 
} 
2

沒有退出點,從而堆棧溢出。 您需要在遞歸調用中創建一個條件,否則它將永遠不能退出。

實施例:

void LoadFavorites() 
    { 

     if (number <= maxnumber) 
     { 
      if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
      { 
       this.listBox1.Items.Add(number); 
      } 
     } 

     // Increases number by 1 and reruns 
     number = number + 1; 

     if(number <= maxnumber) // create a condition to call this 
      LoadFavorites(); // problem is probably here 
    } 

OR一個較好的方法

void LoadFavorites() 
    { 

     if (number <= maxnumber) 
     { 
      if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
      { 
       this.listBox1.Items.Add(number++); // add number to list THEN increment number by one 
      } 
      LoadFavorites(); 
     } 

    } 
+0

我明白了...我是這樣的一個延遲,謝謝 – user1071461 2012-02-07 01:52:20

1

問題是當數> 100001,您的代碼仍然運行(由1次每次遞增,而不是退出循環) 。 所以更改代碼這樣:

if (number <= maxnumber) 
      { 
       if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
       { 
        this.listBox1.Items.Add(number); 
       } 
       number = number + 1; 
       LoadFavorites(); 
      } 
1
int number = 1; 
int maxnumber = 10000; 
void LoadFavorites() 
{ 

    if (number <= maxnumber) 
    { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
     { 
      this.listBox1.Items.Add(number); 
     } 
    } 

    // Increases number by 1 and reruns 
    number = number + 1; 
    LoadFavorites(); //**MOVE THESE: 
} 

更改爲

int number = 1; 
int maxnumber = 10000; 
void LoadFavorites() 
{ 

    if (number <= maxnumber) 
    { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) 
     { 
      this.listBox1.Items.Add(number); 
      // Increases number by 1 and reruns 
      number = number + 1; 
      LoadFavorites(); // problem is probably here 
     } 
    } 
} 

你調用從一個函數,正如你可能知道,是遞歸內的功能。然而,遞歸,你必須有一個退出條件,導致循環退出。

堆棧是線程中函數調用的順序。例如,在Java中,您有main()這是您的入口點。從main()調用函數會添加到堆棧的頂部。一旦堆棧達到一定的大小,您的計算機不能再緩衝更多的函數調用。它只是從堆棧中刪除主函數,並不知道返回的位置,因此會引發錯誤。 (一旦'main'被放棄,它會拋出錯誤,而不是一旦它試圖返回)。

更改的原因是,只有在編號爲< maxnumber時纔想繼續。這爲遞歸設置了一個條件,之後,該函數將退出。

1

的問題是,當你調用C++中的功能,它佔用一些內存(它需要的空間以存儲其變量等等)。這個內存被稱爲堆棧幀。內存在函數返回時自動返回,但如果您有遞歸函數,則在發生最終函數調用之前,不會釋放任何堆棧幀。在這種情況下,LoadFavorites會嘗試無限調用自己,並且您的計算機不包含無限量的內存。

在C++中,最好的答案通常是將其轉換爲循環 - 在這種情況下,您需要一個for循環。

void LoadFavorites() { 
    int maxnumber = 10000; 
    int number; 
    for (number = 1; number <= maxnumber; number++) { 
     if (Properties.Settings.Default.FavoriteList.Contains("'"+number+"'")) { 
      this.listBox1.Items.Add(number); 
     } 
    } 
} 

或者,你可以調用LoadFavorites進入if語句,這樣你就不會嘗試調用LoadFavorites的無數次。這可能會起作用,但根據您調用LoadFavorites的次數,您仍可能遇到同樣的錯誤。錯誤可以通過正確的編譯器優化來避免,但在這裏簡單地使用循環通常會更安全和更清晰。