2010-04-22 8 views
5

Dire che stiamo scrivendo una semplice funzione ricorsiva fib(n) che calcola l'ennesimo numero di Fibonacci. Ora, vogliamo che la funzione stampi l'ennesimo numero. Poiché la stessa funzione viene richiamata ripetutamente, deve essere presente una condizione che consenta solo la chiamata root a stampare. La domanda è: come scrivere questa condizione senza passare alcun argomento aggiuntivo, o usando variabili globali/statiche.Come rilevare la chiamata ricorsiva di root?

Così, abbiamo a che fare con qualcosa di simile:

int fib(int n) { 
    if(n <= 0) return 0; 
    int fn = 1; 
    if(n > 2) fn = fib(n-2) + fib(n-1); 
    if(???) cout << fn << endl; 
    return fn; 
} 

int main() { 
    fib(5); 
    return 0; 
} 

ho pensato che la chiamata radice differisce da tutti i bambini con il ritorno a un chiamante diverso, vale a dire il metodo principale in questo esempio. Volevo sapere se è possibile usare questa proprietà per scrivere la condizione e come.

Aggiornamento: si prega di notare che questo è un esempio inventato che serve solo a presentare l'idea. Questo dovrebbe essere chiaro dai tag. Non sto cercando soluzioni standard. Grazie.

+2

Come indicato in molte risposte, è pratica comune creare una funzione wrapper che avvia la ricorsione. L'elaborazione personalizzata prima/dopo (come IO) può andare lì. –

risposta

5

Il modo in cui vorrei fare questo è con una funzione di supporto:

int _fib(int n) { 
    if(n <= 0) return 0; 
    int fn = 1; 
    if(n > 2) fn = _fib(n-2) + _fib(n-1); 
    return fn; 
} 

int fib(int n) { 
    int fn=_fib(n); 
    cout << fn << endl; 
    return fn; 
} 

In alternativa, si potrebbe scrivere in questo modo (C++):

int fib(int n, bool f=true) { 
    if(n <= 0) return 0; 
    int fn = 1; 
    if(n > 2) fn = fib(n-2, false) + fib(n-1, false); 
    if(f) cout << fn << endl; 
    return fn; 
} 
+0

Bello. Ho dimenticato gli argomenti di default per un momento. –

+0

btw, la tua prima soluzione non stampa tutto? sembra che la funzione _fib dovrebbe chiamarsi, invece di fib. – Feyyaz

+0

Eh sì, piccolo errore di battitura: p – Blindy

5

La chiamata ricorsiva di radice è il punto in cui la ricorsione viene invocata, ossia l'invocazione in main. Dato che, si potrebbe riscrivere il codice leggermente (qualcosa di simile):

int fib(int n) { 
    if(n <= 0) return 0; 
    int fn = 1; 
    if(n > 2) fn = fib(n-2) + fib(n-1); 
    return fn; 
} 

int main() { 
    cout << fib(5) << endl; 
    return 0; 
} 
1

Ecco un modo difficile, anche se non sono sicuro che ne vale la pena :):

int fib(int n) { 
// if(n <= 0) return 0; 
    int isRoot; 
    if (n <= 0){ 
     isRoot = 1; 
     n = -n; 
    } 
    else isRoot = 0; 
    int fn = 1; 
    if(n > 2) fn = fib(n-2) + fib(n-1); 
    if(isRoot) cout << fn << endl; 
    return fn; 
} 

int main() { 
    fib(-5); 
    return 0; 
} 

Ma, il la funzione richiede che tu non intenda davvero mandare un valore negativo :).

1

Se davvero intenzione di chiedere se C ha accesso a una sorta di API che consente al codice in un corpo della funzione di scoprire da dove è stata chiamata la funzione di esecuzione, la risposta è no.

+1

Vero, ma * tu * (come nel programmatore) puoi decorare le chiamate per capire da dove provengono. – Blindy

+1

Le altre risposte lo coprono già. – reinierpost

0

Penso che si possa ottenere l'indirizzo di ritorno dallo stack e confrontarlo in qualche modo con l'indirizzo della funzione fib. L'indirizzo di ritorno dovrebbe essere da qualche parte vicino al parametro n a meno che n non sia passato in qualche registro, ma in C standard non dovrebbe. Devi solo sapere dove l'indirizzo di ritorno è relativo al parametro.

Problemi correlati