Introduzione alla programmazione in Visual Basic for applications. Una guida per imparare a programmare [2 rev.2 ed.] 8876616101, 9788876616105

Questo testo vuole essere una guida per chi affronta per la prima volta lo studio di un linguaggio di programmazione. Sa

425 170 894KB

Italian Pages 220 Year 2007-2019

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Introduzione alla programmazione in Visual Basic for applications. Una guida per imparare a programmare [2 rev.2 ed.]
 8876616101, 9788876616105

Table of contents :
1 Introduzione 1
1.1 Linguaggi e traduttori 1
1.2 L’ambiente di sviluppo 3
1.3 Costruzione dell’interfaccia grafica 5
2 Un primo esperimento 9
2.1 Esercizi 15
3 Variabili e tipi numerici 17
3.1 Variabili numeriche 18
3.1.1 Espressioni numeriche 20
3.1.2 Valutazione delle espressioni numeriche 20
3.1.3 Principali funzioni di conversione di tipo 23
3.1.4 Funzioni intrinseche 25
3.1.5 Precedenza e associatività degli operatori 25
3.1.6 Costanti numeriche 26
3.2 Esercizi 28
4 Input/Output da tastiera e su video 29
4.1 L’istruzione MsgBox 29
4.2 L’istruzione InputBox 31
4.3 Esercizi 32
5 Esecuzione condizionale 33
5.1 Il costrutto If-Then 33
5.2 Espressioni relazionali 38
5.3 Espressioni logiche 39
5.3.1 Operatore Or 39
5.3.2 Operatore And 39
5.3.3 Operatore Xor 40
5.3.4 Operatore Not 40
5.4 Precedenza degli operatori 40
5.5 Il costrutto Select Case 41
5.6 Esercizi 44
6 Le stringhe 47
6.1 Variabili stringa 48
6.2 Operazioni sulle stringhe 49
6.3 Funzioni sulle stringhe 50
6.3.1 Len 50
6.3.2 Left 50
6.3.3 Right 50
6.3.4 Mid 51
6.3.5 Instr 51
6.3.6 Altre funzioni sulle stringhe 52
6.4 Confronti tra stringhe 54
6.5 Esercizi 56
7 Salti incondizionati 57
8 Esecuzione ciclica 59
8.1 Il ciclo For-Next 60
8.2 Esercizi 64
8.3 Il ciclo Do-Loop 66
8.4 Esercizi 70
9 Vettori e matrici 73
9.1 Matrici 75
9.2 Vettori e matrici di tipo stringa 76
9.3 Esercizi 76
10 I file 79
10.1 Aprire e chiudere un file 80
10.2 Scrivere in un file 82
10.3 Leggere da un file 83
10.4 Esercizi 87
11 I sottoprogrammi e la programmazione modulare 89
11.1 Le funzioni 92
11.2 Le subroutine 93
11.3 Argomenti e parametri formali 94
11.3.1 Passaggio degli argomenti 95
11.4 Variabili statiche 99
11.5 Variabili non locali 100
11.6 Inizializzazione delle variabili 101
11.7 La ricorsione 101
11.8 Esercizi 104
12 Tipi di dati composti 107
12.1 Esercizi 109
13 Alcuni altri controlli Visual Basic 111
13.1 Le Label 111
13.2 Le TextBox 111
13.3 Gli OptionButton 114
13.4 Le CheckBox 115
13.5 Abilitare e nascondere i controlli 116
14 Suggerimenti per una buona programmazione 117
14.1 Variabili implicite 117
14.2 Indentazione del codice 117
14.3 I commenti 118
15 Debugging 119
16 Esercizi riassuntivi 121
17 Un esempio di Macro VBA per Excel 129
17.1 Commento del codice 132
18 Soluzione degli esercizi 135
18.1 Capitolo 2 135
18.2 Capitolo 3 136
18.3 Capitolo 4 138
18.4 Capitolo 5 138
18.5 Capitolo 6 143
18.6 Capitolo 8 150
18.7 Capitolo 9 163
18.8 Capitolo 10 174
18.9 Capitolo 11 185
18.10 Capitolo 12 196
18.11 Capitolo 16 198

Citation preview

CLAUDIO FORNARO

INTRODUZIONE ALLA PROGRAMMAZIONE IN VISUAL BASIC FOR APPLICATIONS Una guida per imparare a programmare Seconda edizione con esercizi svolti Rev 2

ii

INDICE

iii

INDICE INDICE ............................................................................................................ iii Prefazione alla seconda edizione ....................................................................vii 1

Introduzione ............................................................................................... 1 1.1 Linguaggi e traduttori ......................................................................... 1 1.2 L’ambiente di sviluppo ....................................................................... 3 1.3 Costruzione dell’interfaccia grafica ................................................... 5

2

Un primo esperimento............................................................................... 9 2.1 Esercizi ............................................................................................. 15

3

Variabili e tipi numerici .......................................................................... 17 3.1 Variabili numeriche .......................................................................... 18 3.1.1 Espressioni numeriche ...................................................................... 20 3.1.2 Valutazione delle espressioni numeriche ......................................... 20 3.1.3 Principali funzioni di conversione di tipo ........................................ 23 3.1.4 Funzioni intrinseche ......................................................................... 25 3.1.5 Precedenza e associatività degli operatori ........................................ 25 3.1.6 Costanti numeriche ........................................................................... 26 3.2 Esercizi ............................................................................................. 28

4

Input/Output da tastiera e su video ....................................................... 29 4.1 L’istruzione MsgBox ........................................................................ 29 4.2 L’istruzione InputBox ...................................................................... 31 4.3 Esercizi ............................................................................................. 32

5

Esecuzione condizionale .......................................................................... 33 5.1 Il costrutto If-Then ........................................................................... 33 5.2 Espressioni relazionali ...................................................................... 38 5.3 Espressioni logiche ........................................................................... 39

iv

INDICE 5.3.1 Operatore Or..................................................................................... 39 5.3.2 Operatore And .................................................................................. 39 5.3.3 Operatore Xor................................................................................... 40 5.3.4 Operatore Not ................................................................................... 40 5.4 Precedenza degli operatori ............................................................... 40 5.5 Il costrutto Select Case ..................................................................... 41 5.6 Esercizi ............................................................................................. 44

6

Le stringhe ............................................................................................... 47 6.1 Variabili stringa ................................................................................ 48 6.2 Operazioni sulle stringhe.................................................................. 49 6.3 Funzioni sulle stringhe ..................................................................... 50 6.3.1 Len.................................................................................................... 50 6.3.2 Left ................................................................................................... 50 6.3.3 Right ................................................................................................. 50 6.3.4 Mid ................................................................................................... 51 6.3.5 Instr .................................................................................................. 51 6.3.6 Altre funzioni sulle stringhe ............................................................. 52 6.4 Confronti tra stringhe ....................................................................... 54 6.5 Esercizi ............................................................................................. 56

7

Salti incondizionati .................................................................................. 57

8

Esecuzione ciclica .................................................................................... 59 8.1 Il ciclo For-Next ............................................................................... 60 8.2 Esercizi ............................................................................................. 64 8.3 Il ciclo Do-Loop ............................................................................... 66 8.4 Esercizi ............................................................................................. 70

9

Vettori e matrici ...................................................................................... 73 9.1 Matrici .............................................................................................. 75 9.2 Vettori e matrici di tipo stringa ........................................................ 76 9.3 Esercizi ............................................................................................. 76

10 I file ...................................................................................................... 79 10.1 Aprire e chiudere un file .................................................................. 80 10.2 Scrivere in un file ............................................................................. 82 10.3 Leggere da un file............................................................................. 83 10.4 Esercizi ............................................................................................. 87

INDICE

v

11 I sottoprogrammi e la programmazione modulare .......................... 89 11.1 Le funzioni........................................................................................ 92 11.2 Le subroutine .................................................................................... 93 11.3 Argomenti e parametri formali ......................................................... 94 11.3.1 Passaggio degli argomenti ........................................................ 95 11.4 Variabili statiche............................................................................... 99 11.5 Variabili non locali ......................................................................... 100 11.6 Inizializzazione delle variabili ........................................................ 101 11.7 La ricorsione ................................................................................... 101 11.8 Esercizi ........................................................................................... 104 12 Tipi di dati composti ......................................................................... 107 12.1 Esercizi ........................................................................................... 109 13 Alcuni altri controlli Visual Basic.................................................... 111 13.1 Le Label .......................................................................................... 111 13.2 Le TextBox ..................................................................................... 111 13.3 Gli OptionButton ............................................................................ 114 13.4 Le CheckBox .................................................................................. 115 13.5 Abilitare e nascondere i controlli ................................................... 116 14 Suggerimenti per una buona programmazione ............................. 117 14.1 Variabili implicite ........................................................................... 117 14.2 Indentazione del codice .................................................................. 117 14.3 I commenti ...................................................................................... 118 15

Debugging .......................................................................................... 119

16

Esercizi riassuntivi ............................................................................ 121

17 Un esempio di Macro VBA per Excel.............................................. 129 17.1 Commento del codice ..................................................................... 132 18 Soluzione degli esercizi ..................................................................... 135 18.1 Capitolo 2 ....................................................................................... 135 18.2 Capitolo 3 ....................................................................................... 136 18.3 Capitolo 4 ....................................................................................... 138 18.4 Capitolo 5 ....................................................................................... 138 18.5 Capitolo 6 ....................................................................................... 143 18.6 Capitolo 8 ....................................................................................... 149

INDICE

vi 18.7 18.8 18.9 18.10 18.11

Capitolo 9 ....................................................................................... 162 Capitolo 10 ..................................................................................... 173 Capitolo 11 ..................................................................................... 184 Capitolo 12 ..................................................................................... 195 Capitolo 16 ..................................................................................... 197

Prefazione alla seconda edizione

vii

Prefazione alla seconda edizione Questo testo vuole essere una guida per chi affronta per la prima volta lo studio di un linguaggio di programmazione. Saper programmare non vuol dire solo conoscere la sintassi di un linguaggio: è necessario, infatti, sapere come funziona la macchina che si utilizza, avere nozioni di logica e di matematica, conoscere gli algoritmi fondamentali per la soluzione delle principali classi di problemi. Soprattutto, è indispensabile avere creatività e inventiva, necessarie per affrontare con metodo problematiche complesse di qualsiasi natura. L’apprendimento di un linguaggio di programmazione è comunque un primo passo fondamentale ed essenziale. Si è scelto di utilizzare il linguaggio Visual Basic for Applications, evoluzione del BASIC, in quanto risulta essere più semplice di altri linguaggi più potenti e versatili quali il linguaggio C o Java e inoltre gli strumenti di sviluppo di cui necessita sono di facile reperibilità: è infatti presente un interprete VBA in ogni applicazione della diffusissima suite di Microsoft Office (Word, Excel ecc.). La versione professionale è oggi uno dei linguaggi più utilizzati per sviluppare applicazioni commerciali, anche in ambito Internet. Essendo questo libro rivolto ai principianti della programmazione, verranno introdotte le sole istruzioni di base (ad esempio non si sono incluse nella trattazione le istruzioni relative ai file ad accesso casuale, agli oggetti, alle classi). Ciò non deve apparire come elemento riduttivo: nell’apprendimento iniziale della programmazione si ritiene più importante rivolgere l’attenzione alla logica della costruzione e alla correttezza dell’algoritmo impiegato piuttosto che identificare il metodo migliore e la sua codifica più “elegante” e veloce. Una volta acquisita la capacità di programmare, imparare gli aspetti più evoluti del linguaggio (o anche un altro linguaggio) è solo questione di studio e non presenta particolari difficoltà. Il testo è pensato come supporto per corsi brevi di introduzione alla programmazione a livello universitario. Si rivolge anche agli autodidatti, i quali, non potendo in genere disporre di un’interazione con un docente, cercano nel testo le risposte alle loro domande. Anche a tal scopo sono proposti numerosi esercizi corredati da una soluzione.

viii Rispetto alla precedente, questa nuova edizione vede la rielaborazione di alcune parti in una forma espositiva più chiara, la correzione di errori, alcuni esercizi aggiuntivi nei vari capitoli e un nuovo capitolo di esercizi riassuntivi. Un sentito ringraziamento va al professor Marco Mezzalama del Politecnico di Torino per la revisione critica del testo. Torino, gennaio 2004 Claudio Fornaro

Introduzione

1 1.1

1

Introduzione Linguaggi e traduttori

Lo scopo di scrivere un programma è sostanzialmente quello di “spiegare” ad un calcolatore quali operazioni debba eseguire per risolvere un problema. Per indicare ad un calcolatore le operazioni che esso deve svolgere, bisogna utilizzare un linguaggio che sia conosciuto sia dalla persona (opportunamente istruita) che impartisce gli ordini sia dal calcolatore che li deve eseguire. Con un linguaggio noto ad entrambi, la persona comunica alla macchina l’attività che essa deve svolgere, ossia la programma: da cui il termine linguaggio di programmazione. I linguaggi naturali delle due entità, uomo e calcolatore, sono assai diversi tra loro, l’uno si esprime mediante parole (“somma 2 e 5”), per l’altro esistono solo sequenze di zeri e uno (la parola uno è indeclinabile!) Più in dettaglio, il microprocessore (ossia la CPU) conosce un solo linguaggio chiamato linguaggio macchina (o codice macchina): ogni sequenza di zeri e uno ha un significato ben preciso per la CPU, ad esempio la sequenza 1011010 potrebbe significare “calcola la somma”. Se una persona volesse richiedere a quel calcolatore di fare una somma, dovrebbe impartirgli il comando 1011010, se volesse un’altra operazione dovrebbe informarsi (su un manuale) su quale sia la traduzione di questa in linguaggio macchina per poi poterla impartire. Chiaramente si tratta di soluzione assai complessa e lunga da attuare, per questo sono stati introdotti linguaggi di programmazione evoluti molto simili al linguaggio naturale (in particolare all’inglese). Tali linguaggi, dei quali il Visual Basic è un esempio, sono detti di alto livello. La traduzione di programmi scritti in linguaggio evoluto nel corrispondente codice macchina binario è effettuata da speciali programmi detti traduttori. Il programmatore usa un traduttore per convertire l’istruzione “calcola la somma”, il traduttore traduce l’istruzione in 1011010 e quando questo codice macchina 1011010 viene passato al microprocessore esso “capisce” che cosa si vuole ed esegue la somma. Un programma non è niente altro che una sequenza di comandi, detti più propriamente istruzioni, espresse in un dato linguaggio di programmazione. Il file contenente queste istruzioni costituisce il programma sorgente (o codice sorgente).

2

Capitolo 1

Esistono sostanzialmente due modi di realizzare un traduttore:  mediante un compilatore;  mediante un interprete. Un compilatore traduce in una volta sola tutto il programma sorgente e lo memorizza in un file detto programma eseguibile (o codice eseguibile); in ambiente Microsoft si tratta di file con estensione .EXE o .COM. Per eseguire il programma è sufficiente “lanciare” il file eseguibile (ad esempio con un doppio click sul suo nome in ambiente Windows), mentre il programma sorgente non è richiesto per l’esecuzione del programma. Un interprete invece traduce una per volta ciascuna istruzione del programma sorgente in linguaggio macchina, non memorizza il risultato della traduzione in un file, ma lo fa eseguire immediatamente al microprocessore e poi la cancella. Il ciclo di esecuzione di un programma interpretato è quindi: 1) leggi un’istruzione 2) traducila in linguaggio macchina 3) invia l’istruzione tradotta al microprocessore perché la esegua immediatamente 4) riparti da 1) per leggere la successiva istruzione dal programma sorgente Questo significa che se un’istruzione deve essere eseguita più volte, ogni volta verrà tradotta in linguaggio macchina. Confrontando i due metodi possiamo fare le seguenti considerazioni:  attuare la traduzione una volta per tutte permette di avere un programma molto più veloce in fase di esecuzione;  mandare in esecuzione un programma compilato è molto semplice (in genere basta un doppio click sull’icona del programma), mentre in genere solo un programmatore può attivare un programma interpretato, in quanto deve conoscerne l’interprete;  l’utente di un programma compilato (il cosiddetto utente finale) non deve disporre di costosi strumenti di sviluppo quali sofisticati traduttori per mandare in esecuzione il programma;  l’utente di un programma compilato non può modificare il programma stesso in quanto non dispone del codice sorgente (questo è normalmente richiesto per questioni di copyright);  ogni volta che, durante la fase di sviluppo del programma, viene modificato il codice sorgente, il compilatore deve tradurre di nuovo da capo tutto quanto o parte del codice sorgente (questo può richiedere una discreta quantità di tempo), mentre per un interprete non è necessario. Riassumendo, un interprete può essere più comodo per sviluppare un programma. La maggior parte dei linguaggi di programmazione è solo compilata, ossia non è stato per essi sviluppato un interprete; altri, come il

Introduzione

3

Visual Basic, hanno sia interpreti sia compilatori. In particolare, in ciascuno dei programmi di Microsoft Office è presente un interprete Visual Basic for Applications (VBA), mentre si può acquistare un compilatore Visual Basic (non for Applications) sempre della stessa ditta. Esistono differenze tra Visual Basic e Visual Basic for Applications, ma dal punto di vista della filosofia del linguaggio cambia poco e il passaggio dall’uno all’altro non è complesso. Nel seguito, per brevità, quando non indicato diversamente, si utilizzerà il termine Visual Basic intendendo con questo la versione for Applications.

1.2

L’ambiente di sviluppo

L’ambiente integrato di sviluppo di Visual Basic (detto Integrated Development Environment, più brevemente IDE) permette essenzialmente al programmatore di scrivere codice Visual Basic e di eseguirlo, mettendo a disposizione un elevato numero di strumenti di gestione del programma, di controllo e verifica del codice. Per attivarlo è necessario avviare uno dei programmi di Microsoft Office, ad esempio Excel, selezionare dal menu Strumenti la voce Macro e quindi scegliere Visual Basic Editor (tutto ciò si ottiene anche premendo la combinazione di tasti Alt-F11). Si presenta una schermata come quella indicata nella figura seguente. Se vi è una segnalazione relativa alla sicurezza, selezionare Strumenti/Macro/Protezione dal menu e impostare il valore su Medio. Chiudere Excel e riattivarlo. Si notino le due finestre sulla sinistra: una reca informazioni sul progetto a cui Barra dei menu Finestra progetto

Finestra delle proprietà

Barra degli strumenti

4

Capitolo 1

