Home Page Home Page Articoli Cosa sono e come funzionano le funzioni ricorsive?

Cosa sono e come funzionano le funzioni ricorsive?

Ecco tre esempi efficaci che vi spiegano come usare correttamente le funzioni ricorsive, per effettuare ricerche di file e cartelle all'interno del disco fisso, per ricostruire la struttura di un file XML oppure per svuotare determinati controlli in una Form.
Autore: Matteo Raumer Livello:
Cosa sono le funzioni ricorsive
Le funzioni ricorsive sono quelle funzioni che al loro interno hanno una chiamata a se stesse.
Di primo impatto può sembrare una cosa di poco senso destinata solo a loop infiniti e se scritte male cio è vero.
Se scritte correttamente invece si rivelano determinanti quando con esse si analizzano dati annidati come la lista delle sottodirectory di una directory.
L'algoritmo migliore per risolvere questo tipo di problemi è proprio quello di usare questo tipo di funzioni dato che ogni directory può avere n sottodirectory che a loro volta possono avere n sottodirectory etc...ed il numero di cicli annidati non lo si può decidere a priori poichè può variare da percorso a percorso.
Basta dare alla funzione ricorsiva parametri che possano ricrearsi all'interno della funzione stessa e chaimarla da un punto iniziale ed il gioco è fatto.
Questo metodo si applica in diverse situazioni in questo articolo ne vengono prese in esame 3 di utili.


Ricorsione su Directory e Files

Per l'esempio delle directory/files basta utilizzare la seguente funzione:

1) la funzione:

Codice .NET n°1
	private void LeggiDir(string pDir,TreeNode pTrn)
{
foreach (string zDirs in System.IO.Directory.GetDirectories(pDir))
{
LeggiDir(zDirs, pTrn.Nodes.Add(zDirs.Remove(0,pDir.Length+1)));
}
foreach (string zFls in System.IO.Directory.GetFiles(pDir))
{
pTrn.Nodes.Add(zFls.Remove(0,pDir.Length+1));
}
}


2) chiamo la funzione ricorsiva con un nodo iniziale:

Codice .NET n°2
	LeggiDir(@"c:\windows",miaTreeView.Nodes.Add (@"c:\windows"));


il trucco sta nel fatto che il metodo add dell'insieme nodes ritorna un nodo che a sua volta puo avere dei sottonodi percui ha il suo insieme nodes e via così.
Il ciclo si interrompe appena non ci sono sottodirectory infatti foreach non restituisce niente e quindi non viene richiamata se stessa internamente.
Se si prova a debuggare l'applicazione si rischia di impazzire, ma fortunatamete il computer si gestisce bene e sa sempre a che profondita è arrivato.
Il remove della stringa ritornata dal metodo getdirectories serve per lasciare solo il nome della directory o del file e non tutto il path.

Esempio in esecuzione sulla ricorsione di Directory
Esempio in esecuzione sulla ricorsione di Directory



Ricorsione all'interno degli elementi di un file XML

Un caso simile è quello che si debba ciclare all'interno di un documento xml per ricreare la struttura:
per compattezza del codice si deve introdurre all'inizio la direttiva:

Codice .NET n°3
using System.Xml.XPath;



1) La funzione:

Codice .NET n°4
	private void LeggiNodi(XPathNavigator pNav,TreeNode pNodo)
{
pNav.MoveToFirstChild();
do
{
switch (pNav.NodeType)
{
case XPathNodeType.Element:
LeggiNodi(pNav,pNodo.Nodes.Add("<" + pNav.LocalName + ">" ));
break;
case XPathNodeType.Text:
pNodo.Text += pNav.Value + pNodo.Text;
break;
}
} while (pNav.MoveToNext());
pNav.MoveToParent();
}


2) chiamo la funzione ricorsiva con un nodo iniziale:

Codice .NET n°5
	XPathNavigator nav = new XPathDocument(txtXml.Text).CreateNavigator();
LeggiNodi(nav,miaTreeView.Nodes.Add("XMLroot"));


Anche qui il metodo è simile al precedente, in particolare viene utilizzata la classe Xpathnavigator per "navigare" tra i nodi di un documento xml.
In paticolare viene controllato il tipo di elemento restituito dal Xpathnavigator per sapere se si tratta del contenuto di un tag o di un elemento.
In questo ultimo caso viene preso il nome del nodo, altrimenti al nodo inserito nella chiamata ricorsiva precedente viene aggiunto il suo testo.
Particolare è il ritorno al parent che serve a riportare il puntatore al successivo nodo superiore.

Esempio in esecuzione sulla ricorsione all'interno di un file XML
Esempio in esecuzione sulla ricorsione all'interno di un file XML


Ricorsione sugli oggetti di una Form

Infine un'altro metodo utile, soprattutto quando ci troviamo a dover pulire i filtri impostati da un'utente, è quello di ciclare su tutti i controlli di una form in questo modo:

1) la funzione:

Codice .NET n°6
	private void pulisci(Control pCtrl)
{
foreach (Control zObj in pCtrl.Controls)
{
switch (zObj.GetType().Name)
{
case "TextBox":
zObj.Text = "";
break;

case "ListBox":
ListBox Lst = (ListBox)zObj;
Lst.Items.Clear();
break;
default:
if (zObj.Controls.Count > 0) pulisci(zObj);
break;
}
}
}


2) chiamo la funzione ricorsiva con un nodo iniziale:

Codice .NET n°7
	pulisci(this);


