Pier Paolo wrote:
>
> Buona sera a tutti, spero abbiate trascorso delle belle vacanza al
> contrario di me.... Sigh!
Perché, cosa ti è successo?
> Vorrei un piccolo aiuto, un'idea su come impostare i campi di un
> database che dovrà contenere tutti i nomi dei componenti di un albero
> genealogico di una famiglia.
> Forse qualcuno lo ha già fatto e mi sa dire quanti e quali campi
> impostare e come ha risolto le relazioni figli-genitori-genitori-figli
> ecc....
Non mi è mai capitato di fare qualcosa del genere ma immagino che la
struttura dati ideale per rappresentare un albero genealogico sia una
sorta di albero ennario che come dati ha, fondamentalmente, il nome
della persona e il suo sesso e come puntatori ad altri nodi uno per il
coniuge, uno per il genitore padre, uno per il genitore madre ed un
certo numero massimo, da stabilirsi a priori, per i figli. Puntatore
nullo indicherebbe che non punta a nessun padre, madre o figlio.
Tutto ciò lo puoi implementare utilizzando un array o un database. Nel
primo caso puoi utilizzare, ad esempio, un array di elementi ognuno dei
quali sarebbe a sua volta un array di tot elementi atto a rappresentare
una persona. I puntatori non sarebbero altro che elementi numerici
puntanti alla posizione numerica dell'indice dell'array primario (o 0 se
non punta a niente). Nel secondo caso, invece, utilizzeresti un record
per ogni persona e il numero record come indice per i puntatori.
Ovviamente, in entrambi i casi, non puoi eliminare fisicamente dei
record (niente ADEL() o PACK) altrimenti perdi la significatività dei
puntatori. Potresti implementare una tecnica di riutilizzo degli
elementi cancellati. Oppure potresti utilizzare un campo apposta
progressivo come indice invece di lasciare all'ordine fisico il compito
di rappresentarlo.
Spero di averti dato una traccia utile.
EMG
Enrico Maria Giordano schrieb:
> Pier Paolo wrote:
> >
> > Buona sera a tutti, spero abbiate trascorso delle belle vacanza al
> > contrario di me.... Sigh!
> Perché, cosa ti è successo?
Influenza!!!!
> EMG
Da tempo ho provato come dici tu ma è più facile a dire che a farsi.
Infatti:
1) i nomi delle persone che costituiscono l'albero genealogico sono
inseribili spesso solo a casaccio in quanto sono disponibili spesso solo
quando vi è disponibilità di ricordi da parte dei più vecchi.
2) Non riesco a implementare una relazione uno a molti e molti a uno fra
record dello stesso database.
3) pensate che si debbano usare più database? Per esempio uno per i
figli, uno per i genitori eccc......
Siccome un figlio è a sua volta un genitore, un nonno o un bisnonno ecc...
si fa solo una grande confusione.
4) Voglio che la generazione di arrivo e partenza sia gestibile non a
priori ma da menù con default a tutti i possibili membri.
Comunque la cosa più difficile mi sembra quella della relazione uno a molti
e molti a uno all'interno dello stesso database.
Come si può risolvere?
Paolo
Pier Paolo wrote:
>
> Da tempo ho provato come dici tu ma è più facile a dire che a farsi.
Sicuramente un linguaggio come il C++ aiuterebbe molto.
> Infatti:
> 1) i nomi delle persone che costituiscono l'albero genealogico sono
> inseribili spesso solo a casaccio in quanto sono disponibili spesso solo
> quando vi è disponibilità di ricordi da parte dei più vecchi.
Non vedo il problema. Per inserire una persona basta creare un nuovo
record e riorganizzare i puntatori.
> 2) Non riesco a implementare una relazione uno a molti e molti a uno fra
> record dello stesso database.
Non ti serve una relazione del genere. Quello che ti serve è, come ti ho
già detto, un albero ennario o magari, più genericamente, un grafo. E ti
ho anche dato delle linee su come implementarlo in Clipper nonostante il
linguaggio non supporti direttamente strutture dinamiche di questo tipo
(come invece fanno il C ed il C++).
> 3) pensate che si debbano usare più database? Per esempio uno per i
> figli, uno per i genitori eccc......
> Siccome un figlio è a sua volta un genitore, un nonno o un bisnonno ecc...
> si fa solo una grande confusione.
Infatti. Ritengo che un solo DBF sia più che sufficiente. Forse non hai
colto perfettamente come dovresti realizzare il grafo. In caso dimmelo
che te lo spiego meglio.
> 4) Voglio che la generazione di arrivo e partenza sia gestibile non a
> priori ma da menù con default a tutti i possibili membri.
Spiegami bene quale sarebbe la difficoltà. Io non la vedo. Non c'è molta
differenza tra costruire un grafo che poi rimane statico e riempirlo
invece a richiesta dell'utente. In entrambi i casi hai bisogno
dell'operazione di inserimento che consiste in:
1. Creazione di un nuovo record (APPEND BLANK).
2. Memorizzazione del nome della persona e degli altri dati anagrafici
che possano servire.
3. Impostazione del campo MADRE con il numero di record effettivo della
persona "madre".
4. Analogamente per il campo PADRE.
5. Impostazione del campo CONIUGE con il numero di record dell'eventuale
coniuge già inserito (oppure zero).
6. Impostazione nel record madre del primo campo FIGLIOn libero con il
numero di record della nuova persona.
7. Analogamente nel record padre.
8. Impostazione a zero di tutti i campi FIGLIOn del nuovo record.
E inoltre puoi avere tutti gli indici che ti servono per ordinare le
persone, ad esempio, alfabeticamente ed avere così delle ricerche
rapide.
> Comunque la cosa più difficile mi sembra quella della relazione uno a molti
> e molti a uno all'interno dello stesso database.
La relazione tra genitori e figli e viceversa è data proprio dai campi
"puntatore" di cui sopra.
EMG
Certo non ti posso dare un esempio in due righe, ma quello che devi
fare e' uguale a quello che nelle aziende di produzione viene chiamata
Distinta Base.
Solitamente si usa un solo database in cui un campo rappresenta il
Padre e il secondo il figlio. Se un padre ha piu' figli, ci saranno
tanti record che hanno come primo campo il padre e secondo campo i
singoli figli.
Usando poi la tecnica della ricorsione, puoi navigare tra padre e
figli per ricostruire l'albero (esplosione) o, partendo da un figlio,
ricostruire la discenzenza (implosione).
Ciao
-----------------------------
Fabio Cresta
EDP Consultant & VO/Jasmine developer ITALY
President of Clipper/Visual Objects/Jasmine User Group Italy
e-mail: fcr...@tin.it
fcr...@windevs.com
web: http://www.windevs.com
------------------------------
Questo e' un esempio di ricorsione in Clipper
(se vuoi ne ho altri inPascal o C ma non in Vo)
si tratta di una stampa con esplosione di una distinta
basata su di una key di due fields (padre+figlio)
1 ) caa_pro =padre distinta
2) esa_pro=figlio distinta
**********
declare point[30]
declare padri[30]
**********
function livello()
liv=liv+1
padri[liv]=caa_pro
do while caa_pro=padri[liv] .and. inkey()<>27
*
set relation to esa_pro into analisi
@ prow()+1, 1 say esa_pro+"ł"
@ prow() , pcol() say analisi->des_ana+"ł"
@ prow() , pcol() say analisi->una_ana
*
point[liv]=caa_pro+esa_pro
*
SEEK esa_pro
if found()
********* ricorre !
livello()
end
SEEK point[liv]
SKIP
*
if caa_pro<>padri[liv]
liv=liv-1
if liv<1
exit
end
end
enddo
return .t.
**********
Ciao,
Eugenio Belli.
Roberto wrote:
>
> In cosa consiste la tecnica della ricorsione?
Consiste fondamentalmente in una funzione che, ad un certo punto, chiama
se stessa. Questo approccio viene naturale quando si ha a che fare con
strutture dati, appunto, ricorsive come gli alberi. In questo caso,
ricorsivo significa che da un qualunque nodo dell'albero io vedo un
sotto-albero con caratteristiche simili all'albero completo ed al quale
posso applicare la stessa funzione di ricerca che sto applicando
all'albero nella sua generalità. Da qui la ricorsione.
EMG
ora ricordo bene, ho usato un paio di volte questa tecnica durante i temi di
informatica scritti in Pascal .................. non sapevo funzionassero
anche in clipper e in vo.
Grazie di nuovo
Saluti
Roberto
Eugenio Belli <s...@hi-net.it> wrote in message 38760ee0.695092@news...
> >In cosa consiste la tecnica della ricorsione?
> >Ciao
> >Roberto
>
Eugenio Belli wrote:
>
> Questo e' un esempio di ricorsione in Clipper
Permettimi di criticare lo stile di questo esempio:
> declare point[30]
> declare padri[30]
Sintassi decisamente obsoleta a favore della più corrente
LOCAL point[30]
LOCAL padri[30]
Inoltre le dichiarazioni di cui sopra non possono stare fuori da una
funzione, come sembra nel tuo esempio. L'unico modo per poterle mettere
esterne è di dichiararle file-wide e cioè STATIC. E comunque, in
generale, le variabili non locali sono da evitare, specialmente nel caso
della ricorsione che richiede la completa "rientranza" della funzione
(leggi: niente variabili non locali).
> function livello()
> liv=liv+1
Questa variabile non è stata dichiarata né, tanto meno, inizializzata.
> padri[liv]=caa_pro
Come sopra per caa_pro.
> do while caa_pro=padri[liv] .and. inkey()<>27
In un programma non dovrebbero mai comparire costanti numeriche nude e
crude. Meglio utilizzare il simbolo K_ESC appositamente fornito
nell'header file INKEY.CH.
> if caa_pro<>padri[liv]
> liv=liv-1
> if liv<1
> exit
> end
> end
Questo è un peccato veniale, ma sarebbe meglio utilizzare i più chiari
ENDIF (anche se bisogna dire, ad onor del vero, che all'interno delle
direttive di preprocessore #command non funzionano gli endif/enddo ma ci
vogliono per forza gli end).
EMG
Si tratta di un cut&paste da un programma
scritto _molti_ anni fa, e che nonostante
tutto continua a funzionare.
Se ricordo bene lo scrissi la prima volta
con un compiler che si chiamava Quick Silver.
Non c'e' dubbio che sia obsoleto e che
non sia scritto nel miglior modo ma era
mia intenzione di dare _solo_ un' idea
di cosa fosse la ricorsione a Pier Paolo.
D'accordo sulle critiche, sono suggerimenti
che ho adottato in altri linguaggi e programmi
piu' recenti.
Saluti,
Eugenio Belli.