si sta lavorando (finestra Progetto) e, sotto, l’altra mostra un elenco di proprietà (finestra Proprietà). Se mancano, selezionare il menu Visualizza e quindi le voci finestra Progetto o finestra Proprietà. Utilizzeremo spesso queste finestre e ne parleremo diffusamente in seguito. Sotto il titoletto della finestra vi è la cosiddetta barra dei menu, tramite la quale si accede a tutti i comandi (della maggior parte ovviamente non sappiamo ancora nulla); tra questi i più utili sono i seguenti: o File per aprire, salvare e stampare file; o Modifica per le operazioni di Copia, Incolla, Annulla (annulla l’ultima modifica apportata), Cerca, Sostituisci ecc. o Visualizza per mostrare altre finestre quali quella delle Espressioni di controllo e la Finestra Immediata per le operazioni di debug e per ripristinare la finestra Progetto e la finestra Proprietà se le abbiamo chiuse; o Formato per assistere il programmatore nello sviluppo dell’aspetto grafico (allineare e rendere uguali i controlli ecc.); o Debug per assistere nella ricerca degli errori (ne tratteremo adeguatamente in un capitolo specifico); o Esegui per eseguire, interrompere e fermare un programma; o Strumenti per modificare e personalizzare l’ambiente di sviluppo (ad esempio per aggiungere nuovi controlli e scegliere le opzioni che ci interessano; o ? per richiedere l’help on line: un grosso e completo database di informazioni con utili esempi di programmazione. A riguardo è importante sottolineare che durante l’installazione del pacchetto Office deve essere stato indicato il Visual Basic for Applications Help. Sotto la barra dei menu si trova la barra degli strumenti, contenente i pulsanti che consentono di eseguire rapidamente operazioni di programmazione comuni, quali l’aggiunta di un nuovo modulo, il copia e incolla, l’annulla, l’esegui ecc. Si può accedere agli stessi comandi anche tramite la barra dei menu, ma in modo molto meno comodo e veloce. Vedremo l’utilizzo di questi bottoni all’occorrenza.

Introduzione

1.3

5

Costruzione dell’interfaccia grafica

Il Visual Basic produce programmi con interfaccia grafica, ossia ogni programma avrà almeno una finestra grafica dove inserire i dati e leggerne i risultati. Anche noi dovremo “aprire una finestra” sullo schermo per i nostri programmi. Dopo aver attivato l’ambiente VBA (ad esempio quello di Excel) come indicato precedentemente, facciamo click sul bottone (in alto a sinistra nella barra degli strumenti). Otteniamo quello che viene riportato nella figura seguente.

Form

Si è aperta una finestra bianca contenente un’altra finestra, costituita da un pannello grigio puntinato detto form. Quest’ultimo sarà la finestra principale di ogni nostro programma, ossia quella che verrà visualizzata quando il programma verrà mandato in esecuzione. Il form può essere ridimensionato trascinando i quadratini bianchi che lo circondano. Dopo questa operazione, nella finestra Progetto vediamo che, rispetto a prima, è stata aggiunta una voce denominata UserForm1. Questa identifica il form che abbiamo aggiunto e tutto il codice di

6

Capitolo 1

programmazione ad esso relativo. Ogni volta che aggiungiamo un form (o un modulo come vedremo più avanti), questo viene riportato in questa finestra. Per rimuovere un elemento da questa finestra è sufficiente fare un click su di esso con il bottone di destra del mouse e selezionare la voce di cancellazione. Attenzione che sia le impostazioni grafiche sia il codice di programmazione relativo a quel form vengono perduti. Il form così generato è completamente vuoto, vi aggiungeremo molti altri oggetti (in particolare per raccogliere dati e per visualizzarli) detti controlli o controls: oltre alle due finestre di cui sopra si è aperta anche un’altra piccola finestra sulla sinistra (copre in parte la finestra Progetto) contenente appunto gli oggetti che possiamo aggiungere alla nostra interfaccia, detta casella dei controlli o degli strumenti. Se questa non compare, premere il pulsante presente sulla destra della barra degli strumenti. Gli oggetti presenti sono solo una parte di quelli possibili, nella casella vengono inizialmente elencati solo i principali. Per conoscere il nome di un certo controllo riportato nella casella dei controlli basta posizionare il cursore su di esso e aspettare un paio di secondi: il sistema mostrerà il nome del controllo stesso in un riquadro giallo (nell’esempio si tratta del controllo Pulsante di Comando). Si seleziona il controllo voluto facendo click e lo si colloca sulla finestra nella posizione prescelta disegnando (ossia trascinando il mouse tenendo premuto il bottone di sinistra) un rettangolo. Mettiamo ad esempio una scritta sul form. Selezioniamo dunque il controllo Label (ha come icona una A) facendo click sulla A stessa. Si noti che il puntatore del mouse non ha più la forma di una freccia, ma assume quella di una crocetta con accanto una A. Posizioniamo la crocetta nell’angolo in alto a sinistra del form (un po’ più a destra e un po’ più sotto), facciamo click con il bottone sinistro del mouse e teniamolo premuto, trasciniamo il puntatore del mouse per un paio di centimetri verso destra e uno verso il basso, quindi rilasciamo il bottone. Viene creato un riquadro contenente la scritta Label1 (vedasi la figura a destra). Abbiamo appena collocato un’etichetta (in inglese label ) e il sistema le ha assegnato un nome generico che deriva dal suo tipo, in questo caso il nome è Label1.

Introduzione

7

Si noti che il controllo ora posizionato è incorniciato in modo evidente: questo significa che è l’elemento attualmente selezionato, ossia quello su cui si può intervenire per modificarlo. La dimensione del controllo attualmente selezionato può essere modificata trascinando uno di quegli otto quadratini bianchi che fanno parte del riquadro circostante il controllo stesso: quelli sui lati permettono di modificare una sola delle due dimensioni (altezza o larghezza), quelli agli angoli entrambe contemporaneamente. In tutti e due i casi si nota che la forma del puntatore del mouse cambia per assumere la forma di una freccia a due punte. Si può spostare il controllo selezionato trascinando uno dei lati del riquadro (ma non ci si posizioni sui quadratini altrimenti lo si ridimensiona), la forma del puntatore del mouse in questo caso cambia in una doppia freccia a crocetta. Spostiamo la casella dei controlli sulla destra in modo da poter vedere interamente la finestra Proprietà. Questa elenca le proprietà dell’elemento in quel momento selezionato, nel nostro caso contiene la scritta Label1. Per cambiare la scritta Label1 in un’altra, dobbiamo identificare tra le proprietà del controllo Label1 quella di nome Caption (in italiano “didascalia”), questa si trova nella colonna di sinistra. Trovatala, notiamo che sulla sua destra c’è appunto la scritta Label1 (la didascalia è inizialmente uguale al nome dell’oggetto per poter agevolmente identificare quest’ultimo sul form). Cambiamo la caption facendo un doppio click su di essa e scrivendo al posto di Label1 un’altra scritta: Sottrattore; premiamo infine il tasto INVIO. La procedura per cambiare le altre proprietà è simile a questa. Proviamo ad esempio a collocare un bottone al centro del form (impareremo a far sì che premendo questo bottone il programma svolga una certa elaborazione). Selezioniamo il controllo Pulsante di comando (ha l’aspetto di un rettangolo in rilievo, si veda la figura dei Controlli alla pagina precedente) e, così come abbiamo fatto per la Label sopra, ora disegniamo un bottone e gli assegniamo come Caption la dicitura Calcola. Al bottone creato il sistema assegna il nome CommandButton1. Ora utilizzando la proprietà Font sia della Label sia del Bottone cerchiamo di ottenere un form come quello della figura a destra.

8

Capitolo 1

Per avere più controlli dello stesso tipo è possibile ogni volta ripetere la procedura vista, ma se i controlli devono essere tutti uguali è possibile, dopo aver selezionato un controllo, crearne più copie identiche mediante la solita procedura di Copia e Incolla: si seleziona un oggetto e dal menu Modifica si seleziona Copia, poi si seleziona Modifica/Incolla tante volte quante è necessario. Automaticamente il sistema genera controlli identici, con le stesse proprietà (anche la Caption), ma di nome diverso; così se si copia il controllo Label1 con Caption XYZ e lo si incolla tre volte si ottengono tre oggetti di nome Label2, Label3 e Label4, ma tutti con Caption XYZ. I nuovi oggetti appena generati devono comunque essere posizionati opportunamente sul form, talvolta vengono copiati uno sopra l’altro e non ci se ne accorge. Nel caso sia necessario rimuovere un oggetto è sufficiente selezionarlo con il bottone di destra del mouse e scegliere Rimuovi dal menu che viene mostrato. Per cambiare la stessa proprietà a più oggetti è possibile selezionarli tutti facendo click sugli oggetti tenendo premuto sulla tastiera il tasto Control. Può essere utile talvolta selezionare gli oggetti disegnando intorno ad essi un unico rettangolo con il mouse, come per mettere un controllo che li riunisca tutti, questa volta però non si deve selezionare alcun controllo. Per allineare e formattare più controlli uguali è possibile selezionarli tutti e utilizzare i comandi del menu Strumenti. È importante infine ricordare la presenza di un esteso sistema di aiuto (help) in linea, raggiungibile mediante il menu Help o premendo il tasto F1. Quest’ultimo fornisce un help diverso a seconda del contesto, ossia se si sta impostando una proprietà e si preme F1 viene attivata la sezione di help relativa agli oggetti, se si sta programmando viene attivata la sezione relativa alle istruzioni Visual Basic e così via. Data la vastità, non è sempre facile ottenere le informazioni che si cercano, soprattutto le prime volte che se ne fa uso spesso sono necessari vari tentativi. Da ultimo, l’help non è pensato per insegnare a programmare, ma per fornire dettagli tecnici completi relativi ad un argomento, ossia è pensato nell’ottica di chi sa già programmare. Per questo all’inizio sarà piuttosto ostico e non molto utile, ma acquisendo conoscenze sarà in seguito di grande aiuto.

Un primo esperimento

2

9

Un primo esperimento

Per cominciare, proveremo con qualcosa di molto semplice: vogliamo un programma Visual Basic che chieda di introdurre due valori e ne visualizzi la differenza. La sequenza delle operazioni da far eseguire al calcolatore sarà: 1) 2) 3) 4)

Chiedi il primo numero Chiedi il secondo numero Calcola la differenza tra il primo numero e il secondo numero Visualizza il risultato

Le operazioni andranno ovviamente eseguite nell’ordine in cui sono state scritte. Raffiniamo il nostro programma. Innanzitutto, i numeri che vengono chiesti dove vengono memorizzati? Dobbiamo predisporre alcuni “contenitori” per numeri, “scatolette” dove possiamo riporre i valori, prelevarli quando ci serve, sostituirli con altri. Queste “scatolette” si chiamano variabili, a ciascuna scatoletta assegneremo un nome per poter distinguere le une dalle altre. Nel nostro esempio chiamiamo X e Y le scatolette rispettivamente del primo e del secondo valore. Allora il nostro programma diventa: 1) 2) 3) 4)

Chiedi il primo numero e mettilo in X Chiedi il secondo numero e mettilo in Y Calcola X - Y Visualizza il risultato

Anche il risultato della differenza di X e Y deve essere memorizzato in una variabile, chiamiamola D. Dopo questo passo il programma diventa: 1) 2) 3) 4)

Chiedi il primo numero e mettilo in X Chiedi il secondo numero e mettilo in Y Calcola X - Y e metti il valore in D Visualizza D

Capitolo 2

10

Cerchiamo di esprimere le quattro istruzioni nel modo più schematico possibile, senza inutili verbosità. Innanzi tutto togliamo i numeri iniziali: è abbastanza ovvio che le istruzioni verranno eseguite dalla macchina nell’ordine in cui sono state scritte. Otteniamo: Chiedi X Chiedi Y X - Y  D Visualizza D È chiaro che non scriveremo le istruzioni in modo informale e in italiano come fatto sopra, ma useremo un linguaggio comprensibile sia per l’interprete Visual Basic sia per noi, schematico, essenziale e di significato univoco (non ci sono due o più significati diversi per una sequenza di comandi, come invece può avvenire nel linguaggio umano). Vediamo la fase di input. In Visual Basic uno dei modi per chiedere un dato all’utente è quello di aprire un’altra finestrella con una scritta che indica che cosa si vuole venga introdotto e contenente lo spazio per poterci digitare i valori, questa finestrella viene creata per mezzo dell’istruzione InputBox (letteralmente “scatola di input” – “input” significa “introdurre”, “put” “mettere” e “in” “dentro”). Allora l’istruzione “Chiedi X ” diventerà: X = InputBox("Dammi il primo valore") Quando l’interprete eseguirà questa riga di codice, verrà dunque mandata in esecuzione la funzione InputBox. Questa visualizzerà una finestrella con la scritta Dammi il primo valore e un bottone con la scritta OK, poi il programma si metterà in attesa che questo bottone OK venga premuto (figura sotto). Premuto questo, il valore che l’utente ha scritto nella finestrella viene messo nella variabile X (è il segno di uguale che fa questo).

Un primo esperimento

11

La stessa cosa sarà fatta per il secondo valore. Y = InputBox("Dammi il secondo valore") La terza riga è quella dove il calcolo viene effettuato, un semplice simbolo di uguale fa sì che il risultato dell’espressione presente a destra del segno di uguale venga posto (assegnato) nella (alla) variabile D: D = X - Y Si noti che la variabile D è a sinistra del segno di uguale e il calcolo da eseguire sulla destra, questa istruzione si chiama assegnazione. Il simbolo = non sta a indicare un’uguaglianza, piuttosto lo si può interpretare come “assume il valore di”, quindi: “D assume il valore del risultato di X – Y”. Anche per la visualizzazione abbiamo diverse possibilità: una di queste consiste nell’indicare quello che vogliamo “stampare” (termine del gergo informatico comunemente usato con il significato di “visualizzare”) in una nuova finestrella (questa volta di output – “out” significa “fuori” e “put” “mettere”). In Visual Basic ciò si ottiene per mezzo dell’istruzione MsgBox (letteralmente “scatola con messaggio”): MsgBox D La variabile D è ciò che vogliamo visualizzare (più precisamente ci interessa il suo contenuto). Questa istruzione produce una finestrella come quella indicata a lato. Ricapitolando, le quattro righe del nostro programma sono diventate finalmente vero e proprio codice Visual Basic che l’interprete è in grado di comprendere. Eccole riunite (i numeri di riga non servono, l’interprete sa che deve eseguire le istruzioni nell’ordine in cui sono scritte): X = InputBox("Dammi il primo valore") Y = InputBox("Dammi il secondo valore") D = X - Y MsgBox D Dove scriviamo queste righe perché il programma possa leggerle ed eseguirle? Ci sono moltissime soluzioni, adottiamone una che già abbiamo visto: un form con un bottone al centro, premendo il quale le istruzioni di cui sopra vengono eseguite. Allora creiamo il form di cui abbiamo già detto nel capitolo precedente e che aveva questo aspetto:

12

Capitolo 2

Dobbiamo innanzitutto fare una piccola digressione per introdurre un concetto importante: quello di evento. Con i linguaggi di programmazione come il BASIC, il Fortran, il C ecc. di norma il programmatore scrive un programma e questo viene eseguito immediatamente dal sistema, il programma si mette in attesa solo quando è previsto che debba ricevere un input dall’utente. Nei linguaggi come il Visual Basic invece, di norma, il programma esegue (eventualmente) alcune istruzioni iniziali e poi si mette sempre in attesa di ricevere eventi. In base all’evento ricevuto si esegue una parte di programma piuttosto che un’altra. Tutto il sistema è gestito tramite eventi (anche un sistema operativo come Windows funziona per mezzo di eventi). Ma che cos’è un evento? Lo si può paragonare ad un segnale che informa che un qualcosa si è verificato. Questo qualcosa può essere di vario tipo: la pressione di un tasto della tastiera, un click del mouse, lo spostamento del mouse ecc. In realtà ogni evento ha un livello di dettaglio molto maggiore, si consideri ad esempio una finestrella come la seguente:

Un click sul bottone Sì, un click sul bottone No o uno sul bottone Annulla generano eventi di tipo click, ma deve esserci qualcosa che li differenzi tra loro per poter sapere dove il click è stato fatto. In un sistema pilotato dagli eventi, ad ogni evento deve essere associata una porzione di programma (detta subroutine) che svolge un compito ben preciso, nell’esempio sopra, azioni diverse devono essere intraprese a seconda di quale bottone venga premuto. Torniamo al nostro programma di calcolo. Abbiamo capito che il codice Visual Basic scritto sopra deve costituire la subroutine che risponde all’evento click effettuato su CommandButton1. Per associare il codice al bottone facciamo un doppio click sul bottone stesso: si apre una finestra che ha una riga iniziale e una finale già scritte, tra queste collochiamo le nostre quattro righe. Il tutto dovrebbe presentarsi come la figura seguente:

Un primo esperimento

13

La riga iniziale: Private Sub CommandButton1_Click() è composta di alcune parti (trascuriamo Private): Sub sta per subroutine e indica che questa è una subroutine, ossia un insieme isolato di righe di codice; CommandButton1 indica che si tratta della subroutine associata proprio a quel bottone, Click() specifica che la subroutine in questione risponde all’evento Click sul bottone dal mouse. Prima di far funzionare il nostro programma, è bene salvarlo su disco. Per fare questo si va nel menu File e si sceglie Salva (o Save). Questo non solo salva il nostro programma, ma anche la cartella Excel da cui siamo partiti (o il documento Word se siamo partiti da questo). In particolare, il nostro programma è una parte del file Excel (o Word) e non ne è separabile. Excel o Word chiama Macro questo codice, Macro sta per Macroistruzioni: si tratta di comandi che l’utente crea per sé e che vengono aggiunti alle funzionalità del programma stesso. Ad esempio si può scrivere una macro di Word (e avere il relativo bottoncino tra quelli di Word) che trasforma in un colpo solo il testo selezionato in Arial, corsivo, 12 punti, rosso su sfondo viola, cosa che se fatta ogni volta a mano richiederebbe parecchie manovre e tempo. Se abbiamo attivato il Visual Basic da Excel possiamo mandare in esecuzione il nostro programma, se invece lo abbiamo attivato da Word dobbiamo prima chiudere Word, riavviarlo e riaprire il documento: ora Word ci chiede se si vogliono abilitare le Macro e dobbiamo rispondere affermativamente. A questo punto il nostro programma può essere eseguito anche da Word. Mandiamo dunque in esecuzione il nostro programma: in alto al centro vi sono tre icone: da sinistra a destra il loro significato è: Esegui, Sospendi, Termina; quindi per eseguire il nostro programma facciamo click sul triangolino (o premiamo il tasto F5). Il programma ora è in esecuzione (si dice in gergo che sta “girando”). Ci presenta la nostra finestra con il bottone Calcola e attende. Che cosa? Eventi! In realtà l’unico evento che sa intercettare è quello relativo alla pressione del

14

Capitolo 2

