Il processo di programmazione
Una volta compresi i concetti di base, programmare si riduce ad un processo iterativo. Sarà sufficiente eseguire i passi necessari tante volte quante ne necessiterà la messa a punto del programma. All'inizio si eseguiranno molte verifiche, spendendo molto tempo in prove ed errori; via che, però, si acquisirà familiarità con il linguaggio, si procederà sempre più speditamente e si imparerà ad eseguire a mente i test preliminari.
I passi necessari per eseguire un buon programma:
- Identificare il problema.
- Suddividere il problema nei suoi elementi fondamentali.
- Realizzare le varie parti del programma.
- Testare e mettere a punto ogni parte realizzata.
- Assemblare le varie parti.
- Testare tutto il programma.
Ci sono però alcune cose che è necessario ricordare quando si inizia:
- Cercare di delineare chiaramente il problema prima di tentarne la risoluzione. In caso contrario rischieremmo di dover eseguire un sacco di modifiche, buttando via codice già scritto, ripartendo daccapo molte volte o dovendoci, alla fine, accontentarci di un prodotto di molto inferiore alle nostre aspettative.
- Suddividere il problema in parti più facilmente gestibili, invece di cercare di risolvere tutto in una volta.
- Testare e correggere (debug) il codice non appena scritto. Verificare sempre che il codice faccia esattamente quello per cui lo abbiamo scritto. Il debugging è il processo di ricerca e correzione dei problemi che impediscono ai programmi di fare quello per cui sono stati realizzati.
- Perfezionare la struttura dei dati ed i loro contenitori affinché il programma riesca a manipolarli agevolmente ed efficientemente. Questo spesso significa dover strutturare correttamente le proprie tabelle.
Il rimanente di questa sezione mostrerà i vari passi necessari a costruire un piccolo applicativo in Visual FoxPro.
Identificare il Problema
Prima di tentare di risolvere un problema, è necessario formularlo in maniera corretta. Qualche volta, trovando il giusto modi di formulare un problema, si è in grado di individuare strade migliori o diversificate per poterlo risolvere.
Supponiamo di ricevere molti dati da diverse sorgenti. Benché la maggior parte di questi dati sia strettamente numerica, alcuni di questi contengono, insieme ai numeri, trattini e spazi. Abbiamo la necessità di rimuovere tutti i trattini e gli spazi dai campi e salvare solo i dati numerici.
Invece di partire tentando subito di rimuovere i caratteri indesiderati dai dati originali, si può cercare di formulare l'obiettivo del programma come segue:
Obiettivo (Goal) Sostituire i valori esistenti in un campo con altri contenenti tali valori epurati dagli spazi e dai trattini.
Questa formulazione evita di scontrarsi con la difficoltà di manipolare stringhe di caratteri la cui lunghezza può cambiare durante la nostra elaborazione.
Suddividere il problema
Siccome abbiamo la necessità di fornire specifiche istruzioni a Visual FoxPro in termini di operazioni, comandi e funzioni, è necessario suddividere il problema in elementi discreti. Il passo più semplice per affrontare il problema che ci siamo posti è quello di verificare ogni caratteri presente nella stringa. Finché non valuteremo ogni carattere individualmente non saremo in grado di decidere se salvarlo o meno.
Una volta individuato un carattere, sarà necessario verificare se si tratta di un trattino ad uno spazio. A questo punto, saremo in grado di rifinire la dichiarazione del problema. E se, in futuro, si ricevessero dati contenenti parentesi aperte o chiuse? E come fare per sbarazzarsi di simboli di valuta, virgole e punteggiatura? Più ampio sarà il campo di azione del programma, più lavoro ci potremo risparmiare in futuro. Allora possiamo riformulare gli obiettivi in maniera da poter lavorare, in futuro, con una maggiore varietà di dati:
Ridefinizione dell'obiettivo Sostituire i valori esistenti in un campo con altri contenenti tali valori epurati da tutti i caratteri diversi da cifre.
Con questo nuovo obiettivo si è in grado di riformulare il problema a livello di carattere: se il carattere è numerico, va salvato; se il carattere non è numerico si passa al successivo. Una volta costruita la stringa contenente solo i caratteri numerici di quella di partenza, sarà possibile salvarla e procedere con il record successivo fino alla completa elaborazione di tutti i dati.
Per riassumere, il problema può essere suddiviso nelle seguenti parti:
1. Valutare ogni carattere.
2. Verificare se rappresenta un numero oppure no.
3. Se numerico, copiarlo nella seconda stringa.
4. Una volta valutati tutti i caratteri della stringa originale, sostituirla con la seconda generata
5. Ripetere le operazioni per tutti i records dell'archivio.Costruire le varie parti
Una volta che abbiamo ben chiaro quello che esattamente si intende realizzare, si può finalmente iniziare a costruire le varie parti del programma, assemblando i comandi, le funzioni e gli operatori che Visual FoxPro mette a disposizione.
Dal momento che i comandi e le funzioni saranno utilizzati per manipolare dati, sarà necessario realizzare delle basi dati di prova sulle quali eseguire le simulazioni. Naturalmente sarà opportuno realizzare basi dati le più somiglianti possibili a quelle su cui il programma dovrà in futuro lavorare.
Nell'esempio successivo vediamo come immagazzinare una stringa di caratteri all'interno di una variabile, utilizzando l'istruzione direttamente dalla finestra dei comandi di FoxPro:
cTest = "123-456-7 89 0"
Lavorare sul singolo carattere
Per valutare ogni singolo carattere di una stringa è necessario utilizzare alcune particolari funzioni che possiamo trovare elencate nel paragrafo relativo, funzioni di manipolazione dei caratteri (Character Functions).
Le funzioni in grado di restituire specifiche sezioni di una stringa sono tre, e precisamente: LEFT( ), RIGHT( ), e SUBSTR( ).
La funzione SUBSTR( ) restituisce i caratteri di una qualsiasi porzione di stringa. SUBSTR( ) necessita dei seguenti tre argomenti (o parametri): la stringa, la posizione dalla quale si intende partire ed il numero di caratteri che intendiamo estrarre, ad iniziare dalla prima posizione a sinistra. Per verificare il funzionamento della funzione SUBSTR( ) sulla variabile appena realizzata, proviamo a scrivere le seguenti istruzioni dalla finestra dei comandi:
? SUBSTR(cTest, 1, 1)
? SUBSTR(cTest, 3, 1)
? SUBSTR(cTest, 8, 1)
In uscita avremo
1
3
-
Si può notare come il primo, il terzo e l'ottavo carattere siano stati visualizzati nella finestra principale di Visual FoxPro.
Per eseguire lo stesso tipo di operazione possiamo ricorrere alla tecnica del loop. Siccome conosciamo la lunghezza della stringa di testo (14 caratteri), possiamo utilizzare un loop di tipo FOR. Il contatore che controlla il ciclo viene incrementato ogni volta che viene rieseguito il loop stesso, così siamo in grado di utilizzarlo come parametro della funzione SUBSTR( ). E' possibile provare il funzionamento del loop all'interno della finestra dei comandi, ma a questo punto potremmo sentire la necessità di salvare il nostro lavoro per poterlo riutilizzare successivamente. E' arrivato il momento di realizzare il nostro primo programma !
Creare un programma
Creare un programma
1. All'interno della finestra dei comandi, digitare le seguenti righe di istruzione:
2.MODIFY COMMAND numonly
3. All'interno della nuova finestra, digitare le seguenti linee di codice:
4.FOR nCnt = 1 TO 14
5.? SUBSTR(cTest, nCnt, 1)
6.ENDFOR
Adesso che abbiamo realizzato il nostro programma, possiamo mandarlo in esecuzione.Eseguire un programma
1. Dalla finestra del programma, premere CTRL+E.
2. All'interno della finestra di dialogo (Save dialog box), scegliere OK.
In fase di esecuzione del programma, i singoli caratteri estratti dalla stringa di partenza, verranno visualizzati uno ad uno in linee separate, all'interno della finestra principale di Visual FoxPro (main Visual FoxPro window).
Testare una parte di programma
La prima operazione è compiuta. Adesso è possibile visualizzare ogni carattere della stringa.
Verificare se il carattere è numerico o meno.
Una volta estratto un carattere dalla stringa, si può verificare se si tratti di un numero o no. Questa verifica la possiamo eseguire utilizzando la funzione ISDIGIT( ).
Proviamo a digitare i seguenti comandi dalla Command window:
? ISDIGIT('2')
? ISDIGIT('-')
? ISDIGIT(SUBSTR(cTest, 3, 1))
In uscita avremo
.T.
.F.
.T.
I risultati ottenuti testimoniano che '2' è un numero, '- ' non è un numero, mentre il terzo carattere della stringa cTest, 3, è nuovamente un numero.
Se il carattere è numerico, lo possiamo copiare nella Seconda Stringa
Una volta appurato che il carattere è di tipo numerico, avremo bisogno di una nuova variabile all'interno della quale poterlo memorizzare: la nuova variabile si chiamerà, ad esempio, cNumOnly.
Per creare cNumOnly, sarà sufficiente assegnarle come valore iniziale una stringa di lunghezza pari a zero:
cNumOnly = ""
Mentre il nostro ciclo FOR si sposta all'interno della nostra stringa di partenza, può risultare utile creare una nuova variabile per memorizzare ogni nuovo carattere estratto dalla stringa al fine di poterlo valutare:
cCharacter = SUBSTR(cTest, nCnt, 1)
Suggerimento: spesso è consigliabile memorizzare il risultato di un calcolo, di una scelta (valutazione) o di una funzione all'interno di una variabile, in maniera da poterlo elaborare e modificare senza dovere ogni volta ripetere l'operazione di calcolo.
La seguente linea di codice può essere utilizzata ogni volta che troviamo un carattere di tipo numerico all'interno della stringa (e che dobbiamo trasferire nella nuova):
cNumOnly = cNumOnly + cCharacterIl programma scritto fino ad ora, quindi, è:
cNumOnly = ""
FOR nCnt = 1 TO 14
cCharacter = SUBSTR(cTest, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + cCharacter
ENDIF
ENDFOR
Testare le varie parti
Aggiungendo un paio di comandi alla fine del programma, si può vedere come esso lavori via via con la nostra stringa:
cNumOnly = ""
FOR nCnt = 1 TO 14
cCharacter = SUBSTR(cTest, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + cCharacter
ENDIF
ENDFOR
? cTest
? cNumOnly
In uscita avremo
123-456-7 89 0
1234567890
Il risultato sembra corretto. Però cambiando la stringa di prova durante il collaudo si può incappare in qualche problema
Digitiamo il seguente comando nella finestra dei comandi:
cTest = "456-789 22"
e lanciamo nuovamente l'esecuzione del programma.
Il programma mostrerà un messaggio di errore. Il ciclo FOR proverà, infatti, ad eseguire 14 cicli anche se la nuova stringa contiene solo 10 caratteri. Per ovviare al problema è necessario trovare un sistema per poter adattare l'esecuzione del programma a stringhe di diversa lunghezza. Per fare questo è necessario ricorrere alla funzione LEN( ), in grado di restituire proprio la lunghezza di una stringa di caratteri. Inserendo questa funzione nel ciclo FOR, si potrà verificare la correttezza dell'esecuzione con ambedue le stringhe:
cNumOnly = ""
FOR nCnt = 1 TO LEN(cTest)
cCharacter = SUBSTR(cTest, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + cCharacter
ENDIF
ENDFOR
? cTest
? cNumOnly
Assemblare le varie parti
Per completare la soluzione del problema si può impostare la lettura dei dati, invece che da una variabile, direttamente da una tabella. Infatti, una volta selezionata la tabella da utilizzare, sarà possibile leggere i vari record che la compongono, prelevando da essi le stringhe da elaborare.
Per iniziare, occorre creare una tabella temporanea contenente una certa varietà di stringhe di esempio. Una tabella siffatta può contenere anche un solo campo di tipo carattere chiamato, ad esempio, TestField e quattro o cinque record:
Contenuto del campo TestField 123-456-7 89 0 -9221 9220 94321 99- 456-789 22 000001 98-99-234 Sostituendo il nome del campo a quello della stringa, creeremo un nuovo programma che avrà la seguente struttura:
FOR nCnt = 1 TO LEN(TestField)
cCharacter = SUBSTR(TestField, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + cCharacter
ENDIF
ENDFOR
? TestField
? cNumOnly
E' possibile posizionarsi manualmente su di un certo record scorrendo la tabella (browsing) sui vari records. Quando il puntatore si trova su di un certo record, il programma può eseguire le proprie istruzioni sulla base dei dati che, via via, vi trova. E' possibile anche istruire il programma in maniera tale da fargli effettuare automaticamente la scansione della tabella:
SCAN
cNumOnly = ""
FOR nCnt = 1 TO LEN(TestField)
cCharacter = SUBSTR(TestField, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + cCharacter
ENDIF
ENDFOR
? TestField
? cNumOnly
?
ENDSCAN
In uscita avremo
123-456-7 89 0
1234567890
456-789 22
45678922
-9221 9220 94321 99-
922192209432199
000001 98-99-234
0000019899234
Testare tutto il programma
Invece di stampare la stringa generata, si può voler salvare il contenuto all'interno della tabella stessa. Per fare ciò si può utilizzare la seguente linea di codice:
REPLACE TestField WITH cNumOnly
Quindi il nuovo programma diventa:
SCAN
cNumOnly = ""
FOR nCnt = 1 TO LEN(TestField)
cCharacter = SUBSTR(TestField, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + cCharacter
ENDIF
ENDFOR
REPLACE TestField WITH cNumOnly
ENDSCAN
Una volta completato il programma, prima di iniziare ad utilizzarlo, è necessario testarlo su un modello di prova della futura base dati.
Rendere il programma più affidabile
Un programma affidabile, oltre a fare ciò per cui è stato progettato, deve anche essere in grado di prevedere, ed eventualmente gestire, eventuali errori. Il programma utilizzato nell'esempio precedente esegue effettivamente tutte le elaborazioni necessarie, ma da per scontate alcune condizioni che devono necessariamente verificarsi affinché tutto possa procedere senza errori.
Le condizioni necessarie sono le seguenti:
- La tabella deve essere già aperta nell'area di lavoro corrente
- La tabella deve contenere un campo di tipo carattere chiamato TestField.
Se nell'area di lavoro corrente la tabella non fosse già presente o quest'ultima non avesse un campo di tipo carattere con il nome specificato, il programma genererebbe un messaggio di errore e non potrebbe proseguire con le operazioni.
Esempio di programma in grado di eliminare, per tutti i records di una tabella, i caratteri non numerici presenti all'interno di un campo
Questa è la porzione di codice deputata alla conversione.
Codice Commenti lFieldOK = .F.Questa variabile è necessaria per determinare se esistono le condizioni necessarie per far funzionare correttamente il programma. La variabile viene inizializzata a falso (.F.), assumendo quindi che le condizioni necessarie al funzionamento del programma non sono rispettate.
FOR nCnt = 1 TO FCOUNT( ) IF FIELD(nCnt) = ; UPPER("TestField") IF TYPE("TestField") = "C" lFieldOK = .T. ENDIF EXIT ENDIFENDFORIn questa porzione di codice si procede alla verifica di ogni campo della tabella corrente alla ricerca di un campo di tipo carattere chiamato TestField. Una volta trovato il campo, la variabile lFieldOK viene settata a vero (.T.) e, tramite l'istruzione EXIT, il ciclo si interromperà (Infatti non ci sarebbe motivo di continuare una ricerca che ha già dato esiti positivi). Nel caso in cui, invece, non si trovi il campo specificato, la variabile lFieldOK resterà settata al valore falso (.F.). IF lFieldOKLa porzione di codice deputata alla conversione verrà eseguita solo se sarà stato precedentemente trovato il campo di tipo carattere (chiamato TestField) all'interno della tabella nell'area di lavoro corrente. SCAN
cNumOnly = ""
FOR nCnt = 1 TO LEN(TestField) cCharacter = ;
SUBSTR(TestField, nCnt, 1)
IF ISDIGIT(cCharacter)
cNumOnly = cNumOnly + ;
cCharacter
ENDIF
ENDFOR
REPLACE TestField WITH ;
cNumOnly
ENDSCANENDIFFine della condizione (IF) applicata al contenuto della variabile lFieldOK.
La caratteristica più limitativa di questo programma è data dal fatto che può essere utilizzato solo per operare su di uno specifico campo di una tabella. Nel caso si volesse estenderne la funzionalità ad un campo diverso da TestField , saremmo obbligati a riscrivere il programma sostituendo tutte le istruzioni relative al campo TestField con altre contenenti il nome del nuovo campo.
Convertendo il programma appena visto in una funzione, come vedremo in seguito, potremo renderne il campo di applicazione più generico, rendendolo riutilizzabile in vari altri casi, risparmiandoci in futuro del nuovo lavoro.
Traduzione Alessandro Bindi© FoxPro e Visual FoxPro sono un marchi registrati da Microsoft Corporation
Febbraio 2002
FoxPro e Visual FoxPro® sono un marchi registrati da Microsoft Corporation©
Fonte: "Programmers Guide Visual FoxPro®" di Microsoft© in lingua inglese.
Questa guida ha il solo scopo di fornire le indicazioni
per muovere i primi passi con questo bellissimo strumento.
dal 22 Giugno 1999
webmaster@foxitaly.com