Anche qui controlliamo che un controllo abbia controlli contenuti in esso altrimenti usciamo dal loop annidato.

Pro
La pulizia del codice e la dinamicità ad adattarsi ai diversi contesti

Contro
Bisogna progettarle bene per evitare loop infiniti e sono un po' complicate da debuggare, inquanto si rischia di perdere il punto dove si è arrivati.
Voto medio articolo: 4.7 Numero Voti: 3

File allegati


Matteo Raumer

Matteo Raumer

Laurea breve in Ingegneria Elettronica presso l'Universita di Padova nel 2001, e nel febbraio 2009 un'altra triennale in Ingegneria Informatica. Da anni lavoro come programmatore .NET principalmente in C#, per migrare applicativi win32 in applicazioni ASP.NET. Ho sviluppato inoltre parecchia reportistica su Crystal Re... Profilo completo

Articoli collegati

Utilizzare NUnit per testare codice .NET
Scopriamo in questo articolo come utilizzare il popolare framework Open Source NUnit per effettuare Unit Testing del codice .NET aumentandone la qualità e riducendo il numero di eventuali bugs.
Autore: Michela Zangarelli | Difficoltà:
SQL Injection, che cosa è e come difendersi
I malintenzionati sono sempre dietro l'angolo. Il SQL Injection è una delle pratiche più semplici da utilizzare per attaccare un'applicazione poco sicura e violarla o arrecare danni al database. Vediamo che cos'è e come garantire la sicurezza delle applicazioni in modo adeguato.
Autore: Alessandro Alpi | Difficoltà: | Commenti: 4
Visual Studio 2005 Team System
Scopriamo il nuovo IDE di sviluppo che copre interamente l'intero ciclo di vita del software integrando in un solo ambiente più prodotti e studiato apposta per i ruoli di Architect, Developer e Tester.
Autore: Marco Caruso | Difficoltà: | Voto:
Tutorial ADO.NET ed esempi pratici - Parte 2
Dopo aver fatto un po' di teoria su ADO.NET nella Parte 1 dell'articolo procediamo con un Tutorial pratico che ci condurrà alla creazione di un'applicazione basilare che consenta l'accesso e la modifica dei dati su un Database Access.
Autore: Stefano Passatordi | Difficoltà: | Commenti: 10
Introduzione ad ADO.NET - Parte 1
ADO.NET è uno dei componenti chiave del .NET Framework. Eredita il nome dal vecchio ADO ma è praticamente quasi tutto cambiato. Una nuova architettura, nuovi concetti, nuove funzionalità e nuovi oggetti. Vediamo quali sono e a cosa servono.
Autore: Stefano Passatordi | Difficoltà: | Commenti: 6
Colonne calcolate e parola "Child" con ADO.NET
Una cosa utile di ADO.NET e' la possibilita di aggiungere ad una colonna da codice il cui valore sia il risultato di operazioni sui dati dei record (o tra valori di altre colonne). Quando si utilizza un dataset con piu tabelle collegate mediante relazioni invece, usando la parola chiave "child" si possono avere delle informazioni riguardanti le tabelle figlio, direttamente nei record della tabella
Autore: Matteo Raumer | Difficoltà: | Voto:
Usare degli indicatori di progresso con Query SQL
Nell'articolo vediamo come sia possibile con un l'aiuto delle classi DataReader e Command di ADO.NET, mostrare un indicatore di progresso che indichi lo stato di avanzamento di una query SQL durante il fetching dei dati.
Autore: Matteo Raumer | Difficoltà: | Voto:
La crittografia e la classe Rijndael
Vediamo come utilizzare una delle tante classi messe a disposizione dal .NET Framework per la crittografia dei dati. In particolare la classe Rijndael implementa un algoritmo di crittografia molto forte diventato famoso negli ultimi anni.
Autore: David De Giacomi | Difficoltà:
DES il famoso standard creato da IBM per la crittografia dei dati
In questo articolo dimostreremo come crittografare dei file usando il .NET Framework e in particolare la classe DESCryptoServiceProvider che implementa l'ormai noto algoritmo di cifratura inventato da IBM negli anni 70 chiamato DES (Data Encryption Standard)
Autore: David De Giacomi | Difficoltà: | Commenti: 2 | Voto:
Costruire Console Applications con Visual Studio .NET
Spiegheremo in questo articolo i passi base fondamentali per costruire Console Applications utilizzando Visual Studio .NET.
Autore: David De Giacomi | Difficoltà: | Voto:
TextReader e TextWriter
Una panoramica su come utilizzare queste due classi che ci permettono di leggere e scrivere file di testo.
Autore: David De Giacomi | Difficoltà: | Commenti: 1 | Voto:
Giochiamo un po' con il registro di Windows!
Scopriamo uno degli elementi fondamentali del sistema operativo Windows e vediamo come è possibile accedervi tramite le classi offerte dal .NET Framework: Microsoft.Win32.Registry e Microsoft.Win32.RegistryKey
Autore: David De Giacomi | Difficoltà: | Commenti: 1 | Voto:
.NET Framework 1.1 Beta
Una prima panormaica sulle novità offerte dal Framework 1.1 che sarà integrato nella prossima versione di Visual Studio .NET 2003.
Autore: David De Giacomi | Difficoltà:
Cosa posso costruire con Visual Studio .NET ?
Un' introduzione sui vari tipi di progetto disponibili in Visual Studio dalle tipiche applicazioni Windows fino alle recenti applicazioni Web e agli innovativi Web Services.
Autore: David De Giacomi | Difficoltà: | Commenti: 1
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5