bottone (quelli per i quali non c’è una subroutine di gestione vengono semplicemente ignorati). Premiamo quindi il bottone Calcola ed ecco che la prima delle InputBox viene eseguita generando una finestrella e chiedendo di introdurre il primo valore; scriviamo un numero. La finestrella di input non scompare finché non premiamo il bottone OK. Quando lo facciamo l’esecuzione riprende dalla riga successiva, infatti appare la finestrella della seconda InputBox; introdotto il secondo valore e premuto OK il programma passa alla riga successiva, quella dove si trova la sottrazione e l’assegnazione del risultato alla variabile D. Questa istruzione non coinvolge l’utente (non è un’operazione di input/output) e quindi non se ne nota l’esecuzione. Dopo averla eseguita il programma passa alla successiva dove la MsgBox visualizza la finestrella con il risultato D. Quando premiamo il tasto OK la finestrella con il risultato scompare e il programma ritorna ad aspettare eventi. Per terminare oppure facciamo click sulla il programma premiamo il bottone Termina in alto a destra della finestra del nostro programma. Normalmente, però, tutti i programmi hanno un bottone di uscita, ad esempio con caption End o FINE. Come esercizio si crei il summenzionato bottone posizionandolo sotto l’altro e mettendo nella sua subroutine di gestione la sola istruzione End che appunto termina il programma. Se le cose sono state fatte bene la subroutine dovrebbe chiamarsi CommandButton2_Click() e la subroutine avere 3 righe (delle quali il nostro contributo è solo la End. Si ricordi che per modificare un programma è necessario che questo sia stato precedentemente fermato (se non si riescono a modificare le istruzioni di un programma, di solito ci si è semplicemente dimenticati di fermarne l’esecuzione). Si possono mettere più istruzioni Visual Basic su una stessa riga separandole con il carattere due punti: D = X – Y : MsgBox D ma è meglio evitare a favore di una maggior chiarezza. Più utile, invece, è poter continuare una riga lunga a capo: basta aggiungere il carattere “_” preceduto da uno spazio alla fine della riga da continuare a capo e appunto continuare la riga a capo. Si può andare a capo in ciascun punto dove si può collocare uno spazio, ma non si può spezzare su più righe una stringa (si scoprirà più avanti che cos’è una stringa). Ad esempio, invece di scrivere: X = InputBox("Primo valore", "Valore", "0") si può scrivere: X = InputBox("Primo valore", _ "Valore", "0") ma attenzione che non si può andare a capo dopo Primo perché lo spazio fa parte di una stringa (è dentro i doppi apici).

Un primo esperimento

2.1

15

Esercizi

1) Scrivere un programma Visual Basic che chieda 3 numeri A, B e C dalla tastiera e visualizzi in MsgBox diverse: A – B, A – C e A – B – C. 2) Scrivere un programma Visual Basic che chieda 2 numeri A e B dalla tastiera, scambi il contenuto delle due variabili e li visualizzi. Ad esempio se ad A viene assegnato il valore 12 e a B il valore 27, il programma deve far sì che il 12 venga scambiato con il 27 (in altre parole inizialmente A contiene 12 e B 27, dopo lo scambio A deve contenere 27 e B 12). Non si risolva questo problema semplicemente visualizzando i valori delle variabili in ordine inverso: lo scopo non è visualizzare due numeri in ordine inverso, ma di scambiare il contenuto di due variabili. La struttura del programma dovrà quindi essere questa: A = InputBox("Introduci A") B = InputBox("Introduci B") qui si scrivono le istruzioni di scambio valori MsgBox A MsgBox B

16

Capitolo 2

Variabili e tipi numerici

3

17

Variabili e tipi numerici

Si è detto che le variabili sono “contenitori” di numeri; più correttamente dovremmo dire che sono contenitori di dati: i numeri sono solo un esempio di dati. I nomi delle variabili in Visual Basic sono lunghi al massimo 256 caratteri, 1 come minimo; il primo carattere deve essere una lettera, i successivi possono essere sia lettere sia cifre sia il carattere di sottolineatura. È buona norma dare alle variabili nomi significativi del contenuto: sarà più semplice sviluppare e correggere il codice. Non si possono usare nomi che il Visual Basic già conosce, quali ad esempio InputBox, MsgBox, e molte altre (vengono chiamate keyword del linguaggio). È preferibile usare nomi che iniziano con una lettera minuscola. Nomi validi sono ad esempio i seguenti: A i somma sommaAlQuadrato somma_2 sommaElevato2 In Visual Basic le lettere maiuscole e quelle minuscole sono considerate uguali: per questo le variabili SOMMA e soMmA sono la stessa cosa. Una variabile può essere usata come operando in un’operazione matematica (ad es. X + Y) o per ricevere un valore per mezzo di un’operazione di assegnazione (ad es. S = 3 + 5). Si noti che il simbolo di eguaglianza assume un significato diverso da quello usualmente assunto in matematica: A=B in matematica è un’equazione che indica che A ha lo stesso valore di B. In Visual Basic (come nella maggior parte dei linguaggi di programmazione) A=B indica che dopo l’esecuzione dell’istruzione A=B, A assume il valore che aveva B (e che continua ad avere, è una copia di valore, non un trasferimento). Così mentre A=A+1 in matematica è un assurdo, in programmazione significa che A, dopo l’esecuzione di questa istruzione, viene incrementata di uno. Le variabili non hanno solo un nome, ma anche un tipo. Ossia ci sono variabili adatte a contenere numeri interi, variabili adatte a contenere numeri con la

Capitolo 3

18

virgola, variabili adatte a contenere una qualsiasi sequenza di caratteri (sono dette stringhe e ce ne occuperemo più avanti), variabili adatte a contenere i valori vero e falso (dette logiche o booleane), variabili speciali adatte a contenere qualsiasi tipo di dato (dette variant). Ne esistono anche altri tipi, ma non vengono qui considerati. A ciascuna delle variabili utilizzate in un programma, l’interprete Visual Basic deve assegnare un tipo appropriato, questa operazione si ottiene esplicitamente mediante la dichiarazione (o definizione) delle variabili. Questa operazione riserva (alloca) memoria per contenerne il valore. In genere le variabili vengono dichiarate tutte quante all’inizio (subito dopo la Private Sub). Se una variabile non viene dichiarata esplicitamente, il suo tipo viene stabilito dall’interprete in modo generico: il tipo Variant. Si sconsiglia vivamente di utilizzare il modo implicito e il tipo Variant: può avere comportamenti “strani” (o meglio non previsti, ne vedremo un esempio in seguito) e soprattutto, salvo poche eccezioni, indica che il programmatore non ha le idee chiare sull’uso che farà della variabile. L’istruzione Dim viene utilizzata per dichiarare una variabile: Dim Nome As Tipo essendo Nome il nome della variabile e Tipo il tipo da associarle.

3.1

Variabili numeriche

In Visual Basic si dispone di 2 tipi di variabili intere e di 2 tipi di variabili reali; le variabili intere sono memorizzate in Complemento a 2, quelle reali in formato floating point IEEE P754 (mantissa ed esponente). I due tipi interi sono Integer e Long, i due reali sono Single e Double. Una variabile Integer occupa 2 byte di memoria e può contenere valori interi compresi tra –32768 e +32767 (circa ±30000). Una variabile Long (intero lungo) occupa 4 byte di memoria e può contenere valori interi compresi tra –2147483648 e +2147483647 (circa ±2 miliardi); una variabile Long può contenere tutti i valori che può contenere una variabile Integer. Una variabile Single (singola precisione) occupa 4 byte di memoria e può contenere valori compresi tra (circa) 1.410–45 e 3.410+38, positivi e negativi, quindi numeri molto grandi o molto piccoli, con una precisione di circa 7 cifre (in base 10), ad esempio –123.456710–12. Una variabile Single può contenere tutti i valori che può contenere una variabile Long. Una variabile Double (doppia precisione) occupa 8 byte di memoria e può contenere valori compresi tra (circa) 4.910–324 e 1.710+308, positivi e

Variabili e tipi numerici

19

negativi, quindi numeri molto grandi o molto piccoli, con una precisione di circa 15 cifre (in base 10), ad esempio –1234567.890123451023. Una variabile Double può contenere tutti i valori che può contenere una variabile Single. Una variabile Variant in realtà non è una variabile numerica, è una variabile che può contenere valori di qualsiasi tipo, tra cui anche quelli numerici e quelli stringa. Essa utilizza un numero variabile di byte a seconda del tipo di dato che contiene, inoltre ha comportamenti particolari che devono essere ben noti al programmatore (si provi ad esempio a modificare l’esercizio del Sottrattore facendo una somma invece che una sottrazione, il simbolo + non esegue più una somma, ma affianca i valori! La spiegazione è rimandata a quando si conosceranno le stringhe, in particolare alla funzione Val descritta nel paragrafo 6.3.6). È bene evitare questo tipo di variabile quando possibile. I calcoli con valori floating point sono più lenti di quelli con valori interi, inoltre più sono i bit da calcolare più il calcolo è lento; anche l’occupazione di memoria può essere importante: una matrice di un milione di elementi occupa 2 MB se si tratta di valori Integer, 8 MB se si tratta di Double. Riassumendo: per avere le migliori prestazioni e un minor utilizzo di memoria è consigliabile utilizzare se possibile il tipo Integer, se non basta si usi un Long, se non basta o servono valori con la virgola un Single e se proprio si vogliono 15 cifre di precisione un Double. Consideriamo ancora il tipo Boolean, una variabile di questo tipo può contenere solo due valori: True e False, ne parleremo in seguito. Errore comune è scrivere: Dim A, B, C As Integer pensando che le tre variabili siano definite tutte di tipo Integer, in realtà solo C viene definita di tipo Integer, mentre A e B sono definite di tipo Variant. Si potrebbe usare la seguente sintassi: Dim A As Integer, B As Integer, C As Integer ma non si ottiene un significativo miglioramento rispetto a: Dim A As Integer 'coeff. a equazione 2o grado Dim B As Integer 'coeff. b equazione 2o grado Dim C As Integer 'termine noto eq. 2o grado Inoltre, quando opportuno, i programmatori accanto ad ogni definizione di variabile ne indicano l’uso mediante un commento (come nell’esempio precedente) e la seconda modalità è più adatta per questo scopo. Attenzione all’input dei numeri frazionari, se il sistema operativo è configurato con lo standard italiano, si deve usare la virgola (3,1415), se con lo standard anglosassone, si deve usare il punto decimale (3.1415).

20

Capitolo 3

3.1.1 Espressioni numeriche I calcoli tra valori vengono chiamati espressioni, un’espressione produce un valore e questo o viene confrontato con altri o viene stampato o viene memorizzato in una variabile (assegnazione). Un’espressione è composta da operatori (+,–,*,/ ecc.), da operandi, da funzioni (Sin, Cos, Tan ecc.) e da parentesi; gli operandi possono essere variabili o costanti numeriche. Nell’esempio sotto, sulla destra del segno di uguale viene calcolata un’espressione e il risultato viene assegnato alla variabile Delta: delta = b^2–4*a*c La tabella seguente elenca gli operatori numerici del Visual Basic. Operazione Simbolo + somma – sottrazione * prodotto / divisione \ divisione intera Mod Resto ^ Elevamento a potenza Note: 1) la divisione tra valori interi produce un valore frazionario (3/2 dà 1.5), diversamente da altri linguaggi di programmazione; 2) la divisione intera e il resto si possono applicare anche a valori frazionari, ma in questo caso gli operandi vengono prima arrotondati all’intero più vicino e il risultato viene poi troncato al valore intero precedente (5.4 \ 2.6 viene visto come 5 \ 3 e produce come risultato 1 e non 1.666667); 3) il Mod si usa come fosse un simbolo: X = 17 Mod 5 calcola il resto della divisione di 17 per 5 e il risultato prodotto (2) viene messo in X; 4) nell’elevamento a potenza, se l’esponente è frazionario la base deve essere positiva (3 ^ 2.2). 3.1.2 Valutazione delle espressioni numeriche Quando viene calcolata un’espressione, i valori intermedi vengono memorizzati temporaneamente in variabili “senza nome” (il programmatore non ha necessità di utilizzarle direttamente, quindi non è necessario che vengano identificate in alcun modo). Quando il calcolo è terminato i valori intermedi (ossia le variabili senza nome) non servono più e vengono cancellati. Si consideri ad esempio l’istruzione X=A+B*C senza considerare il tipo delle variabili e facendo riferimento alla figura seguente.

Variabili e tipi numerici

21

Come prima operazione viene calcolato il X = A + B * C prodotto B*C e il risultato viene messo in una variabile senza nome (che per identificare in questo esempio indichiamo con ), il  contenuto di questa variabile viene sommato ad A e il risultato messo in una seconda variabile senza nome (), il contenuto di questa  seconda variabile viene copiato in X e le due variabili senza nome vengono cancellate. Di che tipo sono le variabili senza nome che il sistema si gestisce da sé? Quando un’operazione è relativa a due valori (variabili o costanti) dello stesso tipo, il risultato dell’operazione (e quindi la variabile senza nome) è dello stesso tipo dei due operandi. Quindi se le variabili A, B e C dell’esempio precedente sono tutte Integer, anche  e  lo sono (della variabile X parleremo più avanti). Se invece i due valori sono di tipo diverso, il valore del tipo meno “capiente” viene prima convertito (promozione) automaticamente nel tipo più “capiente” (indicando con questo termine il fatto che un Long può contenere un Integer, un Single può contenere un Long o un Integer, un Double può contenere un Single, un Long o un Integer). La promozione crea una variabile temporanea senza nome del tipo più capiente dei due e vi copia il valore della variabile promossa (ad esempio, quando si sommano un Integer e un Single, dall’Integer in complemento a 2 si calcola il valore corrispondente in floating point (di tipo Single) e solo dopo si può calcolare la somma). Attenzione: la variabile promossa continua ad essere del tipo che era prima della promozione, dimensionata con Dim, è la variabile temporanea che ha un altro tipo, anche se ha lo stesso valore. Il calcolo viene poi effettuato utilizzando questa variabile temporanea e non quella originale. Riprendiamo l’esempio precedente, ora sono indicati anche i X = AS + BS * CI tipi delle variabili mediante una lettera in alto a destra delle variabili stesse: una I indica che il tipo della variabile è Integer, S che il tipo S è Single. La prima operazione da eseguire è la moltiplicazione B*C, ma le due variabili sono S di tipo diverso: B è Single e C è Integer. Tra i due tipi il più capiente è il Single per cui viene creata una variabile temporanea  di S questo tipo per contenere il valore di C.

22

Capitolo 3

Viene quindi effettuata la moltiplicazione tra B e  (che contiene il valore di C) e il risultato ha il tipo di entrambe, ossia Single. La successiva operazione è la somma di  con A, ma avendo entrambe le variabili lo stesso tipo (Single) non c’è bisogno di promozione e la variabile intermedia  ha anch’essa il tipo Single. Alla fine  viene copiata in X (della variabile X parleremo tra poco) e le variabili intermedie vengono eliminate. Un esempio numerico: A valga 5.2, B valga 2.1 e C valga 3. La promozione calcola un  pari a 3.0, la moltiplicazione calcola 2.1*3.0 producendo un  pari a 6.3 e la somma produce un  pari a 11.5 . La promozione dei valori in un’espressione avviene automaticamente solo nel momento in cui questa è necessaria; si consideri l’esempio seguente. o La prima operazione da calcolare è il X = AS + BI * CI prodotto B*C; essendo le due variabili di tipo Integer, il risultato  è un valore I temporaneo di tipo Integer.  o Il risultato  deve essere sommato ad A che è di tipo Single, quindi prima di fare la somma,  deve essere trasformato in un S altro valore temporaneo  di tipo Single. o Viene quindi fatta la somma di  e A, il S risultato  è di tipo Single e viene  copiato in X. Attenzione al caso seguente: Dim A As Integer, B As Integer, C As Long A=30000 B=2 C=A*B Nonostante C possa contenere il valore 60000 perché di tipo Long, il programma dà errore di overflow (traboccamento) perché A e B sono di tipo Integer e il loro prodotto è dello stesso tipo (la variabile temporanea), ma 60000 non è rappresentabile su un Integer. Non importa che C sia un Long in quanto è il risultato del calcolo che dà overflow, non l’assegnazione a C (non si arriva neanche all’assegnazione: l’errore avviene prima). Come risolvere questo problema? Ci sono diversi metodi, tra cui i seguenti. 1) Si definisce almeno una delle due variabili di tipo Long e non Integer, così grazie alla promozione dell’altra, il tipo di quella temporanea è anch’esso Long e il risultato non dà overflow.

Variabili e tipi numerici

23

2) Si chiede esplicitamente al traduttore di convertire almeno uno dei valori in Long. Per far questo dobbiamo usare una funzione di conversione, così facendo ci si riconduce al caso precedente. Questo secondo metodo permette al programmatore di non dover cambiare il tipo prescelto per le variabili (la scelta dei tipi delle variabili è dettata da esigenze che il programmatore ha valutato in fase di studio del programma) e per questo è preferibile. Alla fine del paragrafo successivo si trova la soluzione del problema seguendo questa modalità. 3.1.3 Principali funzioni di conversione di tipo Creano variabili temporanee del tipo richiesto, aventi come valore quello indicato tra parentesi. Int(A) converte il valore di A in Integer (o meglio crea una variabile temporanea di questo tipo) troncando la parte decimale, restituisce il valore intero più a sinistra (inteso sulla retta dei numeri reali); +3.2  +3 +3.6  +3 –3.2  –4 –4 –3.6 –3.2 –3 0 3 3.2 3.6 4 –3.6  –4 Fix(A) converte il valore di A in Integer troncando la parte decimale, restituisce il valore intero più vicino allo zero; +3.2  +3 +3.6  +3 –4 –3.6 –3.2 –3 0 3 3.2 3.6 4 –3.2  –3 –3.6  –3 CInt(A)converte il valore di A in Integer approssimandolo al valore intero più vicino (arrotondamento); +3.2  +3 +3.6  +4 –3.2  –3 –4 –3.6 –3.2 –3 0 3 3.2 3.6 4 –3.6  –4 Per questioni statistiche, i valori x.5 (positivi e negativi) vengono approssimati al valore: - successivo se x è dispari, - precedente se x è pari CInt(1.5)  2 CInt(2.5)  2 CInt(–1.5)  –2 CInt(–2.5)  –2

24

Capitolo 3

