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:

Ci sono però alcune cose che è necessario ricordare quando si inizia:

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 + cCharacter
Il 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:


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 ENDIFENDFOR
In 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 lFieldOK La 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
ENDSCAN

 
ENDIF Fine 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