2014-02-05 64 views
1
MainScreen() { 
    DisplayUI(); 
    GetInput(); 
} 
DisplayUI { 
    // prints press 1 for this 2 for that etc... 
} 
GetInput() { 
    // Gets input and calls the next approprite function according to that input e.g 1 for login etc... 
    // e.g 
    if (input == 1) { 
    Login(); 
    } 
    . 
    . 
    . 
    if (input == x) { 
    somefunc(); 
    } 
    // if the user enters an input that is not accounted for call this function 
    MainScreen(); 
} 

Login() { 
    // do some stuff 
    MainScreen(); 
} 
somefunc() { 
    // do some stuff 
    MainScreen(); 
} 

main { 
    MainScreen(); 
} 

是否存在使用上述方法(在每個函數實現結束時都有MainScreen();)的缺點?哪個更好?使用while循環或在每個其他函數定義的末尾調用main函數

在這(使用while循環和消除MainScreen();從每一個功能的結束)

哪一個更好?無論哪種情況,我都想無限期地運行我的程序。我使用了上述方法,我的程序完美地工作,是否有任何需要更改我的代碼?

main { 
    while(true){ 
     MainScreen(); // 
    } 
} 
+4

這..這不是Java。 – christopher

+0

java !!!他們沒有發佈這個更新的版本......你怎麼發現這個祕密! –

+0

嗯......我肯定會有某種'堆棧溢出'在某個時候......(?) –

回答

3

使用循環肯定更好。

在每個函數的末尾有一個MainScreen();違反了DRY原則(例如,如果您決定更改該函數名稱,則必須找到所有放置該語句的位置)。

此外,不需要遞歸,所以不要使用它。

2

遞歸方法將導致非常大的調用堆棧,並且不可避免地導致StackOverflow

因此我會推薦while循環。

0

當你調用一個函數時,你的程序在完成函數後必須知道繼續執行的位置。讓我們舉一個簡單的僞代碼程序來說明這一點:

function HelloWorld() { 
    print "Hello, World!\n"; 
} 

function Main() { 
    print "1... "; HelloWorld(); 
    print "2... "; HelloWorld(); 
    print "3... "; HelloWorld(); 
} 

Main(); 
print "Good bye.\n"; 

這個程序的輸出將是相當簡單的

1... Hello, World! 
2... Hello, World! 
3... Hello, World! 
Good bye. 

換句話說,程序調用的Main()。

主要依次打印「1 ...」,調用HelloWorld並繼續執行,打印出「2 ...」,cals HelloWorld,並繼續執行,打印出「3 ...」,調用HelloWorld a最後一次,繼續執行,因此退出。

此時,程序在調用Main之後繼續執行,因此打印告別並退出。

換句話說,對於您調用的每個函數,程序必須記住調用函數的繼續位置。它通過維護名爲調用堆棧來實現。

無論何時調用某個函數,都會將調用幀壓入該調用堆棧的頂部。該調用幀包含下一個要執行的指令的內存地址以及函數調用時在範圍內的變量的值。當函數退出時,最上面的調用幀將從調用堆棧中彈出。該程序跳轉到存儲在該框架中的內存地址,並愉快地繼續其業務。

所以調用堆棧增長與每次調用函數和縮小並在每得到一個改變來完成的功能。

在我們的小程序之上,堆疊永遠不會包含三個以上的幀(它是一個荒謬少量):

  1. 最初,呼叫幀是空的。 (堆棧大小= 0)
  2. 我們稱Main() - 推的幀(堆棧大小= 1)
    1. 我們稱print - 推的幀(堆棧大小= 2)
    2. print退出 - 彈出一個幀(堆棧大小= 1)
    3. 再重複步驟2.1和2.2兩次。
  3. Main()出口 - 彈出一個框(堆棧大小= 0)
  4. 退出程序(堆棧大小= 0)

現在,讓我們看看會發生什麼,如果我們改寫我們的程序是這樣的:

function HelloWorld() { 
    print "Hello, World\n"; 
} 

function Main() { 
    while (true) { 
     HelloWorld(); 
    } 
} 

Main(); 

這會創建一個調用HelloWorld的無限循環,我們將問候世界,直到宇宙結束(或者用戶按Ctrl + C或發生停電)。

調用堆棧會發生什麼?

  1. 開始程序。 (堆棧大小= 0)
  2. 呼叫Main() - 推的幀(堆棧大小= 1)
  3. 呼叫HelloWorld() - 推的幀(堆棧大小= 2)
  4. HelloWorld()退出 - 彈出一個幀(堆棧大小= 1 )
  5. 返回步驟3並從那裏繼續。

調用堆棧在1幀和2幀之間交替,考慮到程序永遠不會結束,這非常合理。

現在,而是採用了while循環,我們姑且稱之爲Main()HelloWorld()末:

function HelloWorld() { 
    print "Hello, World!\n"; 
    Main(); 
} 

function Main() { 
    HelloWorld(); 
} 

Main(); 

從表面上看,這造成同樣的無限循環,我們打印問候世界,直到天結束。但在引擎蓋下發生了不同的事情。你能看到它嗎?

  1. 開始程序(堆棧大小= 0)
  2. 呼叫的Main() - 推的幀(堆棧大小= 1)
  3. 呼叫的HelloWorld() - 推的幀(堆棧大小= 2)
  4. Call Main() - 推送一個幀(堆棧大小= 3)
  5. 調用HelloWOrld() - 推送一個幀(堆棧大小= 4)。

...我相信你得到的模式。

最終你的程序會崩潰,大聲抱怨堆棧溢出。

相關問題