CLng(A) converte il valore di A in Long (stesse considerazioni di Cint) CSng(A) converte il valore di A in Single CDbl(A) converte il valore di A in Double Ecco il secondo modo di risolvere il problema dell’overflow indicato nel paragrafo precedente: C = A * CLng(B) oppure C = CLng(A) * B oppure C = CLng(A) * CLng(B) Ma scrivere: C = CLng(A*B) è assolutamente inutile: è il calcolo che produce overflow e non l’assegnazione; qui il calcolo viene comunque effettuato su variabili Integer dando errore. Quando si assegna ad una variabile il risultato di un’espressione, viene attuata automaticamente una conversione al tipo della variabile stessa (questo avviene anche nel passaggio dei parametri alle funzioni e subroutine). La funzione di conversione utilizzata automaticamente è una di queste: CInt, CLng, CSng o CDbl. Si consideri l’esempio seguente: Dim A As Single Dim X As Integer A = 2.342 X = A qui l’assegnazione viene eseguita come se fosse scritta: X = CInt(A) Si noti che diversamente da altri linguaggi, l’assegnazione di un valore reale ad una variabile intera non tronca la parte frazionaria, ma la approssima all’intero più vicino (con il problema dell’approssimazione dei valori x.5 già considerato). Se si vuole troncare si devono usare le funzioni Int e Fix. Esistono molte altre funzioni di conversione, ai nostri scopi queste sono sufficienti.

Variabili e tipi numerici

25

3.1.4 Funzioni intrinseche Sono funzioni fornite dal linguaggio stesso, ossia programmate dagli sviluppatori dell’interprete. Le funzioni intrinseche accettano espressioni di tipo diverso e in generale restituiscono un Double. Alcune funzioni matematiche che è utile conoscere sono le seguenti: Funzione Significato Sin(A) seno di A Cos(A) coseno di A Tan(A) tangente di A Atn(A) arcotangente di A Log(A) logaritmo naturale di A Log10(A) logaritmo in base 10 di A Exp(A) e elevato ad A Abs(A) valore assoluto di A Sqr(A) radice quadrata di A Sgn(A) segno di A: –1 se negativo, 0 se nullo, +1 se positivo Note: 1) le funzioni trigonometriche richiedono angoli espressi in radianti (1  rad = 180°); 2) la funzione Sgn restituisce un Variant e non un Double. Per maggiori dettagli su queste funzioni si consulti la guida in linea. Si possono utilizzare per ricavare il valore delle costanti, ad es. =4*Atn(1) 3.1.5 Precedenza e associatività degli operatori Un’espressione può contenere diversi operatori e il risultato può dipendere dall’ordine di valutazione degli operatori. Ad esempio A+B*C produce un certo risultato se viene calcolato prima il prodotto e poi la somma, ma produrrebbe un risultato diverso se venisse calcolata prima la somma e poi il prodotto. Viene chiaramente eseguito prima il prodotto e poi la somma (si dice che il prodotto ha priorità o precedenza maggiore rispetto alla somma) in quanto il linguaggio è stato progettato in modo Parentesi da essere conforme alle regole aritmetiche Funzioni classiche. Nella tabella a fianco sono riportati Potenza gli operatori in ordine di priorità decrescente. Moltiplicazione, divisione Le parentesi (sempre e solo tonde, mai quadre Divisione intera o graffe) possono essere utilizzate per forzare la valutazione delle espressioni nel modo Resto voluto, ad esempio se vogliamo che venga Somma e sottrazione

26

Capitolo 3

prima fatta la somma e poi la moltiplicazione possiamo scrivere (A+B)*C. Nelle espressioni gli stessi operatori possono essere utilizzati più volte e alcuni operatori hanno lo stesso livello di precedenza (somma e sottrazione, moltiplicazione e divisione), ecco alcuni esempi: A–B+C A*B/C A*B*C A–B–C A^B^C In questo caso l’ordine di valutazione degli operatori è stabilito dalle regole di associatività: in Visual Basic è sempre da sinistra a destra per tutte le operazioni (incluso l’elevamento a potenza, diversamente da altri linguaggi). Quindi le cinque espressioni sopra vengono valutate come se ci fossero le parentesi indicate nelle cinque espressioni qui sotto: (A–B)+C (A*B)/C (A*B)*C (A–B)–C (A^B)^C 3.1.6 Costanti numeriche Nelle espressioni si utilizzano non solo variabili, ma spesso anche valori costanti, ad esempio l’area di un triangolo verrà calcolata con l’espressione BASE*ALTEZZA/2, il 2 è una costante numerica. Anche le costanti numeriche hanno un tipo:  una costante intera è una sequenza di cifre senza virgola né esponente, è di tipo Integer se il valore è compatibile con tale tipo, altrimenti è un Long; esempi di costanti Integer sono 1234, –23438; esempi di costanti Long sono 123456, –234567;  una costante floating point è una sequenza di cifre con un punto decimale (non si usa la virgola decimale nel codice Visual Basic) e/o un esponente (valore intero positivo o negativo), è di tipo Single se il numero di bit è sufficiente, Double altrimenti; esempi di costanti floating point di tipo Single sono –1234.625, 23.0, 34E4 (che significa 34104), –23.625E–18 (che significa –23.62510–18); esempi di costanti floating point di tipo Double sono –12345.6789012121, –12.4 (0.4 in binario è periodico!), 34E204 (che significa 3410204), –23.4E–18 (che significa –23.410–18).

Variabili e tipi numerici

27

È possibile indicare il tipo che si desidera per una costante aggiungendo al numero stesso un carattere speciale:  esempio di costante Integer: 12%  esempio di costante Long: 12&  esempio di costante Single: 12!  esempio di costante Double: 12# Quindi l’espressione A*12! moltiplica A per una costante Single di valore 12 (anche se non c’è l’indicazione di alcun decimale). Ecco un esempio in cui è utile definire il tipo delle costanti. Si supponga ad esempio di voler calcolare l’area di un milione di triangoli, note basi e altezze come valori Single, se la formula usata è B*H/2, la costante 2 è considerata Integer e ogni volta il traduttore ne deve effettuare la promozione a Single, un milione di volte! Se invece la formula è B*H/2!, il 2 è già di tipo Single e quindi non si ha il milione di promozioni. Si poteva anche utilizzare la scrittura 2.0 (è un valore di tipo Single anche in questo caso). Talvolta è utile dare un nome ad una costante, ecco come si definiscono una costante Single di nome PiGreco e una costante Double di nome hPlank (non possono essere espressioni aritmetiche): Const PiGreco As Single = 3.1415926 Const hPlank As Double = 6.626176E-34

Capitolo 3

28

3.2

Esercizi

1) Scrivere un programma Visual Basic che chieda all’utente di introdurre 4 valori di tipo intero e ne calcoli la media (risultato di tipo reale). 2) Scrivere un programma Visual Basic che chieda all’utente di introdurre un valore di temperatura (di tipo intero) in gradi Fahrenheit e calcoli e “stampi” (cioè visualizzi) i corrispondenti valori in gradi Celsius e Kelvin (entrambi di tipo reale). [C=5/9*(F–32); K=C+273.15]. 3) Un oggetto che si muove ad una velocità v confrontabile con quella della luce c (2.99793ꞏ108 m/s) si accorcia (nel senso della direzione) e aumenta di massa di un fattore  (minore di 1). Si scriva un programma che chieda la lunghezza e la massa di un oggetto fermo e calcoli la 2 v variazione delle due grandezze a quella velocità (richiesta   1    c in input in km/s). 4) Si scriva un programma per calcolare la distanza in linea d’aria tra due punti della superficie terrestre, note le coordinate geografiche. Il programma chiede i valori di latitudine (N-S) e di longitudine (E-O) in gradi dei due punti. Per calcolare la distanza si usi la seguente formula (le coordinate Nord e Est sono positive, Sud e Ovest negative e si ricordi che le funzioni trigonometriche utilizzano i radianti):

d  arccos( p1  p2  p3)  r

dove: r è il raggio medio della Terra: 6372.795 km p1 = cos(lat1)*cos(lon1)*cos(lat2)*cos(lon2) p2 = cos(lat1)*sin(lon1)*cos(lat2)*sin(lon2) p3 = sin(lat1)*sin(lat2) essendo: lat1 latitudine in gradi del primo punto lon1 longitudine in gradi del primo punto lat2 latitudine in gradi del secondo punto lon2 longitudine in gradi del secondo punto N.B. La formula considera la terra sferica con raggio medio r: non essendolo, la formula dà un risultato con un errore massimo dello 0.5%. Per la formula del arco-coseno si utilizzi la formula seguente:  x    arccos( x)  arctan 2   1 x  2 Calcolare le distanze tra gli aeroporti di: Torino (TRN, 45.02ºN, 07.65ºE), Roma (FCO, 41.81ºN, 12.25ºE) e Los Angeles (LAX, 33.94ºN, 118.40ºW). [TRN-FCO: 515.20 km, TRN-LAX: 9692.7 km, FCO-LAX: 10205.48 km]

Input/Output da tastiera e su video

4

29

Input/Output da tastiera e su video

Il punto di vista di un’operazione di input/output (I/O) è sempre quello del microprocessore, quindi un’operazione di input (che significa “mettere dentro”) consiste nel prelevare un valore dall’esterno (dalla tastiera ad esempio) e memorizzarlo in una variabile; mentre un’operazione di output (che significa “mettere fuori”) consiste nel mandare all’esterno un valore (ad esempio sul video). Questo capitolo fornisce ulteriori informazioni sulle già note istruzioni InputBox e MsgBox. Esistono in Visual Basic molte altre istruzioni di Input/Output, ma queste sono le essenziali e più semplici, anche se non certo le migliori in ogni circostanza. Altra possibilità è costituita dalle TextBox descritte nel paragrafo 13.1.

4.1

L’istruzione MsgBox

L’istruzione MsgBox viene usata per visualizzare in una finestrella il valore di una variabile, o più in generale il risultato di un’espressione, indicata tra parentesi. La sua sintassi più in dettaglio (anche se non nella sua completezza) è la seguente (le parentesi possono anche essere omesse, comunque si noti la posizione della parentesi di chiusura): MsgBox (prompt), buttons, title

prompt è ciò che verrà visualizzato, title è il titoletto della finestrella, buttons serve per indicare che nella finestrella non vogliamo solo il bottone OK, ma anche altri. Non considereremo i bottoni. Alcuni esempi. MsgBox 12 visualizza il numero 12, MsgBox 3*X visualizza il risultato del calcolo 3*X. Per visualizzare una scritta (ossia una sequenza di caratteri, detta stringa), questa deve essere racchiusa tra doppi apici: MsgBox "Ciao". Che cosa sarebbe successo se non avessimo messo i doppi apici? Il traduttore Visual Basic avrebbe considerato Ciao come il nome di una variabile; non avendola mai incontrata prima (non essendo stata dichiarata con Dim) la definirebbe ora in modo implicito, quindi di tipo Variant, e vuota. Quindi la MsgBox ne mostrerebbe il contenuto, vuoto, visualizzando una finestrella

30

Capitolo 4

assolutamente vuota. Scopriremo nell paragrafo 14.1 come evitare questo problema con la direttiva Option Explicit. Poiché la MsgBox vuole un unico prompt, per visualizzare più elementi affiancati nella stessa finestrella li si unisce per mezzo dell’operatore & (attenzione a mettere sempre uno spazio sia prima sia dopo il carattere &): MsgBox "Ci sono " & X & " valori" In questo esempio si hanno due sequenze di caratteri (stringhe): la prima è composta dai caratteri “Ci sono ”, la seconda da “ valori”; supponendo che X contenga il valore 10, l’istruzione MsgBox visualizzerà nella finestrella: Ci sono 10 valori Si notino gli spazi dopo sono e prima di valori: se non li avessimo messi, avremmo ottenuto la scritta: Ci sono10valori La MsgBox converte in stringa ciò che si trova nel campo prompt, anche i valori numerici (dopo aver calcolato le espressioni). Anche l’operatore & che unisce le stringhe (si dice che le concatena) trasforma in stringa tutto ciò che gli sta accanto (la X dell’esempio precedente è valore di tipo numerico, quale un Integer, ma viene trasformato nella sequenza di caratteri 1 e 0). Sia title sia buttons possono essere omessi, come nel primo esperimento del Sottrattore; ma per indicare solo title e omettere buttons si deve scrivere come segue (attenzione alle due virgole che indicano di saltare il campo dei buttons, inoltre si noti la posizione delle parentesi – che si possono anche omettere): MsgBox "Ci sono " & X & " valori",, "Conteggio" E l’output generato è indicato nella figura sotto, a sinistra, dove Conteggio è il titoletto (title). Se volessimo stampare su più righe, dovremmo indicare i punti di ritorno a capo all’interno del prompt stesso. I punti di ritorno a capo si indicano con vbNewLine, si tratta di una stringa costante definita dal sistema. Quindi per scrivere su tre righe la scritta precedente, dovremmo scrivere (tralasciamo il titoletto per esigenze tipografiche): MsgBox "Ci sono" & vbNewLine & X & vbNewLine & "valori" vbNewLine è una stringa che quando viene visualizzata fa andare a capo, dovendola concatenare si devono usare i caratteri &. Il risultato generato è indicato nella figura sotto, a destra.

Input/Output da tastiera e su video

4.2

31

L’istruzione InputBox

Una delle istruzioni di input da tastiera è la già nota InputBox; la sua sintassi più in dettaglio (anche se non nella sua completezza) è la seguente (le parentesi non possono essere omesse): variabile = InputBox(prompt, title, default) L’esecuzione di questa istruzione fa sì che sul video venga visualizzata una finestrella con la scritta indicata dal prompt (è una stringa e quindi può essere composta da altre stringhe concatenate insieme con l’operatore di concatenazione &). Il sistema si ferma in attesa che un valore venga introdotto e venga quindi premuto il bottone OK. Premuto il bottone OK, il valore scritto alla tastiera viene collocato temporaneamente in una variabile di tipo stringa e questo subito copiato nella variabile indicata. title serve per mettere un titoletto alla finestrella; default è la risposta tipica da mettere nel campo di introduzione dei dati, se va bene l’utente preme semplicemente OK, se non va bene l’utente la cancella e scrive altro. Esempio: X = InputBox("Primo valore", "Valore", "0") Quando il programma eseguirà la funzione InputBox verrà visualizzata la finestrella indicata nella figura sotto, si è supposto che il primo valore sia spesso uno zero così il default è stato impostato appunto a 0, se non va bene, l’utente lo cambierà.

Nomenclatura: default significa mancanza, in informatica un default è un qualcosa che viene automaticamente utilizzato se non viene specificato di usare qualcos’altro. I valori di default di un programma sono quelli che vengono da esso utilizzati se l’utente non indica altri valori. Ad esempio, quando si fa partire Word per scrivere un nuovo documento, il sistema imposta di default (ossia automaticamente perché non gli abbiamo ancora richiesto altro) un carattere di tipo Times New Roman 10 punti. Se ci va bene lo usiamo, altrimenti lo cambiamo (ossia specifichiamo ben precisi valori, non usiamo più quelli di default). Come già detto, l’input dei numeri frazionari, se il sistema operativo è configurato con lo standard italiano, richiede di usare la virgola (3,1415), se con lo standard anglosassone, richiede di usare il punto decimale (3.1415).

Capitolo 4

32

Poiché l’istruzione InputBox produce una stringa, quando si vuole leggere un valore numerico ed assegnarlo ad una variabile numerica (come nell’esempio) la stringa prodotta viene dapprima implicitamente interpretata dalla funzione Val (vedere 6.3.6 a pag. 52) per ricavarne il valore numerico e questo a sua volta convertito da una delle funzioni di connversione CInt, CLong, CSng e CDbl (con il problema dell’approssimazione dei valori x.5 già considerato).

4.3 1)

Esercizi Scrivere un programma che chieda 4 numeri interi da tastiera e li visualizzi uno sotto l’altro nella stessa MsgBox.

Esecuzione condizionale

5

33

Esecuzione condizionale

Finora abbiamo visto programmi composti da sequenze di istruzioni da eseguirsi una dopo l’altra nell’ordine in cui sono scritte nel programma. Spesso invece si ha la necessità di eseguire alcune istruzioni solo in determinati casi e altre istruzioni in altri casi. Ad esempio se si vuole calcolare la radice quadrata di un numero, si deve prima verificare che il numero sia positivo o nullo, altrimenti non si può calcolarla. Si parla di esecuzione condizionale: si eseguono alcune operazioni solo SE una certa condizione è verificata.

5.1

Il costrutto If-Then

Il costrutto principale di esecuzione condizionale è il costrutto If-Then: If condizione Then istruzioni End If

SE (If) la condizione è vera ALLORA (Then) vengono eseguite le istruzioni che seguono fino alla End If; se invece la condizione non è vera le istruzioni non vengono eseguite. In entrambi i casi l’esecuzione prosegue poi con le istruzioni dopo la End If. Si noti che il Then deve essere l’ultima istruzione della riga dove c’è l’If. Il blocco di istruzioni la cui esecuzione dipende da condizione viene scritto rientrato (indentazione) di alcuni spazi (consigliati 3) in modo che sia visivamente evidente. Ecco un esempio: F V numero = InputBox("Dammi un numero") N>0 If numero > 0 Then POS MsgBox "Il numero è positivo" End If MsgBox "FINE PROGRAMMA" In questo esempio viene richiesto un numero all’utente, se è positivo vengono visualizzate due MsgBox con le scritte “Il numero è positivo” e “FINE PROGRAMMA”, se è negativo o nullo la MsgBox interna all’If non viene eseguita e si ha solo la seconda MsgBox con “FINE PROGRAMMA”.

34

Capitolo 5

Graficamente si può rappresentare il flusso del programma mediante lo schema (flow chart) indicato sulla destra del codice (che in realtà rappresenta solo il costrutto If): il rombo indica la condizione (all’interno si indica la condizione da verificare), da esso si dipartono due rami che sono indicati con V e con F, il ramo con la V (detto ramo then) viene percorso se la condizione è Vera, il ramo con la F (detto ramo else) se è Falsa. Nel percorrere il ramo then si esegue l’istruzione indicata nel parallelogramma (si usa un parallelogramma quando l’operazione è di Input o di Output, un rettangolo se di altro tipo). Il ramo else non contiene alcuna istruzione). Se vogliamo che il programma scriva qualcosa anche se il numero non è positivo, possiamo modificarlo come segue: F V N>0 numero = InputBox("Dammi un numero") If numero > 0 Then POS MsgBox "Il numero è positivo" End If If numero 0 MsgBox "Il numero è positivo" Non POS Else POS MsgBox "Il numero non è positivo" End If MsgBox "FINE PROGRAMMA" In questo esempio, se il numero è positivo la condizione della If risulta essere vera e come prima viene scritto “Il numero è positivo”, ma se il numero è negativo o nullo la condizione non è vera e l’esecuzione passa ad eseguire le istruzioni dell’Else, quindi viene scritto “Il numero non è positivo”. Alla fine viene comunque scritto “FINE PROGRAMMA”. Questa istruzione If ha entrambi i rami contenenti istruzioni da eseguire.

Esecuzione condizionale

35

Modifichiamo ora il programma perché ci stampi “Il valore è nullo” quando viene appunto introdotto il valore zero nella InputBox. numero = InputBox("Dammi un numero") F V N>0 If numero > 0 Then POS MsgBox "Il numero è positivo" End If V F N 0 Then MsgBox "Il numero è positivo""  If esterno Else If numero < 0 Then MsgBox "Il numero è negativo"  If interno Else MsgBox "Il numero è nullo" End If End If MsgBox "FINE PROGRAMMA"

Capitolo 5

36

Se il numero è positivo, si va nel ramo then del primo If, ma se è negativo o nullo si va nel ramo else e dobbiamo ancora verificare se è negativo o se è nullo. Ecco che nel ramo else del primo If è stato messo un altro costrutto If-Then-Else-End If proprio per poter discriminare i due casi: negativo o nullo. Così facendo abbiamo minimizzato il numero di If da valutare. Si noti che il secondo costrutto If-Then-Else-End If è completamente (cioè dall’If all’End If) compreso in un ramo del primo. Il flow chart corrispondente si trova nella figura seguente. F

F

NUL

N0

V

POS

NEG

Essendo questo costrutto molto frequente, il Visual Basic fornisce una struttura alternativa utilizzando la clausola ElseIf (senza spazio in mezzo): numero = InputBox("Dammi un numero") If numero > 0 Then MsgBox "Il numero è positivo" ElseIf numero < 0 Then MsgBox "Il numero è negativo" Else MsgBox "Il numero è nullo" End If MsgBox "FINE PROGRAMMA" ElseIf vuol dire letteralmente altrimenti se. L’esecuzione qui avviene in questo modo: SE il numero è positivo ALLORA stampa “Il numero è positivo”, ALTRIMENTI SE il numero è negativo ALLORA stampa “Il numero è negativo”, ALTRIMENTI stampa “Il numero è nullo” in quanto è l’ultima delle 3 possibilità. La clausola ElseIf è tale per cui se la If o ElseIf precedente è vera, essa e le successive non vengono neppure considerate. Ossia se il numero è positivo (prima If vera) viene eseguita la stampa “Il numero è positivo” e tutte le istruzioni successive fino alla End If (che si noti è una sola) vengono saltate (è come se fossero in un ramo Else). Questo secondo costrutto è assolutamente equivalente a quello con gli If annidati.

Esecuzione condizionale

37

Ricapitolando, la forma completa di un’istruzione If è: If condizione1 Then istruzioni1 ElseIf condizione2 Then istruzioni2 Else istruzionie End If Le clausole ElseIf (opzionali) possono essere ripetute tante volte quante è necessario per considerare tutti i casi, mentre la clausola Else (opzionale) deve essere unica: è il caso che considera tutte le condizioni non espresse dalle If precedenti e viene detto caso di default. Sono quindi leciti costrutti con più ElseIf e senza Else: in questi casi, se nessuna delle condizioni delle If risulta essere vera, tutta l’istruzione If-Then-ElseIf-End If non produce alcun effetto (nessuna delle istruzionix viene eseguita), anche se, ovviamente, tutte le condizioni delle If vengono valutate e questo consuma tempo di elaborazione. Si noti come è scritto il codice:  Le parole chiave If, ElseIf, Else ed End If sono collocate alla stessa distanza dal margine sinistro, questo serve per avere ben evidenti i vari rami; inoltre possono essere precedute solo da spazi;  Le parole chiave Then ed Else devono essere le ultime parole delle righe dove compaiono; errore frequente è indicare una condizione dopo la clausola Else: oltre a non essere l’ultima parola della riga, anche dal punto di vista logico è sbagliato: Else indica “tutto il resto che non è stato precedentemente considerato”, quindi è inutile specificare questo “resto”);  I blocchi indicati con la parola istruzioni, che possono essere composti anche di molte righe, sono spostati ulteriormente sulla destra rispetto alle parole chiave (si dice che sono indentati) in modo che sia evidente da quale riga ne dipenda l’esecuzione. Si veda il paragrafo 14.2 per ulteriori dettagli. Anche se nell’esempio precedente le condizioni delle If e delle ElseIf erano tutte relative al valore Numero, in realtà queste sono assolutamente indipendenti tra loro, ossia possono contenere condizioni completamente diverse. Ad esempio scriviamo un programma che chieda due numeri, se il primo è maggiore di 10 lo stampi, altrimenti se il secondo è maggiore di 100 stampi il secondo, altrimenti (quindi se il primo è minore o uguale a 10 e il secondo minore o uguale a 100) ne stampi il prodotto.

Capitolo 5

38

primoNumero = InputBox("Dammi il primo numero") secondoNumero = InputBox("Dammi il secondo numero") If primoNumero > 10 Then MsgBox primoNumero ElseIf secondoNumero > 100 Then MsgBox secondoNumero Else MsgBox primoNumero*secondoNumero End If

5.2

Espressioni relazionali

Le condizioni espresse nelle istruzioni If sono tipicamente confronti tra due valori (vengono messi in relazione tra loro), ad esempio in: If X = 10 Then ... viene confrontata la variabile X con il valore 10, il risultato è vero se appunto X contiene il valore 10, falso altrimenti. Più in generale il confronto avviene tra due espressioni aritmetiche, o meglio tra i risultati prodotti da due espressioni aritmetiche: If X*(Y-Z^2) = Z-T*3.14 Then ... Gli operatori di confronto, detti relazionali, sono sei: Operatore Uguale Diverso Maggiore Maggiore o uguale Minore Minore o uguale

Simbolo =

> >= < PiGreco*raggio^2 If mag Then ... Nella variabile mag viene posto il valore True o False a seconda che area sia maggiore dell’area del cerchio o no. Se mag fosse stata una variabile di tipo Integer, le sarebbero stati assegnati, rispettivamente, i valori –1 e 0 invece di True e False. Il valore 0 in un contesto booleano viene considerato

Esecuzione condizionale

39

equivalente a False, mentre ogni altro valore a True, ma quando viene prodotto dal Visual Basic stesso, il valore numerico di True è –1. Poiché un qualsiasi valore non nullo viene considerato equivalente a True, in una condizione come X0 la parte “0” può essere omessa: If (X) Then ...

5.3

Espressioni logiche

Una condizione può essere composta da diversi confronti, per far questo bisogna specificare quando la condizione è complessivamente vera, ad esempio se basta che almeno uno dei confronti dia risultato vero oppure se è necessario che tutti i confronti diano risultato vero per far eseguire il ramo Then. Più precisamente, si usano operatori che collegano le espressioni relazionali tra di loro: questi si chiamano operatori logici (o anche booleani). 5.3.1 Operatore Or Se vogliamo scrivere una condizione che sia globalmente vera quando almeno uno (ma anche più di uno) dei confronti è vero, utilizziamo l’operatore Or: If eta = 65 OR giornoDelMese = 1 Then MsgBox "Entri gratis al museo" End If Qui la condizione è globalmente vera se Eta è minore di 12 OPPURE Eta è maggiore di 65 OPPURE se GiornoDelMese è uguale a 1, basta che anche uno solo dei tre confronti (età massima di 12 anni oppure almeno 65 anni oppure è il primo del mese) sia vero perché la condizione sia globalmente vera e venga stampata la scritta. 5.3.2 Operatore And Se vogliamo scrivere una condizione che sia globalmente vera solo quando tutti i confronti sono veri, utilizziamo l’operatore And: If voto >= 18 And voto 10 Then ... If Not(X 10 Or Y < 14 And Z = 3 * X * Y) L’espressione può eventualmente essere semplificata con il teorema di De Morgan. Ma non sempre se ne ottiene una forma di significato altrettanto chiaro.

5.4

Precedenza degli operatori

In una condizione vengono prima calcolate le espressioni aritmetiche, utilizzando le regole di precedenza e associatività già indicate, poi vengono valutate le espressioni relazionali e infine gli operatori logici. Il più prioritario degli operatori è il Not, seguito da And, seguito da Or ed infine da Xor, così l’esempio seguente: If a>10 Or b>10 And c>10 Then ... viene interpretato dalla macchina come se ci fossero le parentesi come indicato sotto: If a>10 Or (b>10 And c>10) Then ... e nel caso a=20, b=0, c=0 l’And dà risultato falso (le due relazioni sono false), ma la prima relazione è vera ed è in Or con il risultato dell’And (l’Or viene calcolato dopo l’And), quindi complessivamente il risultato è vero. Si possono

Esecuzione condizionale

41

all’occorrenza utilizzare esplicitamente le parentesi per forzare un diverso ordine di valutazione degli operatori logici, ad esempio in: If (a>10 Or b>10) And c>10 Then ... si forza prima la valutazione dell’Or e poi quella dell’And. Altro esempio, in: If x>0 And Not y N^(X-Y) Se si vogliono assegnare più risultati possibili a un singolo ramo Case, questi si possono indicare separati da virgole (che agiscono quindi come degli Or): Case valore1, valore2, valore3 Case valore1 To valore2, valore3 To valore4 Case Is > valore1, Is < valore2 Case valore1, valore3 To valore4, Is > valore5 Che cosa succede se gli insiemi di valori si intersecano? La prima clausola Case che soddisfa la condizione viene eseguita e le successive vengono saltate, anche qualora soddisfino la condizione. Un esempio: numero = InputBox( "Dammi un numero tra 0 e 10") Select Case numero Case Is > 10, Is < 0 MsgBox "Non è tra 0 e 10!" Case 2,4,6,8,10,12 MsgBox "Pari" Case 5 To 9 MsgBox "Compreso tra 5 e 9" Case 1,3,5,7,9 MsgBox "Dispari" End Select

Capitolo 5

44

Se il valore introdotto è 12, la prima Case soddisfa la condizione e viene visualizzato “Non è tra 0 e 10!”, quindi la seconda Case non viene neanche valutata. Se il numero introdotto è 8, la seconda Case soddisfa la condizione e quindi viene stampato “Pari”, quindi la terza Case non viene considerata. I numeri 5, 7 e 9 non producono la scritta “Dispari”. Due frequenti errori sono quelli che seguono, spesso commessi insieme: Select Case var = espressione Non si deve scrivere var = in quanto a destra di Select Case si deve indicare solo un’espressione. Attenzione che sintatticamente è corretto (non viene rilevato alcun errore dall’interprete): si tratta infatti di un confronto tra var e l’espressione, questo produce un valore True o False e tale valore viene cercato tra i Case valorei. Case var = 1 Case var = 2 Non si deve scrivere var = in quanto a destra dei vari Case si deve indicare un possibile risultato dell’espressione. Anche qui la sintassi è corretta: si tratta di un confronto tra var e un altro valore, questo produce un valore True o False e questo valore viene usato come risultato dell’espressione. Altro errore frequente è scrivere: Case Is > 0, Is < 10 pensando di determinare un intervallo tra 0 e 10 estremi esclusi, in realtà vengono considerati i valori maggiori di 0 OPPURE minori di 10, cioè tutti. Si usi la clausola To per indicare un intervallo.

5.6 1) 2) 3) 4) 5)

Esercizi Scrivere un programma che chieda due numeri da tastiera e dei due stampi il maggiore. Scrivere un programma che chieda tre numeri da tastiera e dei tre stampi il maggiore. Scrivere un programma che chieda tre numeri da tastiera e li stampi in ordine decrescente. Scrivere un programma che chieda un numero da tastiera e determini se è pari o dispari (consiglio: usare Mod). Scrivere un programma che chieda da tastiera di introdurre un numero intero corrispondente ad un voto e stampi a video “insufficiente” se è inferiore a 18, “appena sufficiente” (18), “basso” (19-20), “medio” (21-23), “buono” (24-26), “alto” (27-29), “massimo” (30).

Esecuzione condizionale

6)

7)

8)

9)

10)

45

La funzione arctan() dell’esercizio 4) del capitolo 3 dà errore quando x=1 a causa della divisione per zero. Si corregga il problema considerando che in questo caso la funzione arctan() dovrebbe dare il valore π/2. Calcolare la distanza tra i punti di coordinate 0o N 0o E and 0o N 180o E. [Risultato: 20020.726 km o 10810.327 NM] Si vogliono dividere gli allievi di un corso in tre squadre denominate ROSSA, VERDE e BLU, distribuendoli secondo il numero di matricola. L’assegnazione avviene con il seguente criterio: l’allievo con matricola 1 va nella squadra ROSSA, quello con matricola 2 nella VERDE, quello con matricola 3 nella BLU, quello con matricola 4 nella ROSSA, quello con 5 nella VERDE ecc. Il programma deve chiedere da tastiera il numero di matricola dell’allievo e deve indicare a quale squadra è stato assegnato (consiglio: usare Mod, non si pensi di elencare in qualche modo tutti i valori per le varie squadre!). Variazione dell’esercizio precedente: si chieda anche se l’allievo è straniero, in caso affermativo lo schema di assegnamento alla squadra deve seguire l’ordine opposto (BLU, VERDE, ROSSA). A tal fine chiedere all’utente di inserire, in altra InputBox, un 1 per indicare se è straniero e uno 0 se non lo è. Si scriva un programma che chieda i tre coefficienti a, b e c di un’equazione di secondo grado e calcoli i valori delle soluzioni se questi sono reali; nel caso non lo siano deve semplicemente scrivere a video “Valori non reali”. Scrivere un programma che dato il reddito (valore di tipo intero) calcoli la tassa (il risultato deve essere di tipo reale) secondo la regola:  10% sui redditi fino a 10 (migliaia di Euro);  15% sulla parte che eccede i 10 fino a 15;  20% sulla parte che eccede i 15 fino a 20;  25% sulla parte che eccede i 20 fino a 25;  30% sulla parte che eccede i 25 fino a 30;  35% sulla parte che eccede i 30. Esempi Un reddito pari a 7 viene tassato con un importo pari al 10% di 7 (0.7). Un reddito pari a 12 viene tassato con un importo che è la somma del 10% di 10 (pari a 1) e il 15% della parte eccedente che è 12–10 (15% di 2, pari a 0.3). Un reddito di 17 viene tassato con un importo che è la somma del 10% di 10 (pari a 1), del 15% di 15–10 (15% di 5, pari a 0.75) e del 20% di 17– 15 (20% di 2, pari a 0.4).

46 11)

Capitolo 5

Un anno non secolare (cioè non divisibile per 100) è bisestile se è divisibile per 4, mentre un anno secolare è bisestile se è divisibile per 400. Ad esempio l’anno 1900 non era bisestile, il 1996 era bisestile, il 2000 lo era, il 2002 non lo era. Scrivere un programma che chieda all’utente di introdurre un anno e indichi se è bisestile.

Le stringhe

6

47

Le stringhe

In informatica una stringa è una sequenza di caratteri. Un carattere è un segno grafico, ad esempio A, $, *, 6, la maggior parte dei quali si ottiene premendo il relativo tasto sulla tastiera. Ad ogni carattere corrisponde un codice numerico all’interno del calcolatore secondo una corrispondenza stabilita dal cosiddetto Codice ASCII, la cui struttura è la seguente: Sezione 255 128 127 123 122 97 96 91 90 65 64 58 57 48 47 33 32 31 0

Caratteri ASCII estesi Altri caratteri a-z (lettere minuscole)

Altri caratteri A-Z (lettere maiuscole)

Altri caratteri 0-9 (cifre)

Altri caratteri Carattere SPAZIO Altri caratteri

Ad esempio alla lettera A (maiuscola) corrisponde il valore 65, alla B il 66, alla a (minuscola) il 97, alla b il 98, allo 0 (zero) il 48 (anche le cifre sono caratteri), alla virgola il 44, e così via. Un carattere occupa un intero byte. Il Codice ASCII standard ha 128 corrispondenze tra caratteri e valori e quindi per rappresentarle tutte sono sufficienti 7 bit (27=128). Poiché però c’è ancora un bit sfruttabile, tutti i sistemi operativi estendono a modo loro il codice

Capitolo 6

48

ASCII con altre 128 corrispondenze tra caratteri e valori (128+128=256 corrispondenze totali, tutte quelle possibili con 8 bit, che sono appunto 28=256) e questa parte viene chiamata Codice ASCII Esteso. Il significato di quella dicitura “a modo loro” scritta poco innanzi è questo: i codici ASCII di un sistema operativo Windows, Unix, Linux, VMS ecc. saranno tutti uguali per la prima metà (appunto i primi 128 caratteri) e diversi per la seconda metà (i codici estesi, utilizzati per rappresentare simboli diversi, come le lettere accentate). In questo libro utilizzeremo solo il codice ASCII standard. Questo è costituito da sezioni diverse (vedasi la figura precedente): ci sono tutti i caratteri alfabetici maiuscoli in ordine alfabetico, ci sono tutti i caratteri alfabetici minuscoli in ordine alfabetico, ci sono tutte le cifre in ordine numerico, ci sono poi altri caratteri (quali i segni di interpunzione, le parentesi ecc.) che costituiscono sezioni più piccole. È importante puntualizzare che la sezione delle lettere maiuscole è compatta, ossia non ci sono altri tipi di caratteri tra la A e la Z; lo stesso dicasi per le minuscole e per le cifre. Si noti che anche lo spazio è un carattere come gli altri, solo che non si vede. L’elenco dei codici ASCII standard ed esteso per sistemi Windows si trova nella guida in linea del Visual Basic (cercare Character Set o set di caratteri). Normalmente non serve conoscere la corrispondenza dei caratteri con i valori del codice ASCII se non in programmi che proprio si basano su di esso, ma è comunque importante ricordarsi che prima viene lo spazio (ha il codice ASCII con il valore più basso), poi ci sono le cifre, poi le lettere maiuscole e poi le minuscole.

6.1

Variabili stringa

Sono variabili adatte a contenere stringhe, la lunghezza massima della stringa è di 231 caratteri (circa 2 miliardi). Vengono dichiarate per mezzo dell’istruzione Dim come segue: Dim variabile As String Nei vecchi programmi, dove non si usava il dimensionamento, si trovano nomi di variabili terminate da un carattere dollaro, come: nome$ I valori delle variabili stringa si assegnano come si fa per le variabili numeriche: nome = "Caio Giulio Cesare" Una sequenza di caratteri tra virgolette è detta stringa costante, o costante di tipo stringa e come tale non può essere modificata dal codice di programmazione, mentre nome è una variabile e qindi può essere modificata.

Le stringhe

49

Una stringa può anche essere letta dalla tastiera per mezzo di un’istruzione InputBox: nome = InputBox("Come ti chiami") I caratteri che l’utente introduce dalla tastiera vengono messi nella variabile nome. Una variabile del deprecato tipo Variant può contenere anche una stringa.

6.2

Operazioni sulle stringhe

L’unico operatore applicabile alle stringhe è l’operatore di concatenazione, ha simbolo & e produce una variabile temporanea, “senza nome”, di tipo stringa costituita da tutti i caratteri della prima stringa seguiti da tutti i caratteri della seconda. Consideriamo il programmino seguente: A = "Ciao" B = "mondo" C = A & B MsgBox C Questo programma stamperà a video “Ciaomondo”. Perché non separa le due parole con uno spazio? Perché la concatenazione affianca soltanto, se vogliamo uno spazio dobbiamo includerlo esplicitamente, ad esempio mettendolo dopo la “o” di “Ciao” o prima della “m” di “mondo” oppure così: C = A & " " & B Si noti che tra le virgolette c’è uno spazio bianco. In realtà, per compatibilità con vecchie versioni di Basic, anche il simbolo + serve per concatenare due stringhe (oltre che per sommare due numeri). Anche se il simbolo è lo stesso, questa non è una somma, ma una concatenazione e quindi scrivere C=A+B (che equivale a C=A&B) o C=B+A (che equivale a C=B&A) non è indifferente, la seconda infatti produce “mondoCiao”. L’utilizzo dell’operatore + può portare problemi ad esempio quando non vengono dichiarate le variabili (come si è visto quando abbiamo sostituito il – con un + nell’esempio del Sottrattore al paragrafo 3.1): queste infatti sono automaticamente (di default) dichiarate di tipo Variant, ossia il tipo che può funzionare come un qualsiasi altro tipo, compreso il tipo String. Il + tra variabili Variant, anche se contengono numeri, viene visto come una concatenazione di stringhe. La concatenazione con & trasforma (se serve) i suoi operandi in stringhe, così è possibile concatenare una stringa e un numero e ottenere una stringa costituita dai caratteri della stringa di partenza e da quelli del numero (trasformato in stringa), si riveda l’esempio del paragrafo 4.1. Si faccia attenzione che il carattere & deve essere sempre preceduto e seguito da uno spazio.

Capitolo 6

50

6.3

Funzioni sulle stringhe

Oltre all’operatore di concatenazione, il Visual Basic mette a disposizione un certo numero di funzioni per trattare le stringhe: alcune producono valori numerici, altre producono a loro volta stringhe. Di seguito vengono descritte le funzioni più importanti per trattare le stringhe. 6.3.1 Len La funzione Len produce un numero intero che indica di quanti caratteri è costituita la stringa indicata come parametro: A = "Nuvola bianca" X = Len(A) Ad X (che deve essere una variabile numerica) viene assegnato il valore 13 (la stringa A è composta di 13 caratteri, spazio incluso). 6.3.2 Left La funzione Left produce una [variabile temporanea di tipo] stringa (detta sottostringa) costituita dai primi n caratteri della stringa data, la si usa in questo modo: A = "Nuvola bianca" C = Left(A,10) In C vengono copiati i 10 caratteri più a sinistra (left) di A, nello stesso ordine in cui sono in A, ossia C contiene la stringa “Nuvola bia” (anche gli spazi sono caratteri!).

Più in generale la sintassi è: Left(Stringa da cui prelevare i caratteri, quanti caratteri prelevare) 6.3.3 Right La funzione Right produce una [variabile temporanea di tipo] stringa costituita dagli ultimi n caratteri della stringa data. La sintassi è: Right(Stringa da cui prelevare i caratteri, quanti caratteri prelevare) Nel seguente esempio A = "Nuvola bianca" C = Right(A,9) in C vengono copiati gli ultimi 9 caratteri (i più a destra – right) di A, nello stesso ordine in cui sono in A, ossia C contiene la stringa “la bianca”. Attenzione che Right non rovescia la stringa!

Le stringhe

51

6.3.4 Mid La funzione Mid produce una [variabile temporanea di tipo] stringa costituita da n caratteri provenienti da un’altra stringa. Come indica il nome, preleva i caratteri dalla parte centrale (“middle”) della stringa data. La sintassi è la seguente: Mid(Stringa, posizione, quanti caratteri) A partire dalla posizione indicata (1 per il primo carattere, 2 per il secondo ecc.) della Stringa data, vengono copiati il numero di caratteri indicato. Esempio: A = "Nuvola bianca" C = Mid(A,4,7) Qui la Mid estrae 7 caratteri a partire dalla posizione 4 della stringa A, quindi C contiene “ola bia” (con lo spazio, lo spazio è un carattere come gli altri!) I caratteri vengono, come sempre, copiati: nel senso che A non viene modificata affatto. Se il numero di caratteri da prelevare è maggiore di quelli disponibili, vengono prelevati solo quelli disponibili.

La sola istruzione Mid (quindi quanto si sta per dire non riguarda né Left né Right) può essere utilizzata “a rovescio”, cioè per cambiare una parte di una stringa con un’altra. Il codice seguente A = "Pippo" Mid(A,2,3) = "lut" cambia il valore di A: sostituisce i 3 caratteri a partire dalla posizione 2 (ossia la sottostringa ipp) con la sottostringa data lut, quindi A conterrà “Pluto”. Poiché Right e Left non possono essere utilizzate in questo modo, si può risolvere il problema mediante la Mid che ne è una generalizzazione. 6.3.5 Instr La funzione Instr serve per cercare una stringa all’interno di un’altra: Instr(partenza, stringa in cui cercare, stringa da cercare) La stringa da cercare viene cercata all’interno della stringa in cui cercare a partire dalla posizione di partenza indicata. Restituisce (cioè dà come risultato) un valore intero che indica la prima posizione in cui la seconda stringa viene trovata nella prima, o 0 se non la trova. Vediamo alcuni esempi: S = "Apelle figlio di Apollo" N = Instr(1, S, "ll") Viene cercata la stringa “ll” nella stringa “Apelle figlio di Apollo” a partire dalla posizione 1 di quest’ultima, ossia dalla “A” di “Apelle”, la Instr restituisce il valore 4 in quanto “ll” si trova a partire dal quarto

52

Capitolo 6

carattere della stringa S. Si noti che la “ll” di “Apollo” non viene considerata in quanto Instr cerca dalla posizione indicata procedendo verso destra solo la prima “ll” (cerca la prima “occorrenza”). Indicando come posizione di partenza i valori 2 o 3 o 4 invece di 1, la Instr dà comunque il valore 4 perché il valore restituito è sempre relativo al primo carattere della stringa data, semplicemente la ricerca avviene a partire dalla posizione indicata e non dal primo carattere. Ma se la posizione di partenza è 5, la ricerca avviene dalla seconda “l” di “Apelle” e quindi la prima occorrenza di “ll” da quella posizione è quella di “Apollo” e il risultato è 21. Allora per posizioni di partenza comprese tra 5 e 21 il risultato della Instr è sempre 21. Per posizioni maggiori di 21 la Instr non troverà altra occorrenza di “ll” e darà come risultato 0. Anche nell’esempio seguente la Instr non troverà alcuna occorrenza di “ll” e darà come risultato 0. N = Instr(1, S, "palla") Come si fa per trovare la seconda presenza di una sottostringa in una stringa? Non automaticamente, ma usando due volte Instr: A = "Apelle figlio di Apollo" B = "ll" posiz = Instr(Instr(1,A,B)+1, A, B) La seconda Instr trova la “ll” di “Apelle”, il +1 sposta il punto di partenza alla seconda “l” di “Apelle” e la prima Instr trova la seconda “ll”, quella di “Apollo”. Se non trovasse la seconda occorrenza darebbe 0. 6.3.6 Altre funzioni sulle stringhe Ecco altre funzioni relative alle stringhe che possono essere utili: Chr(codice) restituisce una stringa contenente il carattere il cui codice ASCII (numero) è indicato tra parentesi, ad es. Chr(65) darà la A maiuscola. Chr(34) può essere usato per concatenare il carattere " in una stringa. Asc(stringa) restituisce il codice ASCII del primo carattere della stringa indicata come argomento, ad esempio Asc("Aquila") darà il valore 65. Str(numero) restituisce una stringa contenente il numero indicato tra parentesi, ad esempio il numero 123 viene convertito nella stringa " 123" con Str(123) (notare che c’è uno spazio davanti al numero, sarebbe un segno – se il numero fosse negativo). Val(stringa) restituisce il numero (del tipo appropriato) che è indicato nella stringa, ad esempio Val("123") produce il numero 123. Gli spazi e i TAB che eventualmente precedono la prima delle cifre vengono ignorati (Val(" 123") produce comunque il numero 123), ma la presenza

Le stringhe

53

di altri caratteri nella stringa da convertire ferma la conversione in quel punto, ad esempio Val("123ABC234") produce il numero 123 ignorando “ABC234”. Invece Val("ABC234") produce il numero 0. Questa caratteristica è utile ad esempio con le InputBox. Si consideri il seguente codice: Dim A As Integer A = InputBox("valore") MsgBox A Il programma si aspetta di ricevere dall’utente un numero (di tipo Integer in questo caso), ma se l’utente invece di digitare un numero digita altro (es. “ABC” oppure “123ABC”) o preme semplicemente il bottone OK o il tasto Invio, la InputBox produce nei primi due casi una stringa non composta di sole cifre, negli ultimi due casi una stringa vuota, ossia una stringa che non contiene alcun carattere. La stringa vuota non può essere assegnata direttamente ad una variabile numerica, quindi viene prodotto un errore al run-time (ossia mentre il programma sta girando) indicante tipo non corrispondente (cioè il tipo del valore restituito dalla InputBox non è corrispondente al tipo della variabile a sinistra del segno di uguale). Utilizzando la funzione Val come nell’esempio seguente si ottiene il valore 0 anche per la stringa vuota. Dim A As Integer A = Val(InputBox("valore")) MsgBox A La funzione Val è necessaria quando si vogliono sommare due Variant contenenti valori numerici, questo è il modo di risolvere il problema del Sottrattore modificato in Sommatore di cui al paragrafo 3.1 UCase(stringa) produce un Variant (da usare come una stringa) contenente la stringa data convertita tutta in maiuscolo (i caratteri che non sono lettere minuscole sono lasciati invariati). Ad esempio la stringa “Ciao 123! Come stai?” diventa “CIAO 123! COME STAI?” LCase(stringa) produce un Variant (da usare come una stringa) contenente la stringa data convertita tutta in minuscolo (i caratteri che non sono lettere maiuscole sono lasciati invariati). Ad esempio la stringa “Ciao 123! Come stai?” diventa “ciao 123! come stai?” Date (senza parentesi) produce un Variant (da usare come una stringa) contenente la data attuale (il formato dipende dalle impostazioni del sistema operativo). Time (senza parentesi) produce un Variant (da usare come una stringa) contenente l’ora attuale (il formato dipende dalle impostazioni del sistema operativo).

Capitolo 6

54

Ecco un esempio di utilizzo delle varie funzioni indicate: Dim A As String, Dim B As String A = "123" B = "456" MsgBox A + B 'concatenazione, meglio usare & MsgBox Val(A) + Val(B) 'somma MsgBox Asc(A) MsgBox Chr(Asc(B)) MsgBox Str(-333) + Str(444)'concat., meglio usare & Il programma precedente produce il seguente output (a destra le considerazioni per ciascuna riga di output): 123456  è una concatenazione di stringhe 579  somma i valori delle stringhe 49  è il codice ASCII del carattere “1” 4  è una stringa composta di un solo carattere, quello che ha codice ASCII pari al numero 52 che è il codice ASCII del primo carattere della stringa B (ossia il 4) –333 444  è la concatenazione delle due stringhe che derivano dai numeri –333 e 444; notare lo spazio prima di 444, se fosse stato negativo ci sarebbe stato anche qui un segno meno.

6.4

Confronti tra stringhe

Si possono confrontare due stringhe tra loro utilizzando istruzioni If (con gli operatori relazionali usati per i valori numerici) o Select Case: Dim nazione As String nazione = InputBox("Nome della nazione") If nazione = "Italia" Then Tutti gli operatori relazionali possono essere utilizzati: uguale, diverso, maggiore, minore, maggiore o uguale, minore o uguale. Resta da definire che cosa significhi che una stringa è, ad esempio, minore di un’altra. Se le consideriamo come parole, è intuitivo affermare che ad esempio cane venga prima di gatto, infatti la c di cane viene alfabeticamente prima della g di gatto. Lo stesso dicasi per cane e cavallo. Anche per il Visual Basic cane viene prima (è minore) di gatto, ma non tanto perché alfabeticamente la c di cane viene prima della g di gatto, quanto perché la c di cane ha codice ASCII inferiore al codice ASCII della g di gatto. I confronti tra stringhe vengono effettuati sulla base dei codici ASCII dei caratteri che le compongono. Così ad esempio la stringa Gatto è minore della

Le stringhe

55

stringa cane in quanto, secondo il codice ASCII, la G maiuscola ha codice inferiore alla c minuscola (si ricordi lo schema dei codici ASCII riportato nelle pagine precedenti). In particolare si ricordi che lo SPAZIO è un carattere come gli altri e ha codice ASCII inferiore a quelli di cifre, lettere maiuscole e lettere minuscole. Quindi la stringa “ abc” è minore della stringa “abc” in quanto la prima inizia con uno spazio e la seconda con una a. Quando il primo carattere di due stringhe è uguale, si passa a verificare il secondo, e se necessario il terzo, ecc. Si considerino le stringhe “21” e “1234”, la prima è maggiore della seconda (cioè viene dopo). Si tratta infatti di due stringhe (sequenze di codici ASCII) e non di due numeri (ad esempio in Complemento a 2), quindi il confronto viene fatto tra stringhe e il 2 viene dopo l’1 nel codice ASCII. Formalizziamo le regole che stabiliscono come confrontare due stringhe:  due stringhe vengono confrontate carattere per carattere da sinistra a destra in base al codice ASCII dei caratteri di volta in volta considerati (il primo dell’una con il primo dell’altra, poi il secondo dell’una con il secondo dell’altra ecc.);  se i caratteri che vengono confrontati sono uguali (maiuscole e minuscole sono diverse in quanto hanno codice ASCII diverso) si passa a considerare gli altri due caratteri sulla destra;  se invece i caratteri che vengono confrontati sono diversi, la relazione tra questi è la relazione tra le stringhe (la n di cane è minore della v di cavallo, quindi la stringa cane è minore della stringa cavallo);  se le due stringhe hanno uguale lunghezza e i caratteri confrontati a due a due sono sempre uguali, le due stringhe sono uguali;  se una delle due stringhe è più lunga dell’altra, si confrontano come indicato sopra tutti i caratteri fino a esaurire la stringa più corta, se fino a questo punto i caratteri sono uguali, la stringa più corta è minore di quella più lunga (cavallo è minore di cavallone e anche di “cavallo ”, si noti lo spazio in fondo). Riassumendo gli esempi: "cane" "cane" "cane" "cavallo" "cavallo" " cavallo" "21"

< > < < < < >

"gatto" "Gatto" "cavallo" "cavallone" "cavallo " "cavallo" "123"

Capitolo 6

56

6.5

Esercizi

1) Scrivere un programma che, date due stringhe in input, stampi la più lunga (la prima se di uguale lunghezza). 2) Scrivere un programma che, date due stringhe in input, stampi la maggiore. 3) Scrivere un programma che, date tre stringhe in input, stampi la maggiore. 4) Scrivere un programma che, date tre stringhe in input, le stampi in ordine decrescente. 5) Scrivere un programma che determini se il primo carattere della stringa è una lettera maiuscola, una lettera minuscola, una cifra o un altro carattere. 6) Scrivere un programma che determini se il primo carattere e l’ultimo carattere di una stringa sono uguali. 7) Scrivere un programma che, data una stringa in input, indichi se nei primi 10 caratteri compare la lettera A. 8) Scrivere un programma che, date due stringhe in input, indichi se sono uguali (che non significa di uguale lunghezza!), in caso contrario deve dire qual è la minore (che non significa la più corta!) 9) Scrivere un programma che, date due stringhe in input, indichi se la seconda compare almeno una volta nella prima. 10) Scrivere un programma che, date due stringhe in input, indichi se la più corta è contenuta solo una volta (cioè non più di una volta) nella più lunga. 11) Scrivere un programma che, data una stringa in input, indichi se la stringa è composta di due parti uguali; se di lunghezza dispari si trascuri il carattere centrale (verificare che funzioni con le stringhe: ciaociao, bonbon, ciaoXciao e bonXbon – quest’ultima potrebbe creare problemi). 12) Scrivere un programma che, data una stringa in input, ne scambi la prima metà con la seconda; se è di lunghezza dispari, si trascuri il carattere centrale (es. “Ciao come va?” diventa “me va?oCiao c”, la “o” centrale – sottolineata per chiarezza – resta al suo posto, le due metà sono “Ciao c” e “me va?” entrambe di 6 caratteri).

Salti incondizionati

7

57

Salti incondizionati

Per salto incondizionato si intende il passare da un certo punto del programma ad un altro. L’istruzione che fa continuare l’esecuzione da un ben determinato punto del programma è l’istruzione GoTo (letteralmente “vai a”). Nella moderna programmazione strutturata l’uso del GoTo è quasi stato bandito in quanto tende a rendere un programma poco leggibile e manutenibile (cioè revisionabile); è stato anche dimostrato che se ne può fare a meno sempre e in effetti il suo utilizzo è quantomai raro con linguaggi non troppo vecchi. Il GoTo, anche se di utilizzo deprecato dai puristi, è comunque conveniente in alcuni casi che saranno presi in considerazione in seguito. Lo si eviti in ogni altro caso. La sintassi è la seguente: GoTo label dove label (che significa etichetta o cartellino) è una sequenza di caratteri e viene collocata nella riga dove si vuole che il GoTo “salti”: label: La label viene sempre scritta il più possibile a sinistra (ossia mai preceduta da spazi) ed è seguita da un carattere due punti (nel GoTo invece la label non ha il due punti). La si può considerare appunto come un cartellino contenente una scritta (ad es. continua) per identificare una certa riga, quindi l’istruzione GoTo continua è da interpretarsi come “vai alla riga con il cartellino che ha la scritta continua” ed è sottinteso che l’esecuzione continui con le istruzioni successive alla label. Consideriamo l’esempio seguente: var = InputBox("Introduci valore") If var = 0 Then GoTo finito End If altre righe... finito: MsgBox "Programma terminato"

58

Capitolo 7

L’esecuzione avviene in questo modo: 1. viene eseguita l’istruzione InputBox e prelevato un valore (var); 2. se var è uguale a 0, allora viene eseguita l’istruzione GoTo finito che rimanda alla riga contenente la label finito (e quindi salta tutte le righe intermedie); 3. vengono eseguite le righe a partire da quella contenente la label (ossia la MsgBox). La label può essere collocata o dopo il GoTo (come nell’esempio precedente, dove fa un salto in avanti) o prima (quindi fa un salto indietro); purché sempre all’interno dello stesso sottoprogramma (vedi capitolo 11) che contiene quel GoTo. Si possono usare tante label quante se ne vuole, purché tutte diverse, e si possono avere più istruzioni GoTo che saltano alla stessa label.

Esecuzione ciclica

8

59

Esecuzione ciclica

Si supponga di voler stampare a video tutti i numeri pari compresi tra 0 e 1000. La soluzione che per ora conosciamo, ossia scrivere 501 istruzioni MsgBox, non è né compatta (501 righe di codice), né facilmente leggibile (bisogna verificare che siano stati scritti tutti, nell’ordine giusto e senza errori), né agevolmente scrivibile (bisogna scrivere 501 istruzioni MsgBox). Vorremmo avere il modo di dire al calcolatore “esegui 501 volte MsgBox I partendo con I = 0 e ogni volta incrementando I di 2, termina quando arrivi a 1000”. In quasi tutti i programmi, salvo i più banali, vi è la necessità di far eseguire al calcolatore un certo blocco di istruzioni più volte. Questo rende il programma più compatto, più leggibile e più facilmente scrivibile. Si potrebbe pensare di usare un GoTo per tornare indietro nel codice, prima della MsgBox: I = 0 sopra: MsgBox I I = I + 2 If I B And A>C Then If B>C Then MsgBox A & " " & Else MsgBox A & " " & End If ElseIf B>C Then If A>C Then MsgBox B & " " & Else MsgBox B & " " & End If Else If A>B Then MsgBox C & " " & Else MsgBox C & " " & End If End If

139

A") B") C")

B & " " & C C & " " & B

A & " " & C C & " " & A

A & " " & B B & " " & A

Esercizio 4 Dim num As Integer num = InputBox("Introdurre numero") 'oppure If num/2 = num\2 Then If num Mod 2 = 0 Then MsgBox num & " è pari" Else MsgBox num & " è dispari" End If Nota: un numero intero è pari se il resto della divisione per 2 è 0, altrimenti è dispari.

Capitolo 18

140 Esercizio 5 Dim voto As Integer voto = InputBox("Introdurre voto:") Select Case voto Case Is < 18 MsgBox "insufficiente" Case 18 MsgBox "appena sufficiente" Case 19,20 'oppure: Case Is 30 tassa = 1+0.75+1+1.25+1.5 + (reddito-30) * 0.35 End Select MsgBox tassa,, "Tassa da pagare"

Soluzione degli esercizi

143

Esercizio 11 Dim anno As Integer anno = InputBox("Anno?", "Anno") If anno Mod 400 = 0 Or _ (anno Mod 4 = 0 And Not(anno Mod 100 = 0)) Then MsgBox anno & " è bisestile" Else MsgBox anno & " non è bisestile" End If Nota: la condizione della If si legge “If anno è divisibile per 400 Or (è divisibile per 4 And Not è divisibile per 100) Then ...; le parentesi indicate sono sovrabbondanti per le priorità degli operatori booleani.

Altra soluzione Dim anno As Integer Dim d4 As Boolean 'divisibilità per 4 'divisibilità per 100 Dim d100 As Boolean Dim d400 As Boolean 'divisibilità per 400 anno = InputBox("Anno?", "Anno") d4 = anno Mod 4 = 0 'True se anno è divisib per 4 d100 = anno Mod 100 = 0 'True se anno è divisib per 100 d400 = anno Mod 400 = 0 'True se anno è divisib per 400 If d400 Or (d4 And Not d100) Then MsgBox anno & " è bisestile" Else MsgBox anno & " non è bisestile" End If Nota: l’uso di variabili di tipo Boolean rende più semplice la scrittura della condizione; le parentesi indicate sono sovrabbondanti per le priorità degli operatori booleani.

18.5 Capitolo 6 Esercizio 1 Dim s1 As String, s2 As String s1 = InputBox("Stringa 1") s2 = InputBox("Stringa 2") If Len(s1) >= Len(s2) Then MsgBox s1 Else MsgBox s2 End If

144 Esercizio 2 Dim s1 As String Dim s2 As String s1 = InputBox("Stringa 1") s2 = InputBox("Stringa 2") If s1 >= s2 Then MsgBox s1 Else MsgBox s2 End If Esercizio 3 Dim s1 As String Dim s2 As String Dim s3 As String s1 = InputBox("Stringa 1") s2 = InputBox("Stringa 2") s3 = InputBox("Stringa 3") If s1 >= s2 And s1 >= s3 Then MsgBox s1 ElseIf s2 >= s3 Then MsgBox s2 Else MsgBox s3 End If Esercizio 4 Dim a As String Dim b As String Dim c As String a = InputBox("Stringa 1") b = InputBox("Stringa 2") c = InputBox("Stringa 3") If a>b And a>c Then If b>c Then MsgBox a & " " & b & " " & c Else MsgBox a & " " & c & " " & b End If

Capitolo 18

Soluzione degli esercizi ElseIf b>c Then If a>c Then MsgBox b & " Else MsgBox b & " End If Else If a>b Then MsgBox c & " Else MsgBox c & " End If End If

145

" & a & " " & c " & c & " " & a

" & a & " " & b " & b & " " & a

Esercizio 5 Dim stringa As String, c As String stringa = InputBox("Stringa") c = Left(stringa, 1) If c >= "0" And c = "A" And c = "a" And c 0 And pos s2 Then MsgBox "La prima è la maggiore" Else MsgBox "La seconda è la maggiore" End If Esercizio 9 Dim s1 As String Dim s2 As String s1 = InputBox("Stringa 1") s2 = InputBox("Stringa 2") If Instr(1,s1,s2) > 0 Then MsgBox "Compare almeno una volta" Else MsgBox "Non compare nemmeno una volta" End If Esercizio 10 Dim s1 As String Dim s2 As String Dim stemp As String Dim x As Integer Dim y As Integer s1 = InputBox("Stringa 1") s2 = InputBox("Stringa 2") If Len(s1) < Len(s2) Then 'scambia s1 con s2, per avere sempre in s1 la più lunga stemp = s2 s2 = s1 s1 = Stemp End If x=Instr(1,s1,s2) y=Instr(X+1,s1,s2) If x0 And y=0 Then

147

148

Capitolo 18

MsgBox "Compare una volta sola" Else MsgBox "Non compare o compare più volte" End If Esercizio 11 Dim stringa As String Dim L As Integer stringa = InputBox("Stringa") L = Len(stringa) If Left(stringa,L\2) = Right(stringa,L\2) Then MsgBox "Sono uguali" End If Nota: Serve la divisione intera \ in quanto quella normale / produce un risultato frazionario. Le funzioni Right e Left necessitano di un valore intero per il parametro lunghezza, quando ricevono un valore frazionario lo convertono in intero automaticamente, come se fosse un’assegnazione. Ma questo significa che se il valore è x.5 l’approssimazione dipende dal valore di x, come detto nel capitolo delle funzioni di conversione di tipo (paragrafo 3.1.3). Utilizzare la divisione intera \ invece tronca il risultato portando sempre al valore corretto. Ad esempio, se la stringa è di 7 caratteri (come “bonXbon”), 7/2 dà 3.5 che approssimato dà 4, così le due metà estratte dalle funzioni Right e Left sono rispettivamente “bonX” e “Xbon”). Invece 7\2 dà 3, che è il valore corretto. La stringa “ciaoXciao” invece non crea comunque problemi perché composta di 9 caratteri, 9/2 dà 4.5 che viene approssimato a 4, quindi le due metà estratte dalle funzioni Right e Left sono le due stringhe “ciao” presenti. Esercizio 12 Dim s As String Dim L As Integer s = InputBox("Stringa") L = Len(s) If L Mod 2 = 0 Then s = Right(s,L\2) & Left(s,L\2) Else s = Right(s,L\2) & Mid(s,L\2+1,1) & Left(s,L\2) End If MsgBox s

Soluzione degli esercizi

149

18.6 Capitolo 8 Esercizi sui cicli For-Next Esercizio 1 Dim i As Integer Dim v As Single Dim tot As Single tot = 0 For i = 1 To 10 v = InputBox("Valore") tot = tot + V Next MsgBox "media = " & tot / 10 Nota: tot=0 non servirebbe in quanto il Visual Basic lo fa automaticamente, ma altri linguaggi di programmazione non lo fanno ed è comunque considerata pessima pratica di programmazione, quindi è bene abituarsi ad inizializzare sempre tutte le variabili che vengono utilizzate in modo incrementale come tot. Esercizio 2 Dim i As Integer Dim v As Single Dim tot As Single Dim n As Integer tot = 0 n = InputBox("quanti valori") For i = 1 To n v = InputBox("Valore") tot = tot + v Next MsgBox "somma = " & tot MsgBox "media = " & tot / n

150

Capitolo 18

Esercizio 3 Dim i As Integer Dim v As Single Dim max As Single Dim n As Integer n = InputBox("quanti valori") v = InputBox("Valore") 'chiede il primo valore max = v 'il primo valore è per ora anche il massimo For i = 2 To n 'parte da 2 perché uno è già stato letto v = InputBox("Valore") If v > max Then max = v End If Next MsgBox "Massimo = " & max Nota: se si imposta max a 0, il programma funziona correttamente solo sei valori dati in input sono tutti positivi; infatti se i valori immessi fossero tutti negativi, si avrebbe un valore massimo finale che non è nemmeno stato dato in input. Se invece impostiamo il max al valore del primo numero introdotto (come fatto in questo esercizio) siamo sicuri che il max abbia un valore tra quelli dati effettivamente in input. Invece, la soluzione di impostare il max al valore più piccolo possibile per il tipo di dato usato per la variabile che accetta i dati in input, è sì accettabile, ma richiede che si conosca tale valore minimo, inoltre la modifica del programma per utilizzare un altro tipo di dato richiede la modifica del valore max iniziale, cosa che non è richiesta con il metodo suggerito.

Soluzione degli esercizi

151

Esercizio 4 Dim i As Integer Dim v As Single Dim max As Single, min As Single Dim tot As Single Dim n As Integer n = InputBox("quanti valori") v = InputBox("Valore") 'chiede il primo valore max = v min = v tot = v For i = 2 To n 'parte da 2 perché uno è già stato letto v = InputBox("Valore") tot = tot + v If v > max Then max = v ElseIf v < min Then min = v End If Next MsgBox "Massimo = " & max & vbNewLine & _ "Minimo = " & min & vbNewLine & _ "Media = " & tot/n & vbNewLine & _ "Somma = " & tot Esercizio 5 Dim i As Integer Dim riga As String Dim cont As Integer Dim c As String cont = 0 riga = InputBox("Inserire stringa") For i = 1 To Len(riga) c = Mid(riga, i, 1) 'estrae il carattere i-esimo If c >= "0" And c = 2 Then Risult = "1 1" If n >= 3 Then For i = 3 To n c = a + b Risult = Risult & " " & c a = b b = c Next End If End If MsgBox Risult Esercizio 11 Dim n As Integer Dim nf As Double Dim i As Integer n = InputBox("Numero di cui si vuole calcolare il fattoriale") nf = 1 For i = n To 2 Step -1 nf = nf * i Next MsgBox "Il fattoriale di " & n & " è " & nf

Soluzione degli esercizi Esercizio 12 Dim x As Double Dim ex As Double Dim i As Integer Dim k As Integer Dim kf As Double Dim n As Integer

157

'valore di cui calcolare l'esponenziale 'valore dell'esponenziale calcolato 'contatore delle frazioni 'fattoriale di k 'numero di frazioni

x = InputBox("Numero di cui si vuole calcolare l'esponenziale") n = InputBox("Numero di frazioni") ex = 1 'inizializza la sommatoria con il primo elemento For k = 1 To n 'calcola k! e lo mette in kf kf = 1 For i = k To 2 Step -1 kf = kf * i Next 'calcola e somma la frazione successiva ex = ex + (x ^ k) / kf Next MsgBox "Il valore calcolato di exp(" & x & ") è " & _ ex & vbNewLine & _ "Il valore dato da Exp(" & x & ") è " & _ Exp(x) & vbNewLine & _ "La differenza tra i due è " & _ ex - Exp(x)

Nota: La parte in grassetto per il calcolo del fattoriale di k può essere sostituita dalla semplice istruzione kf = kf * k dopo aver inizializzato kf a 1 prima del For esterno.

158

Capitolo 18

Esercizi sui cicli Do-Loop Esercizio 1 Dim cont As Integer 'serve un contatore Dim v As Integer, somma As Integer cont = 0 somma = 0 v = InputBox("introdurre il 1° voto") Do While v >= 18 And v = 18 And v 0 Then risult = "1 1" c = a + b Do While c x Then MsgBox "troppo alto" ElseIf v < x Then MsgBox "troppo basso" End If Loop Until x = v MsgBox "Trovato!" Nota: è necessario usare Int in quanto il semplice Rnd*100 produce un valore Single compreso tra 0 e 99.99999 e l’assegnazione alla variabile x viene effettuata mediante approssimazione. Quindi potrebbe assegnare anche il valore 100. Inoltre anche lo 0 ha probabilità dimezzata di essere prodotto: i valori maggiori di 0.5 vengono approssimati a 1, la probabilità non sarebbe uniforme. La funzione Int tronca la parte frazionaria e quindi i numeri prodotti sono sempre minori o uguali a 99. Anche Rnd*99 non è corretto in quanto solo i valori tra 98.50001 e 98.99999 produrrebbero il valore 99 che dunque avrebbe una probabilità di uscire dimezzata rispetto agli altri valori

Capitolo 18

162

(con la prima formula invece si ha 99 per tutti i valori tra 99.00000 e 99.99999). Esercizio 6 Dim a As Double Dim x As Double Dim x1 As Double Dim risult As String a = InputBox("Numero di cui calcolare la radice") If a = 0 Then risult = "0" ElseIf a < 0 Then risult = "immaginaria" Else x1 = a Do x = x1 'memorizza l'approssim. precedente x1 = 0.5 * (x + a / x) 'calcola la successiva appross. Loop While x x1 'fintantoché il valore di x cambia risult = x 'converte x in stringa End If MsgBox "La radice quadrata di " & a & " è " & risult

18.7 Capitolo 9 Esercizio 1 Dim i As Integer Dim n As Integer Dim valori() As Integer n = InputBox("Quanti valori introdurrai?") ReDim valori(1 To n) For i = 1 To n valori(i) = InputBox("Introdurre valore " & i) Next For i = n To 1 Step -1 MsgBox "valore numero " & i & ": " & valori(i) Next

Soluzione degli esercizi

163

Esercizio 2 Dim i As Integer Dim n As Integer Dim valori() As Integer Dim risult As String risult = "" n = InputBox("Quanti valori introdurrai?") ReDim valori(1 To n) For i = 1 To n valori(i) = InputBox("Introdurre il " & i & "° valore") Next For i = 1 To n If valori(i) Mod 2 = 0 Then risult = risult & " " & valori(i) End If Next For i = n To 1 Step -1 If valori(i) Mod 2 = 1 Then risult = risult & " " & valori(i) End If Next MsgBox risult Nota: le due righe in grassetto possono essere eliminate, collassando i primi due cicli For in uno solo e quindi velocizzando il programma.

Altra soluzione Dim i As Integer Dim n As Integer Dim valori() As Integer Dim risultP As String Dim risultD As String risultP = "" risultD = "" n = InputBox("Quanti valori introdurrai?") ReDim valori(1 To n)

164

Capitolo 18

For i = 1 To n valori(i) = InputBox("introdurre il " & i & "° valore") If valori(i) Mod 2 = 0 Then risultP = risultP & valori(i) & " " Else risultD = valori(i) & " " & risultD End If Next MsgBox risultP & risultD Esercizio 3 Dim i As Integer Dim n As Integer Dim stringhe() As String Dim risult As String risult = "" n = InputBox("Quante stringhe introdurrai?") ReDim stringhe(1 To n) For i = 1 To n stringhe(i) = InputBox("introdurre la " & i & "a stringa") Next For i = 1 To n If i Mod 2 = 0 Then risult = risult & vbNewLine & stringhe(i) End If Next For i = 1 To n If i Mod 2 = 1 Then risult = risult & vbNewLine & stringhe(i) End If Next MsgBox risult Nota: stesse considerazioni dell’esercizio precedente, stessa variante

Soluzione degli esercizi

165

Esercizio 4 Dim i As Integer Dim n As Integer Dim a() As Single Dim b() As Single Dim c() As Single Dim risult As String risult = "" n = InputBox("Quanti valori introdurrai?") ReDim a(1 To n) ReDim b(1 To n) ReDim c(1 To n) For i = 1 To n a(i) = InputBox("Introd. Next For i = 1 To n b(i) = InputBox("Introd. Next For i = 1 To n c(i) = a(i) + b(i) Next For i = 1 To n If i Mod 2 = 0 Then risult = risult & " " End If Next For i = 1 To n If i Mod 2 = 1 Then risult = risult & " " End If Next MsgBox risult

il " & i & "° valore di a")

il " & i & "° valore di b")

& c(i)

& c(i)

Capitolo 18

166

Altra soluzione (con le ottimizzazioni viste negli gli esercizi precedenti) Dim i As Integer Dim n As Integer Dim a() As Single Dim b() As Single Dim c() As Single Dim risultP As String Dim risultD As String risultP = "" risultD = "" n = InputBox("Quanti valori introdurrai?") ReDim a(1 To n) ReDim b(1 To n) ReDim c(1 To n) For i = 1 To n a(i) = InputBox("Introd. il " & i & "° valore di a") Next For i = 1 To n b(i) = InputBox("Introd. il " & i & "° valore di b") c(i) = a(i) + b(i) If i Mod 2 = 0 Then risultP = risultP & c(i) & " " Else risultD = risultD & c(i) & " " End If Next MsgBox risultP & risultD Esercizio 5 Dim r As Integer Dim c As Integer Dim NR As Integer Dim NC As Integer Dim numpari As Integer Dim numdispari As Integer Dim MX() As Integer Dim tabella As String

'indice di riga 'indice di colonna 'numero di righe 'numero di colonne 'contatore dei pari 'contatore dei dispari 'la matrice 'per visualizzare la MX

Soluzione degli esercizi

167

Randomize tabella = "" NR = InputBox("Numero righe") NC = InputBox("Numero colonne") ReDim MX(1 To NR, 1 To NC) 'riempie la matrice con valori casuali For r = 1 To NR For c = 1 To NC MX(r, c) = Int(Rnd * 100) Next Next 'scrive i valori in tabella For r = 1 To NR For c = 1 To NC If MX(r, c) < 10 Then 'mette spazi davanti tabella = tabella & " " & MX(r, c) Else tabella = tabella & " " & MX(r, c) End If Next tabella = tabella & vbNewLine Next 'conta i pari e i dispari numpari = 0 numdispari = 0 For r = 1 To NR For c = 1 To NC If MX(r, c) Mod 2 = 0 Then numpari = numpari + 1 Else numdispari = numdispari + 1 End If Next Next MsgBox tabella & _ "Numeri pari: " & numpari & vbNewLine & _ "Numeri dispari: " & numdispari Nota: anche qui si possono collassare i tre doppi cicli in uno solo (doppio).

168

Capitolo 18

Esercizio 6 Dim r As Integer, c As Integer Dim NR As Integer, NC As Integer Dim numpari As Integer Dim MX() As Integer Randomize NR = InputBox("Numero righe") NC = InputBox("Numero colonne") ReDim MX(1 To NR, 1 To NC) For r = 1 To NR For c = 1 To NC MX(r, c) = Int(Rnd * 100) Next Next numpari = 0 For r = 1 To NR For c = 1 To NC If MX(r, c) Mod 2 = 0 Then numpari = numpari + 1 If numpari >= NR * NC / 4 Then GoTo fuori End If End If Next Next fuori: If numpari >= NR * NC / 4 Then MsgBox "Almeno un quarto dei numeri è pari" Else MsgBox "Meno di unquarto dei numeri è pari" End If Nota: il solo = al posto del >= non è corretto in quanto numpari assume solo valori interi, mentre NR*NC/4 può produrre valori frazionari; ad es. 9 e 9 producono 40.5, se la condizione fosse di sola uguaglianza a 40.5, questa non potrebbe mai essere verificata in quanto numpari passerebbe da 40 a 41, portando ad un ciclo infinito. Alla label fuori si arriva in ogni caso, quindi la condizione dopo la label riconosce se l’esecuzione è giunta in quella riga per effetto del GoTo (almeno la metà dei numeri è pari) o per la terminazione completa dei due cicli For (meno della metà dei numeri è pari).

Soluzione degli esercizi

169

Esercizio 7 Dim n As Integer Dim i As Integer Dim valori() As Single Do n = InputBox("Quanti valori introdurrai?") Loop Until n >= 3 ReDim valori(1 To n) For i = 1 To n Valori(i) = InputBox("valore") Next For i = 1 To n - 2 MsgBox (valori(i) + valori(i + 1) + valori(i + 2)) / 3 Next Esercizio 8 Dim n As Integer 'numero elementi da introdurre Dim x As Integer 'media mobile a x valori Dim i As Integer Dim j As Integer Dim valori() As Single Dim somma As Single x = InputBox("Media mobile a quanti valori?") Do n = InputBox("Quanti valori introdurrai?") Loop Until n >= x ReDim valori(1 To n) For i = 1 To n valori(i) = InputBox("introdurre il " & i & "° valore") Next For i = 1 To n - x + 1 'calcola la somma di x valori a partire dalla posizione i somma = 0 For j = i To i + x - 1 somma = somma + valori(j) Next MsgBox somma / x Next

170

Capitolo 18

Esercizio 9 Dim i As Integer Dim j As Integer Dim n As Integer Dim valori() As Integer Dim temp As Integer Dim risult As String n = InputBox("Quanti valori introdurrai") ReDim valori(1 To n) For i = 1 To n valori(i) = InputBox("Introdurre il " & i & "° valore") Next 'ordina i valori in senso crescente For i = 1 To n - 1 For j = i + 1 To n If valori(i) > valori(j) Then 'scambia i valori temp = valori(i) valori(i) = valori(j) valori(j) = temp End If Next Next risult = "" For i = 1 To n risult = risult & valori(i) & " " Next MsgBox risult Nota: il metodo usato è simile ad un selection sort, ma un po’ meno efficiente; il vettore viene analizzato da sinistra a destra confrontando ciascun elemento con tutti i successivi. I due indici i e j variano rispettivamente da 1 a N–1 e da i+1 a N: l’indice i arriva solo fino a N–1 perché j assume come primo valore il successivo di i (ossia i+1) e se i valesse N non esiterebbe il successivo di i. Confrontando i valori a coppie, quando si scopre che i due elementi sono in ordine errato (quello a sinistra maggiore di quello a destra), questi vengono scambiati tra loro.

Soluzione degli esercizi

171

Esercizio 10 Dim risult As String Dim RA As Integer 'numero di righe della 1a matrice (A) Dim CA As Integer 'numero di colonne della 1a matrice (A) Dim RB As Integer 'numero di righe della 2a matrice (B) Dim CB As Integer 'numero di colonne della 2a matrice (B) Dim A() As Double 'prima matrice Dim B() As Double 'seconda matrice Dim C() As Double 'matrice risultato Dim rx As Integer Dim cx As Integer Dim i As Integer RA = InputBox("Numero di righe della 1a matrice (A)") CA = InputBox("Numero di colonne della 1a matrice") RB = CA 'necessario per poter fare il prodotto MsgBox "Il numero di righe della 2a matrice (B) " & _ "è necessariamente " & RB CB = InputBox("Numero di colonne della 2a matrice (B)") ReDim A(RA, CA) ReDim B(RB, CB) ReDim C(RA, CB) 'riempie la matrice A For rx = 1 To RA For cx = 1 To CA A(rx, cx) = InputBox("Introdurre il valore per " & _ "A(" & rx & "," & cx & ")") Next Next 'riempie la matrice B For rx = 1 To RB For cx = 1 To CB B(rx, cx) = InputBox("Introdurre il valore per " & _ "B(" & rx & "," & cx & ")") Next Next 'C() viene inizializzata a 0 automaticamente

172

Capitolo 18

'calcola il prodotto di A*B e lo mette in C For rx = 1 To RA For cx = 1 To CB For i = 1 To CA C(rx, cx) = C(rx, cx) + A(rx, i) * B(i, cx) Next Next Next 'visualizza la matrice C For rx = 1 To RA For cx = 1 To CB risult = risult & C(rx, cx) & " " Next risult = risult & vbNewLine Next MsgBox risult

Soluzione degli esercizi

18.8 Capitolo 10 Esercizio 1 Dim cont As Integer Dim v As Integer Dim somma As Integer Dim max As Integer Dim min As Integer Dim file As String file = InputBox("Nome del file da aprire?") Open file For Input As #1 If EOF(1) Then 'controlla se esiste almeno 1 riga MsgBox "il file è vuoto" Close #1 Exit Sub 'interrompe l’esecuzione della Sub End If Input #1, v max = v min = v somma = v cont = 1 Do While Not EOF(1) Input #1, v cont = cont + 1 somma = somma + v If v > max Then max = v 'ElseIf v < min Then Else min = v End If Loop Close #1 MsgBox "Numero valori = " & cont & vbNewLine & _ "Massimo = " & max & vbNewLine & _ "Minimo = " & min & vbNewLine & _ "Media = " & somma/cont & vbNewLine & _ "Somma = " & somma

173

174

Capitolo 18

Esercizio 2 Dim cont As Integer Dim riga As String Dim max As String Dim min As String Dim file As String file = InputBox("Nome del file da aprire?") Open file For Input As #1 If EOF(1) Then MsgBox "il file è vuoto" Close #1 Exit Sub End If Line Input #1, riga max = riga min = riga cont = 1 Do While Not EOF(1) Line Input #1, riga cont = cont + 1 If riga > max Then max = riga 'ElseIf riga < min Then Else min = riga End If Loop Close #1 MsgBox "Numero righe = " & cont & vbNewLine & _ "riga minore = " & min & vbNewLine & _ "riga maggiore = " & max Nota: maggiore secondo il codice ASCII, non più lunga; idem per minore.

Soluzione degli esercizi

175

Esercizio 3 Dim file As String Dim riga As String Dim cont As Integer Dim i As Integer Dim stringhe() As String Dim risult As String file = InputBox("Nome del file da aprire?") Open file For Input As #1 cont = 0 risult = "" Do While Not EOF(1) 'conta le righe del file Line Input #1, riga cont = cont + 1 Loop Close #1 ReDim stringhe(1 To cont) Open file For Input As #1 For i = 1 To cont 'si sa quante sono le righe Line Input #1, stringhe(i) Next Close #1 For i = cont To 1 Step -1 risult = risult & stringhe(i) & vbNewLine Next MsgBox risult Nota: il primo ciclo è di tipo Do-Loop in quanto non si sa quante siano le righe del file, le righe vengono lette e scartate: lo scopo di questo ciclo è solo quello di contare quante righe ci sono per poter dimensionare il vettore dinamico stringhe di dimensione opportuna (cont). Il secondo ciclo è di tipo For-Next in quanto ora il numero di letture da fare è noto (cont), si sarebbe potuto comunque utilizzare un altro ciclo Do-Loop. Lo scopo di questo secondo ciclo è leggere tutte le righe del file. Il terzo ciclo percorre il vettore a ritroso.

176

Capitolo 18

Esercizio 4 Dim fileIN As String Dim fileOUT As String Dim riga As String Dim cont As Integer Dim i As Integer Dim stringhe() As String fileIN = InputBox("Nome del file in input?") Open fileIN For Input As #1 fileOUT = InputBox("Nome del file in output?") cont = 0 Do While Not EOF(1) Line Input #1, riga cont = cont + 1 Loop Close #1 ReDim stringhe(1 To cont) Open fileIN For Input As #1 For i = 1 To cont Line Input #1, stringhe(i) Next Close #1 Open fileOUT For Output As #2 For i = cont To 1 Step -1 Print #2, stringhe(i) Next Close #2 MsgBox "sono state trascritte " & cont & " righe"

Soluzione degli esercizi Esercizio 5 Dim i As Integer Dim riga As String Dim maius As Integer Dim minus As Integer Dim cifre As Integer Dim altri As Integer Dim file As String maius = 0 minus = 0 cifre = 0 altri = 0 file = InputBox("Nome del file da aprire?") Open file For Input As #1 Do While Not EOF(1) Line Input #1, riga For i = 1 To Len(riga) Select Case Mid(riga, i, 1) Case "0" To "9" cifre = cifre + 1 Case "A" To "Z" maius = maius + 1 Case "a" To "z" minus = minus + 1 Case Else altri = altri + 1 End Select Next Loop Close #1 MsgBox "cifre " & cifre & vbNewLine & _ "maiuscole " & maius & vbNewLine & _ "minuscole " & minus & vbNewLine & _ "altri " & altri

177

178

Capitolo 18

Esercizio 6 Dim fileIN As String Dim fileOUT As String Dim n As Integer Dim riga As String fileIN = InputBox("Nome del file in input?") Open fileIN For Input As #1 fileOUT = InputBox("Nome del file in output?") Open fileOUT For Output As #2 n = InputBox("larghezza massima") Do While Not EOF(1) Line Input #1, riga If Len(riga) n Print #2, Left(riga, n) riga = Right(riga, Len(riga) - n) Loop Print #2, riga End If Loop Close #1 Close #2

Nota: l’istruzione If in grassetto potrebbe essere sostituita dal codice: For I = 1 To Len(riga) Step n Print #2, Mid(riga, I, n) Next

Soluzione degli esercizi

179

Esercizio 7 Dim fileIN As String Dim fileOUT As String Dim n As Integer Dim riga As String Dim spazio As Integer Dim i As Integer fileIN = InputBox("Nome del file in input?") Open fileIN For Input As #1 fileOUT = InputBox("Nome del file in output?") Open fileOUT For Output As #2 n = InputBox("larghezza massima") Do While Not EOF(1) Line Input #1, riga If Len(riga) n 'cerca l'ultimo spazio (se c'è) spazio = 0 'posizione dello spazio, 0 se non c'è For i = n To 1 Step -1 If Mid(riga, i, 1) = " " Then spazio = i Exit For End If Next If spazio = 0 Or Mid(riga, n+1, 1) = " " Then 'non trovato spazio nei primi n caratteri di riga spazio = n End If Print #2, Left(riga, spazio) riga = Right(riga, Len(riga) - spazio) Loop Print #2, riga End If Loop Close #1 Close #2

180

Capitolo 18

Esercizio 8 Dim codice As Integer Dim c As String Dim cc As Integer Dim riga As String 'riga da cifrare Dim fileIN As String Dim fileOUT As String fileIN = InputBox("Nome del file in input?") Open fileIN For Input As #1 fileOUT = InputBox("Nome del file in output?") Open fileOUT For Output As #2 codice = InputBox("Codice") Do While Not EOF(1) Line Input #1, riga For I = 1 To Len(riga) c = Mid(riga, I, 1) cc = Asc(c) 'codice ASCII del caratt da convertire If c >= "A" And c Asc("Z") Then cc = cc - 26 ElseIf cc < Asc("A") Then cc = cc + 26 End If Mid(riga, I, 1) = Chr (cc) ElseIf c >= "a" And c Asc("z") Then cc = cc - 26 ElseIf cc < Asc("a") Then cc = cc + 26 End If Mid(riga, I, 1) = Chr(cc) 'se non è una lettera 'cc non è stato cambiato End If Next Print #2, riga Loop Close

Soluzione degli esercizi

181

Altra soluzione Dim codice As Integer Dim c As String Dim cc As Integer Dim riga As String 'riga da cifrare Dim fileIN As String Dim fileOUT As String fileIN = InputBox("Nome del file in input?") Open fileIN For Input As #1 fileOUT = InputBox("Nome del file in output?") Open fileOUT For Output As #2 codice = InputBox("Codice") codice = (codice + 26) Mod 26 'così codice non è mai negativo Do While Not EOF(1) Line Input #1, riga For I = 1 To Len(riga) c = Mid(riga, I, 1) If c >= "A" And c = "0" And c = "0" And c v(j) Then temp = v(i) v(i) = v(j) v(j) = temp End If Next Next End Sub

194

Capitolo 18

Esercizio 10 Modulo chiamante (CommandButton1_Click) Dim i As Integer, n As Integer Dim direz As String Dim risult As String Dim vett() As Single n = InputBox("dimensione vettore") ReDim vett(1 To n) For i = 1 To n vett(i) = InputBox("Introdurre il " & i & "° valore") Next Do direz = LCase(InputBox("riordinamento ascen/disc (a/d)")) Loop Until direz = "a" Or direz = "d" Call sort(vett(), direz) risult = "" For i = 1 To n risult = risult & vett(i) & " " Next MsgBox risult

Sottoprogramma Sub sort (v() As Single, direz As String) Dim i As Integer, j As Integer Dim L As Integer Dim R As Integer Dim temp As Single L = Lbound(v, 1) R = Ubound(v, 1) For i = L To R - 1 For j = i + 1 To R If v(j) < v(i) Xor direz = "d" Then temp = v(i) v(i) = v(j) v(j) = temp End If Next Next End Sub

Soluzione degli esercizi

195

Nota: la condizione dell’ If indicata per esteso sarebbe: (v(j) < v(i) AND direz = "a") OR (v(j) > v(i) AND direz = "d") Ponendo A=(v(j)v(i) non è proprio il complementare di A, il vero A è v(j)>=v(i), ma il maggiore o uguale ha come effetto quello di far scambiare di posto anche i valori uguali quando si ordina in senso decrescente, la cosa non porta grande inefficienza e in fondo la condizione è decisamente più semplice da scrivere e veloce da calcolare.

18.10 Capitolo 12 Esercizio 1 Module Type Allievo matricola As Long cognome As String nome As String media As Integer End Type

Modulo chiamante (CommandButton1_Click) Dim fileIN As String Dim fileOUT As String Dim numRighe As Integer Dim s As String Dim i As Integer Dim allievi() As Allievo fileIN = InputBox("Nome del file in input?") Open fileIN For Input As #1 fileOUT = InputBox("Nome del file in output") numRighe = 0 Do While Not EOF(1) Line Input #1, s numRighe = numRighe + 1 Loop

196

Capitolo 18

Close 1 ReDim allievi(1 To numRighe) As Allievo Open fileIN For Input As #1 For i = 1 To numRighe Input #1, allievi(i).matricola Input #1, allievi(i).cognome Input #1, allievi(i).nome Input #1, allievi(i).media Next Close 1 Call riordina(allievi()) Open fileOUT For Output As #2 For i = 1 To numRighe Print #2, allievi(i).matricola; ","; Print #2, allievi(i).cognome; ","; Print #2, allievi(i).nome; ","; Print #2, allievi(i).media Next Close 2

Sottoprogramma Sub riordina(a() As Allievo) Dim i As Integer, j As Integer Dim L As Integer 'lunghezza vettore Dim temp As Allievo L = UBound(a, 1) For i = 1 To L - 1 For j = i + 1 To L If a(i).matricola > a(j).matricola Then temp = a(i) a(i) = a(j) a(j) = temp End If Next Next End Sub

Soluzione degli esercizi

18.11 Capitolo 16 Esercizio 1 Dim i As Integer Dim file As String Dim riga As String Dim c As String Dim frase As String frase = "" file = InputBox("File da aprire?") Open file For Input As #1 Do While Not EOF(1) Line Input #1, riga For i = 1 To Len(riga) c = Mid(riga, i, 1) If c >= "A" And c areaMax Then areaMax = area rigaMax = rigaNum ElseIf area < areaMin Then areaMin = area rigaMin = rigaNum End If Loop If rigaNum 0 Then 'se il file è vuoto rigaNum = 0 MsgBox "File: " & file & vbNewLine & _ "Trapezio di area maggiore: riga " & rigaMax & _ " (" & areaMax & ")" & vbNewLine & _ "Trapezio di area minore: riga " & rigaMin & _ " (" & areaMin & ")" Else MsgBox "Il file è vuoto" End If Close #1

202

Capitolo 18

Esercizio 7 Dim i As Integer Dim j As Integer Dim k As Integer Dim n As Integer Dim risult As String risult = "" n = InputBox("Valore massimo dei lati?") For i = 1 To n For j = 1 To n For k = j To n If i * i = j * j + k * k Then risult = risult & vbNewLine & j & " " & k & " " & i End If Next k Next j Next i MsgBox risult Nota: facendo partire k non da 1 ma da j si eliminano le righe con i cateti scambiati tra di loro (ad es. 3 4 5 e 4 3 5), l’ordine di stampa (j, k, i) permette di avere i valori sempre in ordine crescente.

Soluzione degli esercizi Esercizio 8 Dim file As String Dim m As Double Dim x As Double Dim y As Double Dim z As Double Dim sumM As Double Dim sumMx As Double Dim sumMy As Double Dim sumMz As Double

203

'somma 'somma 'somma 'somma

delle masse di m*x di m*y di m*z

sumM = 0 sumMx = 0 sumMy = 0 sumMz = 0 file = InputBox("Nome del file da aprire?") Open file For Input As #1 Do While Not EOF(1) Input #1, m, x, y, z sumM = sumM + m sumMx = sumMx + m * x sumMy = sumMy + m * y sumMz = sumMz + m * z Loop Close MsgBox "Xg = " & sumMx / sumM & vbNewLine & _ "Yg = " & sumMy / sumM & vbNewLine & _ "Zg = " & sumMz / sumM Esercizio 9 Dim fuori As Boolean 'fuori = non in mezzo ad una parola Dim lett() As Integer Dim c As String, file As String, riga As String Dim i As Integer, risult As String ReDim lett(Asc("A") To Asc("Z")) 'Dim vuole costanti file = InputBox("Nome del file da aprire?") Open file For Input As #1

204

Capitolo 18

Do While Not EOF(1) Line Input #1, riga riga = UCase(riga) 'così si considerano solo le maiuscole fuori = True For i = 1 To Len(riga) c = Mid(riga, i, 1) If c >= "A" And c