Programmare Con wxdev-c++

Dimensione: px
Iniziare la visualizzazioe della pagina:

Download "Programmare Con wxdev-c++"

Transcript

1 Programmare Con wxdev-c++ Uso di wxdev-c++ per la Programmazione ed il Debugging Elementi di Programmazione C e C++ Uso delle wxwidgets con wxdev-c++ Risposte a Domande Frequenti Codice Sorgente Disponibile Online By Sof.T (traduzione di Baldassarre Cesarano)

2 Copyright (C) 2006 Sof.T Questo libro e il codice sorgente allegato, è materiale pubblicato gratuitamente; lo si può distribuire e/o modificare nei termini della GNU General Public License come pubblicato dalla Free Software Foundation; o dalla versione 2 della Licenza, o (a propria scelta) da qualsiasi versione successiva. Questo libro e il codice sorgente allegato, è distribuito nella speranza che possa risultare utile, ma SENZA ALCUNA GARANZIA; senza neppure la garanzia implicita della COMMERCIABILITÀ o IDONEITÀ PER UNO SCOPO PARTICOLARE. Per ulteriori dettagli si veda la GNU General Public License. Si dovrebbe aver ricevuto una copia della GNU General Public License assieme a questo libro; altrimenti, si scriva alla Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Version No: Release Date: 17th October 2007 Revisione Traduzione: 4 Dicembre 2008 Newest version available from

3 Contenuto Programmare Con wxdev-c++ It s got some quirks but then again don t we all NinjaNL La parte noiosa... 1 Introduzione...1 Storia di wxdev-c Per chi è questo Libro...4 Ringraziamenti...5 Parte 1 C / C++ La Programmazione con wxdev-c Capitolo 1 Scaricare, Istallare ed Aggiornare wxdev-c Introduzione...2 Il download di wxdev-c Installare wxdev-c Aggiornare wxdev-c Aggiungere Package Extra...20 Capitolo 2 La compilazione del primo programma...27 Introduzione...27 Aprire un progetto esistente...28 Creare un proprio progetto...33 Capitolo 3 Fondamenti di Programmazione C...38 Introduzione...38 Cominciamo con un semplice esempio...38 Elementi di C...42 Cicli (loop) Condizionali...46 Esecuzione Condizionale...48 Il Preprocessore...51 Funzioni...52 Input/Output ed altre utili funzioni...57 Puntatori...66 Allocazione di Memoria...68 Array...69 Stringhe...71 Strutture...75 Sommario...79 Capitolo 4 Fondamenti di Programmazione C Introduzione...81 Cominciamo con un semplice esempio...81 Fondamenti di C Funzioni...83 Allocazione della memoria...85 Classi...85 Input/Output...87 Input...88 Output...88 Strings...88 Namespaces...88 Exceptions...88 Templates...88 Capitolo 5 Cercare la propria strada per l IDE...89

4 Capitolo 6 Il Debugging con wxdev-c Introduzione...90 Compile Time Bugs...90 Link Time Errors...90 Run Time Errors...90 Domande Frequenti (FAQ) relative a DevC Q. Ho sentito parlare di Easter egg (Ovetto con sorpresina) in Dev-C++?...91 Q. Perché il mio programma non viene ricompilato quando uno dei file header viene modificato?...91 Parte 2 Elementi per lo Sviluppo con wxwidgets e wxdev-c Capitolo 7 La creazione di un semplice Editor HTML...94 Introduzione...94 Iniziare un Progetto wxwidgets...94 L uso del Form Designer...95 Modifica delle Proprietà...98 Aggiungere il Codice Capitolo 8 Lavorare con i Frame e le Dialog Introduzione Creazione di un nuovo progetto Un Progetto a Frame Multipli Aggiungere un Nuovo Frame Aggiungere una nuova finestra di dialogo Applicazione di esempio Parte 1 - Lo schema...137

5 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 1 di 150 La parte noiosa Introduzione La prima domanda che qualunque bambino farà è perché ed è una buona domanda (a meno che non sia la trentesima). Il sole splende fuori, è caldissimo, quindi perché sto qui a scrivere questo libro? La ragione principale è perché molte persone hanno chiesto sul wxforum se si intendesse scrivere un libro su wxdev-c++. Finora sono stati prodotti alcuni tutorial e vi sono state varie opinioni sui libri. Questo risponde alla domanda sul perché sto scrivendo questo libro, non sul perché io stia scrivendo questo libro. Per me wxdev-c++ è qualcosa di molto speciale. Tutto risale al luglio del 1999 (atmosfera da flashback e filtri annebbianti alla telecamera). Come al solito comprai una rivista di computer, una da un mucchio, ma questa era speciale. Sulla copertina del disco c era Championship Manager 3, ma da geek non ero interessato a questo. Piuttosto ero preso dal piccolo trafiletto nell angolo che recitava Bagno di sangue DevC++, un ambiente per C e C++ gratuito. Mi si era aperto un tutto mondo nuovo, quello del C e del C++ in quanto fino ad allora avevo programmato solo in Basic e Visual Basic. Ho anche conosciuto il mondo sorprendente del software Open Source. Figura 0.1 Dev-C++ nel 1999 circa Tornai a casa dal lavoro e installai questo programma, era piuttosto elementare e brutto, ma non me ne accorsi. Aprii uno degli esempi, e premuto su compilazione mi accolse un messaggio che mi diceva che questo programma non poteva essere compilato, quindi l'ide (Integrated

6 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 2 di 150 Development Environment) si bloccava. Testardo, ricaricai DevC e un altro esempio e questa volta si compilò. Era solo una semplice finestra con dentro un pulsante, ma per me fu un miracolo. Pensavo che Colin Laplace fosse un santo a fare questo programma e a darlo via gratis. Negli anni seguenti ho continuato a utilizzare DevC++ e l ho visto crescere da brutto ed instabile ad una IDE che ricorda Microsoft Visual Studio e che soddisfa la maggior parte delle mie esigenze di programmazione. Non sono solo, oggi DevC++ resta l applicativo per sviluppare più scaricato da SourceForge. Figura 0.2 DevC++ in una veste più recente Nel frattempo ho usato anche un altro IDE questa volta della Borland chiamato C++ Builder. Mi piaceva la semplicità d'uso nella creazione di GUI in pochi secondi. Potevo vederne l aspetto prima di compilarle e potevo modificare le cose in un attimo anziché modificare delle righe di codice. Fui indeciso tra DevC++ e C++ Builder finché non sono entrato in un progetto denominato SkinDoc su SourceForge nel Era diretto da un programmatore noto come Nuklear Zelph che ne ha iniziato lo sviluppo partendo da qualcosa che ricordava il mio passato e si chiamava wxdev-c++. Fondamentalmente era una finestra di progettazione visuale costruita su DevC++. L ho scaricata ed ho trovato la risposta a tutti i miei desideri di programmazione. Niente da dire, wxdev-c è un grande lavoro, molti programmatori qualificati hanno speso e continuano a trascorre molto tempo nella sua creazione e per migliorarlo. Ma è anche un lavoro in corso, di conseguenza ha ancora qualche sbavatura. È anche simile, e non ancora sufficientemente diverso, ad altri IDE tanto che alcune parti risultano difficili per i principianti. Ho girato fino a trovare dei tutorials disponibili sul sito di wxdev-c++ scoprendo poi il wxforum. wxdev-c++ soffre inoltre di un grande handicap. Il DevC++ originale è stato un paradosso, dato che era una IDE di C/C++ scritta in Delphi Pascal. wxdev-c++ continua questa

7 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 3 di 150 tradizione e per questo, in tali programmi di sviluppo, non sempre la progettazione del form coincidone con la versione compilata. È un esempio di applicazione WYSINAWYG (What You See Is Not Always What You Get Quello che vedi non sempre è quello che ottieni), alcune cose miglioreranno col tempo, ma dubito che ci sarà mai una corrispondenza perfetta. Questo libro quindi è scritto con l'esperienza acquisita e con quella di altri utenti sui forum, nella speranza che possa essere utile. Parte di esso sarà senza dubbio datata visto che wxdev-c++ continua ad evolvere, ma questo libro rifletterà man mano tali modifiche crescendo a fianco dell IDE. Sof.T

8 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 4 di 150 Storia di wxdev-c++ Nel 1983 Richard Stallman ha annunciato il progetto GNU. Questo progetto mirava a fornire un sistema operativo unix free con strumenti comparabili. Il noto compilatore GCC è stato creato da Richard Stallman nell'ambito di questo progetto. Nel 1992 Julian Smart iniziò un progetto denominato wxwindows, che nel 2004 è stato rinominato wxwidgets cedendo alle pressioni di Microsoft. Questo progetto è stato realizzato per produrre una libreria GUI multi-piattaforma e Open Source, che utilizzasse le widget native di ciascuna piattaforma. Nel 1995 Steve Chamberlain iniziò il progetto Cygwin dopo aver notanto che GCC conteneva una gran numero di funzioni che lo rendevano utile da portare su Windows. Altri programmatori hanno aderito al progetto e contribuito ad espandere il pacchetto di Cygwin. Inizialmente, separandosi da Cygwin, è arrivato il progetto MinGW (Minimalist GNU for Windows), fornendo gli strumenti e i file di intestazione per lo sviluppo sua piattaforma Win32. Verso il 1999 Colin Laplace ha rilasciato la prima versione di Dev-C++. Utilizzando il compilatore MinGW, fornendo una IDE minimale. Altri sviluppatori vi hanno aderito, contribuendo ad espandere Dev-C++ in una IDE che ora assomiglia a Microsoft Visual Studio. Nel 2003 Guru Kathiresan ha creato una versione a sé stante di Visual Form Designer in Delphi. Sebbene avesse funzionalità limitate era in grado di creare applicazioni di elementari. Nel 2004 Guru Kathiresan ha incluso il Visual Form Designer in Dev-C++. L applicazione risultante è stata rinominata wxdev-c++ ed è diventata uno strumento RAD simile a Delphi e Visual Basic. Molti altri sviluppatori vi hanno aderito e questo strumento continua a migliorare. Per chi è questo Libro Per far funzionare questo libro lo si deve indirizzare ad un gran numero di utenti. Da quelli che non hanno mai programmato in C++ a quelli più competenti ma che non hanno mai utilizzato le wxwidgets e a quelli che conoscono entrambi, ma cercano maggiori informazioni. Questa vasta gamma di potenziali lettori ha influenzato l aspetto di questo libro, gli esperti non vogliono rileggere le basi della programmazione C/C++ ed i principianti non vogliono greare GUI dato che non ne possono creare il codice che vi sta dietro. Di conseguenza il libro è suddiviso in modo che gli utenti possano saltare direttamente alla sezione cui sono interessati. Sezione uno Affronta l installazione di wxdev-c++, la codifica C e C++, e la parte DevC++ di wxdev-c++. Sezione due Affronta la creazione di GUI utilizzando wxdev-c++. Va dentro le wxwidgets e su come i due lavorino assieme. Sezione tre La sezione finale copre argomenti avanzati, per gli utenti che vogliono andare oltre la creazione con i soli controlli standard. Ogni sezione termina con una selezione delle FAQ (domande frequenti) relative.

9 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 5 di 150 Ringraziamenti Grazie a Peter James per aver volontariamente svolto il ruolo di lettore di prova. Le sue modifiche ed integrazioni sono state molto apprezzate ed hanno contribuito a migliorare notevolmente la qualità di questo libro. Malcolm Nealon ha inoltre aggiunto alcuni miglioramenti preziosi, e la correzione di almeno un grave errore. Grazie anche agli sviluppatori di wxdev-c++, specialmente a Joel Low e Tony Reina per il tempo che mi hanno concesso per rispondere alle mie domande.

10 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 1 di 150 Parte 1 C / C++ La Programmazione con wxdev-c++

11 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 2 di 150 Capitolo 1 Scaricare, Istallare ed Aggiornare wxdev-c++ Introduzione Questo capitolo si rivolge a tutti gli utenti. Ho deliberatamente abbassato il livello delle spiegazioni per gli utenti che raramente, o mai, installano o disinstallano programmi. Gli utenti avanzati si potrebbero irritare per il numero di schermate e le istruzioni eccessivamente minuziose. In questo caso si può semplicemente ignorare questa sezione o, forse, leggerla velocemente solo per le funzioni che vi risultano nuove. Una domanda che molti hanno posto è se wxdev-c++ sia disponibile sulle piattaforme diverse da Windows. La risposta in breve è no. Tuttavia la buona notizia è che qualsiasi codice che si produrrà con wxdev-c++ potrà essere compilato su altre piattaforme. Per ulteriori informazioni vedere la FAQ alla fine della Parte 1 oppure visitate il sito Il download di wxdev-c++ Il progetto wxdev-c++ è ospitato su SourceForge e questo è il posto dove recarsi per scaricare l'ultima versione ufficiale (ci sono altre versioni, ma ce ne occuperemo in seguito). Così per il momento accertatevi solo di essere connessi ad Internet ed aprire il browser Web, per andare sul sito ufficiale di wxdev-c++ immettendo l indirizzo Figura 1.1 Il sito web ufficiale di wxdev-c++ [Accesso dell 1/11/2006 alle 7:55] Sulla barra di navigazione a sinistra vedrete il link ai Download. Attualmente esistono due diversi collegamenti uno a wxdev-c++ e l'altro per wxdev-c++ per VC. La prima versione

12 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 3 di 150 usa solo il compilatore open source Mingw mentre l'altra versione è utilizzabile anche col compilatore della Microsoft. Presto le due versioni verranno unificate. Si clicca sull opzione wxdev-c Figura 1.2 La selezionare di una versione di wxdev-c++ Cliccando sul link intitolato wxdev-c si andrà sulla pagina di download di SourceForge. Tale pagine contiene un elenco di siti specchio dai quali si potrà scaricare il file di setup. Figura 1.3 Pagina di download di SourceForge per wxdev-c++ Si sceglie il sito più vicino. Per me è nel Kent, nel Regno Unito. Sulla destra del nome del sito c è un link blu intitolato Download. Si clicca su tale link per accedere alla pagina di download.

13 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 4 di 150 Questa verrà ricaricata utilizzando tale sito ed immediatamente partirà il download. NOTA: In Internet Explorer di Windows XP Service pack 2, il download potrebbe risultare bloccato. Nel qual caso è necessario cliccare sull intestazione e selezionare Consenti il download da questo sito. La prossima cosa che si dovrebbe vedere è la finestra di dialogo del Download. Questa potrà differire a seconda del browser web, ma tutti dovrebbero dare la possibilità di scaricare il file o per eseguirlo. Se si sceglie l'esecuzione, il file di installazione verrà scaricato e subito dopo eseguito automaticamente. Se si sceglie di salvarlo, questo verrà memorizzato sul computer per una futura esecuzione. O si clicca sul pulsante [Run] o su [Save]. Figura 1.4 La finestra di download di Internet Explorer Figura 1.5 La finestra di download di Firefox

14 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 5 di 150 Nel mio caso ho scelto [Save] dato che preferisco conservarmi i file di setup per poterli installare e deinstallare su diversi computer. Quindi si clicca su [Run] o su [Save] per andare avanti. Figura 1.6 Si sceglie un posto in cui salvare il file di setup. Una volta scelto [Run] o [Save], inizia il download. A seconda della connessione Internet, c è il tempo di una tazza di tè o una stiratina veloce. (Come mostra la finestra seguente nel novembre 2006, il download era di 47.5Mb circa) Figura 1.7 Il download del file di setup Installare wxdev-c++ Una volta scaricato il file, se si è scelto di lanciare l installazione il programma si avvierà automaticamente, altrimenti si dovrà andare dove lo si è salvato e:

15 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 6 di 150 O doppio click sul file per avviarlo. O click col tasto destro e poi Open. Figura 1.8 Avvio del programma di installazione La prossima cosa che si dovrebbe vedere è una finestra che vi avvisi di non per installare il programma su un'installazione precedente. Un'avvertenza importante come molti hanno constatato. L incapacità di osservare queste istruzioni può dare l impressione che tutto sia andato bene, ma comporterà infiniti mal di testa (un po come i vini di poco prezzo). Si veda in seguito la sezione Aggiornare wxdev-c++ in questo capitolo per ulteriori dettagli. Figura 1.9 Il messaggio di attenzione iniziale dal setup di wxdev-c++ La finestra seguente mostra la lingua da utilizzare durante l installazione. Personalmente lascio l inglese dato che ho difficoltà a capire altro. Si seleziona la propria lingua e si clicca su [OK]. Figura 1.10 La finestra di scelta della lingua L opzione seguente segna un cambiamento dalle versioni precedenti di wxdev-c++. Dato che questo rilascio offre il supporto per più tipi di compilatori, propone di scegliere quali compilatori usare. Si seleziona il compilatore che si vuol usare. Poi si clicca su [Next>]

16 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 7 di 150 Figura 1.11 La scelta dei compilatori Sebbene wxdev-c++ sia gratuito, per usarlo è necessario accettarne un contratto di licenza. Quello utilizzato è la versione 2 della GNU GPL (Licenza Generale Pubblica). Lo si può leggere tutto oppure ignorarlo. Si clicca su [I Agree] per continuare. Figura 1.12 La finestra di accettazione della licenza

17 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 8 di 150 La finestra successiva consente di scegliere quali componenti installare. Personalmente lascio le impostazioni predefinite, ma vale la pena di scorrere l'elenco dei componenti per avere un idea di cosa sia incluso nella distribuzione. La combo box superiore intitolata Select the type of install (selezionare il tipo di installazione) consente di scegliere tra un installazione completa, una minima o una personalizzata. Se lo spazio è un problema, si opti per l'installazione minima. Si noterà che le prime due voci sono grigiate, questo perché sono propedeutiche a qualsiasi tipo di installazione. Se si usa un altro IDE (non che si utilizzerebbe) e si sta solo testando wxdev- C++ allora si potrebbe voler deselezionare l'opzione per associare i file con wxdev-c++. Analogamente, se non sono state fatte scelte nella schermata precedente questa è l ultima opportunità di scegliere i compilatori da supportare e per cui caricare le librerie. Fatte le proprie scelte si clicca su [Next >] per continuare. Figura 1.13 La finestra per scegliere i componenti La finestra per scegliere il Menù Start consente di indicare dove debba apparire wxdev-c++ nel menù Start. Questa è una decisione personale, a me piace raggruppare programmi simili quindi cambio tale opzione in Programming\wxDevCpp. Fatta la propria scelta si clicca su [Next >] per continuare.

18 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 9 di 150 Figura 1.14 Finestra per scegliere la posizione nel menù Start Finestra Install Location consente di impostare il percorso di installazione per wxdev-c++. Questo è un valore predefinito che di solito si rispetta. In precedenza l uso di C:\Dev-cpp era dovuto al fatto che DevCpp non riusciva a gestire gli spazi nel path dei file durante la compilazione dei programmi. Ora, grazie all intenso lavoro degli sviluppatori di wxdev-c++ questo non è più necessario. Quindi il path predefinito ora è C:\Program Files\Dev-cpp. Uno dei tanti miglioramenti di questa release. Trattenete il respiro e cliccate su [Install]. Figura 1.15 La finestra di scelta del path di installazione

19 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 10 di 150 Nel mentre la successiva finestra si riempie con i nomi dei file installati si avrà il tempo di fare un altra pausa. Figura 1.16 Finestra di Istallazione A metà, circa, dell'installazione, apparirà la seguente finestra. Se si desidera che la voce per wxdev-c++ nel menu avvio sia disponibile per tutti gli utenti si sceglie [Yes], altrimenti [No]. Io seleziono [No] perché gli altri utenti del mio computer non vogliono che tocchi il loro ambiente. Si clicca su [Yes] o [No] per continuare. Figura 1.17 La finestra per installare per tutti gli utenti Altri file scorreranno in seguito. Presto wxdev-c++ completerà l istallazione. Si clicca su [Next] per continuare.

20 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 11 di 150 Figura 1.18 Finestra di istallazione dei file alla fine Questo vi porterà nella finestra di completamento. Si deseleziona il check Run wx-dev-c++ se non si vuol avviare wx-dev-c++ subito dopo e si deseleziona Read Sof.T s wxdev-c++ Programming Manual se non si vuol leggere subito questo libro. È preferibile lasciare la selezione di Run wx-dev-c++ e continuare seguendo queste istruzioni. Diversamente la prossima volta che si avvia wxdev-c++ si dovranno completare le operazioni dei passi successivi. Si clicca sul pulsante [Close] e si esce esultando.

21 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 12 di 150 Figura 1.19 La finestra di completamento del setup Quando si avvia wxdev-c++ per la prima volta ci sarà una nota sul fatto che si tratta di una versione beta. Questo sparirà nelle versioni regolari successive. La si può leggere o meno. Si clicca su [OK] per continuare. È opportuno ricordare che appena si trovano degli errori questi si possono comunicare. Tale possibilità consente al software Open Source di migliorarsi offrendovi qualcosa di meglio che epitetare i programmatori quando l'applicazione si blocca. L'altro punto da notare sono gli aggiornamenti, che verranno descritti in dettaglio più avanti in questo capitolo, nella sezione Aggiornare wxdev-c++. Figura 1.20 La finestra delle versioni beta Ora vengono presentate varie opzioni per personalizzare la versione di wxdev-c++. Questa è la stessa introduzione della versione standard del DevC++. Qui è possibile scegliere la lingua preferita. Come già accennato mi attengo all inglese. È possibile scegliere tra 3 diversi temi di icone, (io preferisco New Look) e scegliere se avere i temi di XP o meno. Effettuata la personalizzazione si clicca su [Next] per continuare. Figura 1.21 La finestra di Configurazione

22 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 13 di 150 Di seguito abbiamo la possibilità di attivare il completamento del codice. Si sceglie Yes, I want to use this feature (sì, voglio questa funzionalità). Il visual designer in wxdev-c++ si basa sulla funzione di completamento del codice per crearvi automaticamente gli eventi. Mentre il completamento automatico del codice può risultare fastidioso, è anche una grande fonte di informazioni ed aiuta nell evitare gli errori di tipo. Si clicca su [Next] per continuare. Figura 1.21 Finestra per l abilitazione del completamento automatico del codice La seconda parte della funzione di completamento del codice chiede se si vuol creare una cache. Fondamentalmente cerca tutti i file di intestazione (.h) nella directory include e costruisce un elenco delle funzioni. Successivamente quando si programmerà, la funzione di completamento userà tale cache per suggerire il resto del codice. Si seleziona Yes, create the cache now. Si clicca su [Next] per continuare. A questo punto, a meno di non avere un computer velocissimo, si può preparare la macchinetta del caffè. Figura 1.22 Finestra per la creazione della cache per il completamento del codice (provatene la velocità) Sorseggiate il caffè e continuate ad attendere. Prometto che finirà.

23 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 14 di 150 Figura 1.23 Ancora in attesa, il caffè però è quasi finito Hurrà siamo arrivati alla finestra finale. Se si vuole si può leggere poi: Si clicca su [OK] per completare il processo di istallazione. Figura 1.24 Finalmente la finestra finale Dopo una breve pausa apparirà l IDE, seguita da un suggerimento giornaliero. Aggiornare wxdev-c++ Aggiornare wxdev-c++ è una procedura piuttosto semplice fintanto che ci si ricorda del messaggio, durante l'installazione, che recitava non installare questa versione di wxdev-c++ su un'installazione pre-esistente. Per gli smanettoni di Windows questa risulterà una procedura semplice, ma nel caso non siate sicuri, ecco come fare.

24 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 15 di 150 Come sempre si clicca sul pulsante [Start] nella toolbar. Da menù che appare si sceglie la voce Settings Si clicca su Control Panel (o su WindowsXP si clicca direttamente sul Control Panel ). Figura 1.25 Si va sul Pannello di Controllo (Windows 9x) Il Pannello di Controllo apparirà con diverse voci. Si deve selezionare Add/Remove Programs. Figura 1.26 La selezione di Add/Remove Programs Apparirà la finestra Add/Remove Programs. A seconda di quanti programmi siano già stati installati sul computer, ci potrebbe impiegare qualche secondo per riempire la finestra. Quando la lista sarà completa, si selezionerà wx-devcpp e poi si attiva il pulsante Add/Remove. Click sul pulsante [Add/Remove] per continuare.

25 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 16 di 150 Figura 1.27 La finestra Add/Remove La finestra successiva mostra la collocazione di wxdev-c++ e si dovrà cliccare su Uninstall per proseguire. Click sul pulsante [Uninstall] per continuare. Figura 1.28 La finestra di disinstallazione Scorrerà l elenco dei file che si vanno a disistallare.

26 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 17 di 150 Figura 1.29 wxdev-c++ durante la rimozione. Infine appare la seguente finestra. Se avete speso molto tempo per configurare la vostra IDE secondo i propri gusti, potreste voler lasciare i file di configurazione. Si clicca sul pulsante [No] per conservare i file di configurazione oppure Si clicca sul pulsante [Yes] per cancellare anche i file di configurazione e tornare al default. Figura 1.30 Finestra di rimozione dei file di configurazione Finalmente, la finestra finale. Dato che personalmente mantengo i miei progetti in C:\DEV-CPP, lascio tale directory. È più sicuro lasciare questa directory, per installarci la nuova versione. O eliminarla. Come sempre, la decisione è vostra. Figura 1.31 La finestra finale

27 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 18 di 150 Per installare l ultima release dal sito di Sourceforge si seguono le istruzioni della sezione precedente Il download di wxdev-c++. Utenti Esperti Per gli utenti avanzati esiste la possibilità di cercare le versioni alfa più recenti di wxdev-c++. Questi builds mostrano funzioni che verranno implementate in versioni future di wxdev-c++. Vi sono due siti per provarle, il sito di Tony Reina e quello di Joel Low. Entrambi sono accessibili dalla home page wxdev-c++ sotto Alpha builds sulla barra di navigazione laterale. Figura 1.32 Il link alle versioni alfa dell IDE wxdev-c++ Di seguito c è la pagina del sito di Tony. In genere Tony ha varie versioni di wxdev-c++.

28 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 19 di 150 Figura 1.33 La pagina di Tony su wxdev-c++ Si clicca sul collegamento a wx-devcpp Testers (alpha versions). E si suppone passa alla pagina seguente. Si vorrà prendere la devcpp.palette dato che aggiunge gli ultimi controlli alla tavolozza (palette) delle widget dell'ide. Le date a fianco dei file ne indicano l aggiornamento. Si clicca su quella che interessa. La si salva nel path in cui è installato wxdev-c++ (è ' C:\Program Files\Dev-Cpp se si è scelto il path predefinito). Figura 1.34 L elenco delle versioni di wxdev-c++ di Tony Una volta completato il download si va in C:\Dev-cpp e si rinomina il file devcpp.exe in qualcosa d altro, per esempio devcpp.exe.backup. Questo consente di tornare indietro, se la nuova versione risultasse troppo instabile. Si cerca il file scaricato e lo si rinomina in devcpp.exe. Ora è possibile avviare wxdev-c come di consueto. La pagina di Joel, invece, ha collegamenti solo a versioni alfa in binario o a pacchetti di installazione. Elenca inoltre i collegamenti a varie librerie di wxwidgets precompilate. Queste sono disponibili anche tramite aggiornamento web. Si veda la sezione successiva per maggiori dettagli.

29 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 20 di 150 Figura 1.35 L elenco di Joels delle versioni di pacchetti wxdev-c++. L ultima versione CVS dovrebbe trovarsi in Che fornisce un altra opportunità di test. Aggiungere Package Extra Da qualche parte durante lo sviluppo di DevC++, qualcuno deciso che sarebbe stato meglio se gli utenti avessero potuto aggiunge delle librerie da usare ed aggiornare l'ide. La prima versione di questo meccanismo si chiamava VUpdate. Tuttavia alla fine venne scartato e DevC++ fu dotato di un nuovo sistema chiamato Web Update che consente all'utente di scaricare le versioni più recenti di DevC++ appena rilasciate e i DevPaks. I DevPaks sono pacchetti di file che contengono tante cose diverse, dai file di help alle librerie extra. Dato che wxdev-c++ è basato su DevC++ ne utilizza le stesse funzioni di Web Update, ma ne consegue che vi sono alcuni effetti collaterali da evitare e di cui parleremo più tardi. Innanzi tutto vediamo come aggiungere librerie extra alla nostra nuova installazione di wxdev- C++. Se wxdev-c++ non è già in avviato, lanciatelo. Dal menù Tools si seleziona Check for Updates/Packages

30 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 21 di 150 Figura 1.36 Controllo degli aggiornamenti dal menù tool Questo attiverà l'applicazione Web Update. Ci si assicuri di essere connessi ad Internet prima di procedere ulteriormente. Nella parte superiore della finestra c è la listbox intitolata Select DevPak server. Si clicca sulla freccia per vedere l elenco dei server (al momento ce ne sono solo tre, e solo uno è dedicato a wxdev-c++). Si seleziona 'Dev-C++ primary devpak server'. Figura 1.37 La selezione di un server per DevPak Una volta selezionato il server: Si clicca sul pulsante [Check for updates] in basso nella finestra. Dopo una breve pausa la finestra dovrebbe riempirsi con un elenco di aggiornamenti scaricabili. Da sinistra a destra l'elenco indica: il nome dell'aggiornamento, il numero di versione, se si dispone già di questo file installato anche il numero di versione. Questo per evitare di scaricare e installare versioni obsolete. Segue la dimensione del file, che può essere utile sulle connessioni più lente, e la data di creazione del file che fornisce qualche riferimento sull aggiornamento del file. Si clicca sul check box vicino al nome del file per selezionare quelli da scaricare. Per avviare il download, si clicca sul pulsante [Download Selected]. Da notare il warning seguente... A questo punto tutti i file, con una spunta verde vicino, verranno scaricati.

31 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 22 di 150 Figura 1.38 La selezione delle librerie da scaricare. ATTENZIONE: Ci si ricordi che questo sistema è usato per aggiornare sia DevC++ che wxdev- C++. L immagine seguente mostra una nuova versione di DevC++ scaricabile. Non la si deve scaricare ameno di non perdere la parte di progettazione visuale di DevC++. Si possono anche avere dei problemi nello scaricare delle versioni di wxdev- C++ segnate come Alfa. Tali versioni possono risultare meno stabili della versione corrente o non avere delle funzionalità. Allo stesso modo non si devono scaricare le librerie chiamate wxwindows, questo è il vecchio nome delle wxwidgets e vi daranno problemi. Infine si faccia attenzione nello scaricare le versioni delle wxwidgets, se esse sono compilate con opzioni diverse o sbagliate possono rovinare una buona installazione. È più sicuro scaricarle dal server wxdev-c++. Figura 1.39 Si faccia attenzione a non scaricare gli aggiornamenti di DevC++

32 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 23 di 150 Al completamento del download, i file verranno installati silenziosamente nel caso di WebUpdate Mirrors, oppure comparirà la seguente finestra. Figura 1.40 La finestra di installazione degli aggiornamenti Cliccando su OK si avvia un altra parte dell istallazione dell applicazione chiamata PackMan. No, non è una piccola pallina gialla con un grande appetito, è il gestore di Devpak. È qui che si sceglie o [Install >] o [Cancel]. È più probabile che si scelga di installare. Figura 1.41 Installazione di un nuovo pacchetto. Ora avete installato un nuovo pacchetto. Potrebbero essere stati aggiunti dei nuovi templates alla finestra dei nuovi progetti (New Project), altri file di help al sistema o anche nuove librerie con cui giocare (o lavorare). Manutenzione dei Package Ma cosa succede se si vuol rimuovere un pacchetto scaricato, o si vuol controllare quali pacchetti siano disponibili? Tutto questo è possibile da PackMan. A tale scopo Si seleziona Package manager dal menù Tools.

33 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 24 di 150 Figura 1.42 Il controllo dei propri pacchetti. Una volta avviato, PackMan elenca tutti i pacchetti disponibili. Quando si clicca su uno, il pannello sulla sinistra mostrerà il nome del pacchetto, il numero di versione, una breve descrizione ed un sito di riferimento. Cliccando sul tab dopo General, sulla sinistra, chiamato Files apparirà l elenco di tutti i file contenuti in tale pacchetto. Figura 1.43 Verifica dei pacchetti Da qui è anche possibile installare o rimuovere pacchetti. Quello descritto prima non è l unico modo per ottenere e installare nuove devpaks. È possibile scaricare devpaks da vari siti Web. Per farsene un idea della varietà, basta cercare devpak su Google. Uno dei siti trovati sarà Devpaks.org. Ci si ricorderà di tale nome in quanto era nell elenco del Web Update. Devpaks.org è uno dei più grandi siti per trovare devpaks.

34 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 25 di 150 Figura 1.44 La home page di Devpaks.org Il pacchetti vengono raggruppati in categorie. È possibile scaricare devpaks da qui. Una volta scaricati, è possibile eseguirli direttamente o con un doppio clic. Se wxdev-c++ è stato installato correttamente questo avvierà automaticamente l'installazione guidata come visto in precedenza. Per i devpack relativi a wxdev-c++ esistono altri siti più piccoli. Come quello citato sul forum indicato in seguito. Questo sito è raggiungibile all indirizzo Figura 1.45 L annuncio di un nuovo sito di pacchetti per wxdev-c++ Sono disponibili altri devpaks come quelli in NinjaNL idgets-2.6.2contrib.devpak Widgets-2.6.2contrib.DevPak Utenti Avanzati Gli utenti esperti potrebbero essere interessati a sapere dove vengono memorizzati i devpaks installati da PackMan. La risposta è nella cartella di installazione di wxdev-c++, quella chiamata packages. Perché è interessante? Faccio girare tre diverse installazioni di wxdev-c++, uno sul mio computer di casa, uno sul mio portatile e uno virtuale su vmware di Windows che uso per provarli. Invece di scaricarli e

35 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 26 di 150 installarli continuamente, installo un solo pacchetto sul mio computer principale e poi sulle altre macchine copio i file.devpak in tutti gli altri computer usando l'opzione [Install] in Packman. Figura 1.46 Versioni locali dei DevPaks installati

36 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 27 di 150 Capitolo 2 La compilazione del primo programma Introduzione Ora avete un nuovo IDE installato e aggiornato come desiderato. Cosa ci facciamo? Questo capitolo si occuperà di come aprire i progetti esistenti e come creare e salvarne di propri. Anziché imbottirvi di schernate questo capitolo inizierà indicando le convenzioni usate in seguito. I Menù Quando si vedrà nel testo una linea come File New Project Vorrà dire andare al menù File sulla barra del menu nella parte superiore dell'ide. Selezionare File cliccandoci sù, spostarsi verso alla voce New e selezionare Project dal menù che uscirà, come mostrato in seguito. Figura 2.1 Dimostrazione di File New Project Tasti di scelta rapida Quando si vedranno istruzioni come premere <Ctrl> <F9>, vorrà dire: tenere schiacciato il tasto Ctrl e, tenendolo premuto, schiacciare anche il tasto <F9>. Esistono tre tipi di tasti in combinazione Ctrl, Shift e Alt. Sia Ctrl che Alt si trovano sulla parte inferiore della tastiera. Shift si trova sui lati sinistro e destro della tastiera. I tasti che iniziano con F si trovano sulla parte superiore della tastiera e sono noti come tasti Funzione. Per ulteriori informazioni riguardanti i tasti di scelta rapida da tastiera in wxdev-c++ si veda l Appendice 1. Pulsanti sullo schermo Quando si vedono istruzioni come premi [Close], significa individuare il pulsante sullo schermo con sopra scritto Close e cliccarci col mouse, come mostrato nella seguente schermata.

37 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 28 di 150 Aprire un progetto esistente DevC++, e quindi wxdev-c++, sono accompagnati da un certo numero di progetto di esempio da compilare e provare e studiarli. Inizieremo aprendo e compilando uno di tali progetti. Ci si assicuri che wxdev-c++ sia avviato. Se è visibile la finestra col suggerimento del giorno, la si chiuda cliccando su [Close]. Si va su: File Open Project or File Si aprirà la finestra Open File. La locazione visualizzata sarà la directory dell ultimo file aperto. Questa finestra appare diversamente su altre piattaforme quindi non ci si preoccupi se sembra diversa dalla mia. Figura 2.2 La finestra Open File

38 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 29 di 150 L esempio che vedremo è situato nella cartella \Dev-Cpp\Examples quindi si deve raggiungerla utilizzando l elenco delle cartelle (quella con il prompt 'Look In') o utilizzando l'icona 'Up One Level'. (Se wxdev-c++ è installato nella cartella predefinita, il path completo sarà C:\Program Files\Dev-Cpp\Examples ). Dovreste vedere l'elenco seguente. Figura 2.3 Gli esempi forniti con DevC++/wxDev-C++ Si apra la cartella Jackpot e se ne esamini il contenuto. Si dovrebbe vedere il seguente elenco di file. Quello che si vuole aprire è Jackpot.dev. Quindi o: Doppio click per aprirlo Oppure lo si seleziona e si preme [Open]. Figura 2.4 La selezione di un file di progetto.dev Il file.dev contiene diverse impostazioni del progetto. Tra queste, cose come i nomi dei file usati nel progetto, le opzioni per il compilatore, i numeri delle versioni ecc. In seguito impareremo come modificare tutte le impostazionei incluse in tale file.

39 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 30 di 150 Una volta aperto il file.dev si ritorna nell IDE. Quando il pannello 'Project' riceve il focus, il controllo ad albero sulla sinistra mostra tutti i files inclusi in tale progetto. Per questo progetto c è un solo file chiamato main.cpp. Si clicca su 'main.cpp' per aprirlo nella IDE. Figura 2.5 L elenco dei file inclusi in questo progetto. Il file verrà aperto nell'ide. Quello che si vede è chiamato codice sorgente. Si notano che diverse righe o parti di esse sono colorate diversamente. Questo viene chiamato Syntax Highlighting (evidenziazione della sintassi) e consente di distinguere facilmente le diverse parti del codice con un colpo d'occhio. La colorazione utilizzata dall'evidenziatore delle sintassi può essere configurata secondo le proprie preferenze quindi non ci si deve preoccupare se la vostra colorazione differisce dalla mia. Guardando l immagine sotto si vedrà che le tre righe in alto sono in verde. Le linee che iniziano con #, sono note come linee del Preprocessore. Tratteremo il Preprocessor approfonditamente in seguito. Successivamente si vedono delle parole in grassetto. Queste sono le Parole Riservate. Le Parole Riservate sono parole che fanno parte del linguaggio di programmazione e che non si possono usare per i propri scopi. Si noterà che sono tutte in minuscolo. Il C e il C++ sono linguaggi case sensitive, quindi 'Save' e 'save' sono diversi. Le parti di righe che iniziano e finiscono con sono dette costanti Stringa e sono colorate in rosso. Le costanti numeriche sono in viola. Infine le righe che iniziano con // o iniziano con /* e finiscono con */ sono in blu. Questi sono i commenti. I commenti sono per voi stessi e altri lettori umani per facilitare la comprensione del codice sorgente. Il compilatore non tiene conto dei commenti, ma sono più utili di quanto si creda. Quando si rileggerà un pezzo di codice complicato a distanza di anni, dei commenti ben fatti accorceranno i tempi per capire il codice.

40 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 31 di 150 Figura 2.6 Codice sorgente con la sintassi evidenziata. Non cerchiamo di capire tutto, ora, visto che è il momento di compilare il primo programma. Compilare vuol dire passare il codice sorgente, leggibile dagli umani (vi prometto che in seguito lo saprete leggere e capire), a un programma chiamato compilatore. Il compilatore poi traduce questo codice in binario, comprensibile da un computer. Completata la compilazione, ed eliminati eventuali errori (vedere Debuggare con wxdev-c++), è possibile eseguirlo. Ci sono diversi modi per compilare un programma ma quello più rapido consiste nel premere < Ctrl><F9> (Si veda l introduzione per ulteriori dettagli). Alternativamente si può usare la voce di menù Execute Compile o si può premere il pulsante di compilazione sulla barra degli strumenti. Figura 2.7 Il pulsante di compilazione Apparirà la finestra di compilazione. A seconda della dimensione del progetto questa parte può durare un po, ma per questo programma si richiederà un secondo o quasi. Quando il compilatore ha finito il pulsante[cancel] si tranformerà in [Close]. Click sul pulsante [Close].

41 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 32 di 150 Figura 2.8 La compilazione. Ora siete tornati all IDE, e allora cosa è avvenuto? Dov è il nuovo programma? Non preoccupatevi abbiamo solo costruito il programma, ora dobbiamo avviarlo. Ciò lo si può fare dall IDE.Ancora una volta si hanno diverse possibilità: Si preme <Ctrl><F10>. Oppure si seleziona 'Run' dal menù Execute Run. O si usa il pulsante [Run] sulla barra degli strumenti. Figura 2.9 L avviamento del programma Presto! Il programma sta andando. Nel frattempo lo si può provare. Il gioco consiste nell indovinare il numero scelto dal computer, tra 0 e 30. Quando vi siete scocciati premete qualsiasi tasto e poi <Enter> per uscire. Figura 2.10 Il gioco del Jackpot

42 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 33 di 150 Finora tutto bene, ma non sarebbe meglio compilare e lanciare il programma in una sola volta? Beh! Non siate pigri. Ma nel caso lo siate, e tutti i migliori programmatori lo sono (in realtà sono interessati a risparmiare tempo nel fare cose ripetitive), potrete compilare e lanciare in un sol colpo con uno dei seguenti metodi: Si preme <F9>. Oppure Execute Compile & Run dal menù principale. O si usa il pulsante Compile & Run nella barra degli strumenti. Figura 2.11 Compilazione e lancio in un sol colpo Congratulazioni! Ora, non solo avete imparato ad aprire i progetti, ma anche come compilarli e avviarli in un sol colpo quindi raddoppiando la produttività. (Per il pubblico maschile, chi ha detto che L uomo non può fare due cose contemporaneamente? ). Creare un proprio progetto Quindi avete finito di giocare con Jackpot e siete pronti a passare ad altro. Questo capitolo è intitolato Creare un proprio progetto. Avete appena compilato un programma, ma non il vostro, e allora lo andiamo a fare. Ci sono due modi per creare un nuovo progetto: Dai menù si seleziona File New Project. Oppure dalla barra degli strumenti, si seleziona il pulsante New Project. Figura 2.12 Il pulsante per i nuovi progetti nella barra degli strumenti. Da entrambi si passerà alla finestra New Project. A seconda dei pacchetti installati nel proprio sistema ci potranno essere delle differenze. Potreste avere più o meno tab e più o meno voci in ciascun tab.

43 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 34 di 150 Figura 2.13 La finestra del nuovo progetto. Tra le scelte visibili in questa scheda ci dovrebbe essere Console Application. Se ci sono molte voci potrebbe essere necessario scorrere verso il basso fino a individuarla. Cliccare sull icona 'Console Application'. La finestra intitolata Description: dovrebbe ora mostrare una semplice descrizione di tale progetto. In questo caso apparirà A console application (MSDOS window) [Un applicazione a riga di comando (Finestra MSDOS)]. L altra cosa mostrata in questa finestra è il nome del progetto. Digitare MyHelloWorld nel campo nome Lasciare le altre impostazioni come sono premere il pulsante [OK]. Figura 2.14 Come dovrebbe apparire la finestra New Project

44 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 35 di 150 Se c è già un progetto aperto, apparirà una finestra per chiedervi se si vuole veramente chiudere tale progetto per avviarne uno nuovo. Si selezioni Yes. Se ci sono file non salvati, vi verrà proposto di salvarli. In seguito presenteremo una finestra che chiede dove salvare il file del progetto. Personalmente vado in c:\dev-cpp e vi creo una nuova cartella col nome Projects (se non esiste già) cliccando sul pulsante [Create New Folder]. Figura 2.15 Creazione di una nuova cartella La nuova cartella verrà creata e vi sarà consentito di modificarne il nome. Cambiate il nome della cartella in Projects, tale cartella diverrà il posto principale per tutti i progetti futuri. Entrate nella cartella 'Projects' con un doppio click sul nome della stessa. Create un altra cartella, questa volta chiamandola MyHelloWorld. (Per sicurezza non mettete nessuno spazio nel nome in quanto viene riferito che spesso Dev-C++ ha problems con gli spazi nei path). Entrate in MyHelloWorld con un doppio click sul nome della cartella. Figura 2.16 Il nome del file ha già lo stesso nome del progetto: MyHelloWorld.dev quindi basta premere Save. Il file del progetto verrà salvato e l IDE mostrerà un codice sorgente elementare come il seguente. #include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { system("pause"); return EXIT_SUCCESS; }

45 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 36 di 150 Ancora una volta non entrerò nel dettaglio, ne riparleremo nei prossimi due capitoli. Modifichiamo, invece, il codice sorgente come segue, assicurandosi di cambiare le costanti stringa con le proprie parole. #include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { //Change the text Your name goes here to your name cout << "Hello my name is: " << "Your name goes here" << endl; //You can change the text between the quotes to describe yourself by day cout << "Mild mannered reporter by day" << endl; //You can change the lines between the quotes to describe your super self cout << "Caped crusader by night" << endl; //This line pauses the program, try putting // in front of it to see what //happens system("pause"); //This line says that the program has terminated normally, ie not crashed return EXIT_SUCCESS; } Premere <F9> per compilare e lanciare il vostro primo programma. Apparirà una finestra che chiederà di salvare il codice sorgente. Verificate che la directory visualizzata nella parte superiore accanto all'etichetta Save in: sia quella del progetto, in questo caso MyHelloWorld. wxdev-c++ avrà automaticamente nominato il file sorgente main.cpp. L estensione.cpp indica al compilatore che è un file sorgente C++, non C o qualsiasi altro linguaggio. È possibile modificarne il nome (ma non l'estensione) volendo, ma è meglio lasciar stare e premere il pulsante [Save]. Immediatamente partirà il compilatore e un secondo dopo circa il programma verrà eseguito. Se avete apportato le modifiche suggerite queste verranno visualizzate sullo schermo. Figura 2.17 L output del programma MyHelloWorld.

46 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 37 di 150 Congratulatevi con voi stessi, avete appena scritto e compilato il primo programma. Benvenuti nei ranghi dei programmatori C++. Ma per iniziare in modo più profiquo studiatevi i prossimi due capitoli.

47 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 38 di 150 Capitolo 3 Fondamenti di Programmazione C Introduzione Nel 1972 Dennis Ritchie scrisse il linguaggio di programmazione C per usarlo sul sistema operativo Unix. Nel 1978 Kernighan & Richie scrissero il libro The C Programming Language, che è diventato quasi uno standard C noto oggi come K&R C. Nel 1983 L'ANSI (American National Standards Institute) ha creato una definizione standard del linguaggio C. Questa è stata completata nel 1988 ed è conosciuta oggi come ANSI C. Questo rende il K & R C obsoleto nonostante lo si ritrovi di tanto in tanto. Da allora il comitato ANSI ha prodotto uno standard di C più recente noto come C99, alla versione precedente ci si riferisce come C89. C99 aggiunge alcune funzionalità necessarie e prende in prestito qualcosa dal C++. Né questo capitolo né il successivo sono pensati per insegnare a progettare programmi, argomento che richiederebbe diversi libri in più (con lo scoppio di qualche guerricciola nel frattempo). Né sono scritti per insegnare i linguaggi C o C++ in modo approfondito, cosa che richiederebbe un intero scaffale di libri. Questi due capitoli vi forniranno i primi elementi di questi linguaggi e con degli esempi vi daranno una spintarella. Vi sono molti ottimi libri su questi argomenti e diversi siti Web. (Si faccia riferimento alle risorse nell Appendice yy) ATTENZIONE: C e C++ sono detti linguaggi Case Sensitive. Questo vuol dire che printf non è uguale a PRINTF né a Printf. Altri linguaggi non sono così restrittivi e questo potrebbe dare qualche problema a chi proviene da questi linguaggi. Cominciamo con un semplice esempio Per cominciare diamo uno sguardo al file di un codice sorgente in linguaggio C. Sarà nostra cura crearlo in wxdev-c++ e compilarlo per vedere quello che fa. In seguito lo analizzeremo per studiare come fa quello che fa. Per iniziare il processo: Ci si assicuri che wxdev-c++ sia aperto Si crea un nuovo progetto (come nel capitolo precedente) Si seleziona 'Console Application'. Si seleziona il progetto 'C Project' Lo si chiama 'SimpleC'

48 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 39 di 150 Figura 3.1 Le impostazioni per il programma SimpleC Si clicca sul pulsante [OK] e verrà richiesto di chiudere ogni altro progetto aperto, quindi di salvare quello corrente: Si cerca la cartella Project creata in precedenza e vi si crea una nuova cartella chiamata SimpleC. Si apre la cartella 'SimpleC' e vi si salva il file del progetto. Sarete riportati nell IDE col seguente codice appena generato #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { } system("pause"); return 0; In primo luogo per renderla un po più facile capire a quali righe mi riferisco, impostiamo la funzione di numerazione delle righe in wxdev-c++. Si seleziona dal menu principale: Tools Editor Options. Nella finestra dell Editor Options: Si clicca sul secondo tab indicato con 'Display' Si clicca sulla spunta vicino a 'Line Numbers'

49 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 40 di 150 Figura 3.2 Mostrare la numerazione delle righe Il codice apparirà così 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define TOP_MAN 2 5 #define THE_PRISONER int main(int argc, char *argv[]) 8 { 9 int i = 0; printf("who are you?\n"); 12 printf("i am the new number %d, ", TOP_MAN); 13 printf("you are number %d\n\n", THE_PRISONER); for(i = 0; i < THE_PRISONER; i++) 16 { 17 printf("thinking...\n\n"); 18 } if(i == THE_PRISONER) 21 printf("i am not a number, I am a free man!\n"); system("pause"); 24 return 0; 25 } Si prema <F9> per compilare ed avviare il programma.

50 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 41 di 150 Vi verrà chiesto di salvare il file del codice sorgente, lo si faccia nella stessa directory del file del progetto. Dovreste ottenere l output seguente. Figura 3.3 L output dal programma SimpleC Suddividiamo questo esempio in varie parti per analizzarle brevemente qui e più approfonditamente in seguito. Il linguaggio di programmazione C ha solo 32 parole chiave (elencate nell'appendice B). Nessuna delle quali fornisce l operazione di output sullo schermo. Prima di dire ma aspetta un attimo, ho appena lanciato un programma che scrive sullo schermo, lasciate che mi spieghi. Ciò che manca nelle parole chiave del C è contenuto nelle librerie. L ANSI C dispone di un gran numero di librerie contenenti funzioni per vari usi. La funzione printf è una di queste. Prima di poter usare tali funzioni si deve dire al C che vogliamo far uso delle librerie contenenti tali funzioni. Per fare ciò si us ail commando #include. Lo si può vedere nell esempio alle righe 1 & 2. Tutte le righe che iniziano con # vengono dette Righe del Prepocessore e di loro ce ne occuperemo nella sezione Il Preprocessore. Ci sono altre due righe nell esempio la 4 & 5, queste righe iniziano con #define e creano valori costanti. Come abbiamo menzionato, il C è composto da funzioni. In seguito, nella sezione "Funzioni", ne creerete di vostre per capirle meglio. Il C esige che vi sia almeno una funzione in ogni programma e che si chiami main. Una funzione si compone di un intestazione e di un corpo racchiusi tra parentesi graffe {}. Il codice racchiuso tra le parentesi graffe nelle righe 8 & 25 è quello che si chiama il corpo della funzione. I valori possono essere memorizzati nelle variabili, ce n è una dichiarata nella riga 9. La prima parte, int, è una parola chiave e ci dice che la variabile verrà memorizzata come un intero. Un valore intero può contenere solo numeri interi. Abbiamo assegnato alla variabile il nome i così sarà possibile farvi referimento in seguito, come nelle righe 15 & 20. ATTENZIONE: In C quando si definisce una variabile questa potrà contenere qualsiasi valore, quindi è meglio assegnarle un default noto come nella riga 9 dove ad i è stato assegnato il valore 0. Questo è un trabocchetto per i nuovi programmatori o per quelli provenienti da altri linguaggi.

51 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 42 di 150 Le righe dalla 15 alla 18 costituiscono un esempio di Loop di controllo e se ne discuterà nella prossima sezione Elementi di C così come le righe 20 & 21 sono un esempio di Esecuzione Condizionale. Delle altre righe se ne discuterà in Input/Output ed alter utili funzioni. Elementi di C Per memorizzare i dati in un programma C si usano le variabili. Queste vengono definite come nella righa 8 dichiarando prima il tipo di dato che la variabile dovrà contenere, poi assegnandole un nome univoco. È buona norma inizializzare la variabile assegnandole già in questo punto un valore. Tipi di dati Nel C89 ci sono 5 tipi base di dati. Questi sono char, int, float, double e void. char è progettato per contenere i valori corrispondenti a ad un carattere. int è per contenere un numero intero. float e double per numeri in virgola mobile e void è un valore nullo. Alcuni di questi tipi di dati si possono estendere con le parole chiavi signed, unsigned, long, e short. int può avere tutti questi valori, char può essere solo signed o unsigned e double può avere solo long. I tipi di dati unsigned (senza segno) possono contenere solo numeri da 0 al loro intervallo massimo. I dati signed (con segno) dimezzano tale intervallo per poter contenere in una metà i valori negatividata e nell altra quelli positivi. Lo standard C indica un intervallo minimo per i tipi di dati, ma non un massimo che può variare a seconda del compilatore e della piattaforma. Il seguente programma chiamato DataSize mostra tali dimensioni. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 printf("the size of a char is %d bits\n",8 * sizeof(char)); 7 printf("the size of a unsigned char is %d bits\n",8 * sizeof(unsigned char)); 8 printf("the size of an int is %d bits\n",8 * sizeof(int)); 9 printf("the size of a unsigned int is %d bits\n",8 * sizeof(unsigned int)); 10 printf("the size of a long int is %d bits\n",8 * sizeof(long int)); 11 printf("the size of a short int is %d bits\n",8 * sizeof(short int)); 12 printf("the size of a double is %d bits\n",8 * sizeof(double)); 13 printf("the size of a float is %d bits\n",8 * sizeof(float)); 14 printf("the size of a void is %d bits\n",8 * sizeof(void)); 15 printf("the size of a long double is %d bits\n",8 * sizeof(long double)); 16 system("pause"); 17 return 0; 18 } Nomi di Variabili I nomi delle variabili hanno delle limitazioni. Il nome non può essere una parola chiave, deve essere unico e può contenere ogni carattere alfa-numerico e l underscore (_), ma non può iniziare con un numero.

52 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 43 di 150 Blocchi di istruzioni Avrete notato nel codice di esempio, l'uso delle parentesi graffe {}. Queste parentesi racchiudono il codice all'interno di quello che viene chiamato Statement Blocks (blocco di istruzioni). Il significato lo si può cercare nella sezione seguente Scope. Le parentesi graffe devono sempre essere usate in coppia, vale a dire la parentesi graffa aperta { deve avere una corrispondente parentesi graffa di chiusura }. Se avete problemi con parentesi non appaiate consultate il messaggio di attenzione in operatori parentesi. Scope (visibilità) Si dice che le variabili hanno uno Scope in C e si può solo far riferimento alle variabili in tale scope. Ci sono diversi tipi di scope. Uno è quello globale, alle variabili di questo tipo ci si può far riferimento da qualsiasi parte del programma (che può comprendere diversi file sorgenti). Un secondo tipo è lo scope del file, alle variabili di questo tipo ci si può accedere solo dal codice nello stesso file sorgente. Il significato di tali differenze tra scope globale e scope di file sarà chiaro in seguito. L ultimo tipo è lo scope locale. Le variabili dichiarate all interno di blocchi di istruzioni sono visibili solo al codice contenuto nello stesso blocco. Operatori Gli operatori (=,&,%,!, ecc) si suddividono in diversi gruppi: di assegnazione, aritmetici, relazionali, logici, bit a bit, puntatori, riferimento, indicizzazione e parentesi sono tutti tipi di operatori. Ce ne sono altri di cui non discuteremo. Gli operatori puntatori verranno spiegati nel paragrafo Puntatori, gli operatori di riferimento in Strutture e gli operatori di indicizzazione in Array. Degli operatori bitwise (bit-a-bit) non se ne parlerà affatto. Operatori di Assegnazione L operatore principale di assegnazione è = per esempio int x = 0; Questa espressione assegna il valore zero alla variabile x. Il valore da assegnare deve sempre stare alla destra dell espressione, per es. 0 = int x non è un espressione valida. È anche possibile fare assegnazioni multiple per esempio x = q = r = t = 0; In questo esempio alla variabile t viene assegnato il valore zero, quindi alla variabile r viene assegnato il valore di t e così via fino a x. È anche possibile dichiarare ed assegnare contemporaneamente più variabili dello stesso tipo per es. int i=0,a=5,b=10,c=15; Se si assegna una variabile di un certo tipo a una variabile di un altro tipo, avviene quello che è conosciuto come conversione automatica di tipo (cast). Quando il valore sulla destra dell espressione viene assegnato ad una variabile sulla sinistra, si tenta di convertirlo automaticamente nel tipo della variabile sulla sinistra. Se il tipo sulla sinistra ha un ampiezza inferiore del tipo sulla destra, allora ci potrà essere una perdita di dati. L esempio seguente ne è una dimostrazione. Si crea un nuovo progetto come al solito. Lo si chiama TruncationAssignment. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 short int ashortint= 0; 7 float afloat = ; 8 long int alongint= ;

53 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 44 di /*Print the value of the long int*/ 10 printf("the long int value is: %d\n",alongint); 11 /*Convert the long int to a short int*/ 12 ashortint = alongint; 13 printf("the long int has been assigned to a short int\n"); 14 /*Print the value of the short int*/ 15 printf("the value now = %d\n\n",ashortint); 16 /*Repeat for a float to int*/ 17 printf("the float value is: %f\n",afloat); 18 printf("the float has now been assigned to a short int\n"); 19 printf("the value is now: %d\n",ashortint); 20 system("pause"); 21 return 0; 22 } Il compilatore potrebbe avvertire della possibile perdita di dati. Se si intende convertire da un tipo ad un altro lo si può comunicare al compilatore utilizzando il cast. Per esempio se x è un intero, lo si può usare in questa espressione float y = (float) x/3; Ci sono operatori di assegnazione abbreviati. Talvolta si vorrà assegnare ad una variabile se stessa più o meno un certo valore. Per esempio x = x 20; lo si può abbreviare con x -= 20; oppure +=. Queste abbreviazioni si usano molto nei programmi professionali. Operatori Aritmetici Ci sono sette diversi operatori aritmetici, i quattro fondamentali: + per l addizione / per la divisione * per la moltiplicazione - per la sottrazione Due operatori aritmetici abbreviati. Sono -- e ++ che vengono usati per incrementare o decrementare una variabile di uno. Per esempio si può scrivere x = x + 1; oppure x++;. Gli operatori abbreviati si possono usare prima o dopo una variabile, per esempio y = x++; oppure y = ++x;. Dov è la differenza? La differenza è che il primo imposta y uguale a x poi imposta x a x + 1. Il secondo imposta x a x + 1 quindi assegna il risultato a y. Una differenza sottile ma importante. L ultimo operatore è il modulo %. Si usa solo con interi e restituisce il resto di una divisione intera. Operatori Relazionali Gli operatori relazionali confrontano due diversi valori e restituiscono vero o falso (1 o 0). I sei operatori relazionali sono: > maggiore di >= maggiore o uguale < minore di <= minore o uguale a == uguale a!= diverso da a

54 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 45 di 150 Operatori Logici Gli operatori logici si possono usare coi valori vero e falso (ovvero 1 e 0). Ce ne sono tre: && AND (e) OR (o, oppure)! NOT (negazione) Forniscono i valori in base alla seguente tabella. X Y X && Y X Y!X 0 (falso) 0 (falso) 0 (falso) 0 (falso) 1 (vero) 0 (falso) 1 (vero) 0 (falso) 1 (vero) 1 (vero) 1 (vero) 1 (vero) 1 (vero) 1 (vero) 0 (falso) 1 (v) 0 (falso) 0 (falso) 1 (vero) 0 (falso) Dato che gli operatori logici funzionano con i valori vero/falso si possono combinare con gli operatori relazionali. Per esempio 4>6 && 3<7 7!=5. NOTA: In C non c è l operatore XOR, ma lo si può facilmente creare con una funzione. Operatori Parentesi Gli opera tori C funzionano secondo un ordine di precedenza. Questo vuol dire che un espressione come la seguente x = / * 352; non viene valutata da destra a sinistra. A seconda della precedenza degli operatori l ordine dei calcoli può differire. Per fare in modo da valutarla come desiderato, bisogna usare gli operatori parentesi ( ). Per esempio x = (40 + (3/(5+(7*352)))). Viene calcolata prima la coppia di parentesi più interna quindi si procede verso quelle più esterne. ATTENZIONE: Si faccia attenzione ad avere il numero di parentesi chiuse pari al numero di quelle aperte altrimenti il compilatore segnalerebbe un errore come questo: main.c: In function `main': main.c:6: error: syntax error before ';' token Allo stesso modo se ci sono più parentesi chiuse di quelle aperte ci sarà un errore come questo: main.c: In function `main': main.c:6: error: syntax error before ')' token Se avete dei problemi è possibile attivare l evidenziazione delle parentesi. In Tools Editor Options. Sulla finestra che viene mostrata si segna il check box a fianco di Highlight matching braces/parentheses come mostrato sotto.

55 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 46 di 150 Da questo momento selezionando una parentesi, l editor proverà a mettere in evidenza la parentesi corrispondente. Cicli (loop) Condizionali Senza aggiungere niente, un programma comincia dall inizio, esegue le istruzioni ed arriva all ultima istruzione dove esce. Talvolta tra l inizio e la fine si vuole che il programma esegua più volte la stessa sequenza di comandi. Per esempio si potrebbe stampare Vattene via 20 volte affinché qualcuno recepisca il messaggio. Per farlo, basterebbe digitare i comandi uno dopo l altro venti volte, così: printf( Go away!\n ); printf( Go away!\n ); printf( Go away!\n ); printf( Go away!\n ); In questo caso non è un operazione complicata, ma che ne dite se lo si vorrebbe scrivere per 2000 volte, presto ci si annoierebbe a scrivere la stessa cosa. Sarebbe anche difficile manutenere il codice. Se poi basterebbe scriverlo 863 volte? Fortunatamente c è un metodo molto più semplice detto Conditional looping (Ciclo condizionale). Il C ha 3 tipi di loop, il ciclo for, il while ed il do while. Il ciclo do while garantisce che il contenuto venga eseguito almeno una volta, prima di controllarne la fine. Il codice contenuto nei cicli while e for potrebbe non essere mai eseguito dato che la condizione di uscita viene controllata all inizio, e se non è vera, le istruzioni del ciclo vengono saltate. Il ciclo for ha questa forma generale: for( <Inizializzazione del ciclo >;<Condizione di controllo>;<incremento del ciclo>) È possible usare l istruzione for in molti modi insoliti, ma qui ne prenderemo in esame solo l utilizzo base. I cicli while e do while sono molto più semplici in quanto contengono solo la condizione di controllo. Create un nuovo progetto chiamato Loopy e modificate il codice come il seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 /* Variable to check the loop condition */ 7 int i = 0; 8 print f("for loop countdown to liftoff\n") ; 9 for(i= 10;i>0;i--) 10 { 11 printf("%d\n",i); 12 } 13 printf("we have lift off.\n\n"); 14 system("pause"); printf("\nwhile loop count to five\n");

56 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 47 di /*Reset i to 0, then try a while loop*/ 18 i = 0; 19 while(i <= 5) 20 { 21 printf("just checked condition i <= 5 and "); 22 printf("i actually = %d\n",i); 23 /*Need to increment i*/ 24 i++; 25 } 26 system("pause"); printf("\ndo...while loop count to five\n"); 29 /*Reset i to 0, then try a do...while loop*/ 30 i = 0; 31 do 32 { 33 printf("i = %d and ",i); 34 /*Need to increment i*/ 35 i++; 36 printf("just about to checked condition i <= 5\n"); 37 }while(i <= 5); 38 system("pause"); return 0; 41 } Analisi del codice: Alla riga 7 si crea la variabile contatore i e la si inizializza a 0. Dalle righe 9 alla 12 si crea un ciclo for. In precedenza si è detto che il ciclo 'for' ha tre argomenti, l inizializzazione, il test e l incremento. L inizializzazione i=10 imposta la variabile i a 10 e viene eseguita una sola volta. Il test i>0 controlla che i sia maggiore di zero e viene eseguito in ciascun ciclo. Quando la condizione diventa falsa, il ciclo cessa. L incremento i-- diminuisce i di 1 per ogni passaggio del ciclo. Tra le righe 19 e 25 si crea un ciclo while. La condizione viene verificata prima di avviare il ciclo, e deve restare vera affinché il ciclo si ripeta. In questo caso finché i resta maggiore o uguale a 5. La riga 24 aumenta i di uno ad ogni passaggio. Nelle righe da 31 a 37 c è il ciclo do while. Questo è molto simile al ciclo while, solo che la condizione viene controllata alla fine. Se il ciclo for contiene solo una riga di codice allora se ne può usare la versione abbreviata senza parentesi graffe. Per esempio le righe dalla 9 alla 12 potrebbero essere sostituite con 9 for(i=10;i>0;i--) 10 printf("%d\n",i); In questo caso il codice eseguito dal ciclo for termina al punto-e-virgola alla fine della riga 10. Si può uscire da un ciclo in qualsiasi momento con la parola chiave break, con questa si esce dal ciclo e si ricomincia subito la fine del ciclo stesso. NOTA: Il ciclo while finisce alla riga 25 con una graffa chiusa }. Tuttavia il ciclo do while finisce alla riga 37 con while();. Il punto-e-virgola alla fine dell istruzione while è di vitale importanza, omettendolo il programma non si compilerà.

57 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 48 di 150 ATTENZIONE: Tutti e tre i cicli modificano la condizione di test alterando il valore di i. Se il valore di i non viene modificato la condizione di controllo restituisce sempre true (vero) ed il ciclo continua all infinito. Per verificarlo, cancellate la riga 35, compilate e rilanciate. Per fermare il programma si preme <Alt><F2> dall interno di wxdev-c++ o cliccando sul pulsante mostrato: Esecuzione Condizionale Nella programmazione, come nella vita, ci sono momenti in cui si vuol fare qualcosa ed altri in cui non lo si vuol fare. Per esempio se piove si vorrà restare nel letto e dormire. Se c è il sole probabilmente no. Questo è detto Esecuzione Condizionale e si può ottenere con l istruzione if. L istruzione if ha il seguente formato: if(<condizione di test>) Talvolta si desidera fare cose diverse a seconda del risultato del test di una istruzione, in questo caso si fa seguire ad if l istruzione else if o un else per fare qualcosa nel caso in cui il test dell if fallisca. Per esempio nel codice seguente, si crea un nuovo progetto e lo si chiama IfBob, quindi si modifica il codice precedente nel modo seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 int BobsAge = 0; 7 for(bobsage = 0;BobsAge <= 100;BobsAge += 10) 8 { 9 if(bobsage <= 0) 10 { 11 printf("bob has not been born yet\n"); 12 } 13 else if (BobsAge <= 10) 14 { 15 printf("bob is a young boy\n"); 16 } 17 else if (BobsAge > 20 && BobsAge <= 30) 18 { 19 printf("bob is a young man\n"); 20 } 21 else if (BobsAge <= 80) 22 {} 23 else if (BobsAge > 80 && BobsAge <= 90) 24 { 25 printf("bob is an old man now\n"); 26 } 27 else 28 {

58 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 49 di printf("bob has just got a telegram from the Queen\n"); 30 } 31 } 32 system("pause"); 33 return 0; 34 } In un gruppo di istruzioni if else, vengono contrallate tutte le condizioni, dall alto in basso fino a trovarne una vera, che sarà l unica ad essere eseguita. Se non ce n è nessuna vera, viene eseguito il codice dell istruzione else. Nell esempio, le istruzioni if..else if..else stanno all interno di un ciclo for loop per essere sicuri che vangano eseguite tutte. Com e visto in precedenza con l istruzione for se è un solo comando a seguire il test, si possono omettere le parentesi graffe. L istruzione if non è la sola istruzione di esecuzione condizionale. Ce n è una forma abbreviata, (talvolta detta operatore ternario dato che richiede tre argomenti)?: che ha questa forma: <test>?<codice se vero>:<codice se falso> Il tutto viene illustrato nel programmino seguente. Si crea un nuovo progetto chiamato BobsLife. E si immette il seguente codice. 1 #i nclude <stdio.h> 2 #include <stdlib.h> 3 4 #define ALIVE 1 5 #define DEAD 0 6 int main(int argc, char *argv[]) 7 { 8 int BobStatus = ALIVE; 9 printf("bob is "); 10 BobStatus == ALIVE?printf("alive\n"):printf("dead\n"); 11 s ystem( "PA USE"); 12 return 0; 13 } La riga 10 controlla BobsStatus per il valore ALIVE. Se è vero, viene eseguita la prima istruzione di printf, se no viene eseguita la seconda. L ultima forma di esecuzione condizionale è l istruzione switch...case. Funziona come una serie di istruzioni if..else if..else e può controllare solo valori interi. L istruzione switch contiene un espressione, il valore che viene controllato, e da un elenco di istruzioni case. Se una istruzione case coincide col codice contenuto nell istruzione switch, questa viene eseguita. Ogni istruzione case finisce con l istruzione break ; se viene omessa, viene eseguito il codice del case successivo. L ultima istruzione è chiamata default. Questa contiene il codice che verrà eseguito se nessun case ha restituito true. Tutto questo è mostrato nel seguente programma. Si crea un progetto intitolato DayCalculator e vi si immette il codice seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define MONDAY 1

59 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 50 di #define TUESDAY 2 6 #define WEDNESDAY 3 7 #define THURSDAY 4 8 #define FRIDAY 5 9 #define SATU RDAY 6 10 #define SUNDAY 7 11 #define NO_DAY int main(int argc, char *argv[]) 14 { 15 int day = MONDAY; 16 for(day = MONDAY;day <= NO_DAY;day++) 17 { 18 switch(day) 19 { 20 case MONDAY: 21 printf("it's Monday, off to work\n"); 22 break; 23 case TUESDAY: 24 printf("it's Tuesday, long week ahead\n"); 25 break; 26 case WEDNESDAY: 27 printf("it's Wednesday, halfway there\n"); 28 break; 29 case THURSDAY: 30 printf("it's Thursday, one more day to go\n"); 31 break; 32 case FRIDAY: 33 printf("thank Crunchie, it's Friday\n"); 34 break; 35 case SATURDAY: /*This is an example of a drop through*/ 36 case SUNDAY: 37 printf("it's the weekend, let's live it up\n"); 38 break; 39 default: 40 printf("hey! This day cannot exist\n"); 41 } 42 } 43 system("pause"); 44 return 0; 45 } Almeno a me, lo switch sembra un po strana e non C. Osservate quelle istruzioni break, quelle possono provocare un sacco di problemi! Altri linguaggi, come il Visual Basic, hanno l istruzioni simile Select, ma in tali linguaggi l istruzione break non è richiesta e l istruzione seguente non viene eseguita come nella riga 35 dell esempio sopra. Se nel vostro programma sembra che vengano eseguite diverse istruzioni, si controlli di aver inserito tutti i break. Ricordatevi che l istruzione default verrà eseguita solo se nessun altro case lo è stato, oppure se è stato omesso il break precedente. Ci si potrebbe chiedere perché il C sia stato fatto così, dopo tutto sarebbe stato più semplice per l esecuzione fermarsi all inizio del case successivo. Il fatto è che in questo modo non sarebbe stato possibile eseguire lo stesso codice per più di un case come nelle righe da 35 a 37 dove sia Saturday (Sabato) che Sunday (Domenica) devono avere lo stesso output. NOTA: Si possono incontrare istruzioni come if(x), cosa vuol dire? Dato che un istruzione if esegue il controllo per i valori vero/falso, se x è uguale a 0 il test fallisce, tutti gli altri valori diversi da zero 0 sono considerati vero. Quindi si può scrivere if(x!= 0), ma questo è considerato poco elegante.

60 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 51 di 150 ATTENZIONE: Il C ed il C++ sono strani nel modo di assegnare un valore ad una variabile, si usa = come in MyAge = 243;. Per il test dell uguaglianza si usa == come in if(myage == 243). Questa è una caratteristica che può provocare parecchi errori, in quanto questo codice if(myage = 243) verrà compilato senza che il compilatore mostri degli errori. Questo if sarà sempre vero ed il codice dopo di esso verrà sempre eseguito. Il Preprocessore Il preprocessore è un insolita funzionalità del C. Esso gira prima del compilatore ed altera il codice sorgente inserendo le dichiarazioni di funzioni dai file di intestazione (header), espandendo le definizioni di macro, e determinando quale codice dovrà essere compilato e quale no. Le istruzioni del preprocessore iniziano sempre con un # e, diversamente dalle righe del C non finiscono con un punto e virgola. L istruzione del preprocessore più comune è quella di #include. Questa ha sia la forma di #include <filename.h> per i file di libreria che #include filename.h per quelli propri. Come si vedrà nella prossima sezione Funzioni, il C non consente ad un programmatore di usare una funzione finché non non ne conoscerà il nome, i parametri che si aspetta, e quale valore restituirà. L istruzione #include aggiunge tutte queste informazioni all inizio del codice sorgente. Nell esempio SimpleC abbiamo incluso i file stdio.h e stdlib.h. Dobbiamo avere stdio per la funzione printf, e stdlib.h per la funzione system. NOTA: Su piattaforme diverse da Windows i nomi dei file include sono case sensitive ed un errore commune è quello di usare le maiuscole scorrette, ne viene fuori che il compilatore non trova il file corretto. La seconda istruzione più comune è la #define. Questa viene usata per definire un nome di una costante che ha un valore. Quando tale nome apparirà nel codice, il preprocessore la sostituirà col suo valore. Spesso la si usa per le variabili costanti (variabili che non cambiano il proprio valore). Un utile funzionalità di ciò è quella creare un codice auto documentato. Per esempio si può creare una definizione come questa: #define DAYS_IN_A_WEEK 7 Quindi usarla nel codice: for(i = 0;i <DAYS_IN_A_WEEK;i++) cosa che aiuta altri programmatori a capire cosa faccia il codice, anziché la riga: for(i=0;i<7;i++) Per convenzione le variabili costanti si scrivono in maiuscolo. Assieme a #define ci sono #ifdef, #ifndef, #else, #endif e #undef. Queste si possono usare per includere o escludere blocchi di codice secondo il valore di un istruzione #define. Il seguente codice #ifdef FRED non verrà compilato se FRED non è stato definito. Il seguente codice #i fndef FRED verrà compilato solo se FRED non è stato definito. #endif chiude il blocco di codice ed #undef rimuove la definizione di una precedente costante in #define.

61 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 52 di 150 Infine, allo stesso modo, ci sono le istruzioni #if, e #elif, esse controllano la verità di un istruzione e funzionano allo stesso modo di #ifdef includendo il codice se l istruzione è vera. Il codice seguente usa tutte queste istruzioni del preprocessore. Si crea un nuovo progetto di tipo Console Application chiamato Prepro. Lo si salva in una cartella di nome Prepro e vi si immette il seguente codice di esempio. Si controlli se funziona prima di compilarlo e lanciarlo. 1 #include <stdio.h> /*include this library to allow us access to printf*/ 2 #include <stdlib.h> /*include this library to allow us to use system*/ 3 4 #define RED_BALLOONS 99 /*Define RED_BALLOONS to be equal to 99*/ 5 int main(int argc, char *argv[]) 6 { 7 #ifdef RED_BALLOONS /*Check if RED_BALLOONS has been defined*/ 8 printf("there were %d red balloons\n",red_balloons); 9 #else /*Do this if the previous #ifdef was false*/ 10 printf("there were no red ballons\n"); 11 endif /*End this conditional block*/ #if RED_BALLOONS < 98 /*Check if RED_BALLOONS is lower than 98*/ 14 printf("there were less than 98 red balloons\n"); 15 elif RED_BALLOONS > 98 /*If previous #if was false check this one*/ 16 printf("there were more than 98 red balloons\n"); 17 #endif /*End this conditional block*/ #undef RED_BALLOONS /*Remove define RED_BALLOONS*/ 20 printf("\nbig BANG!\n\n"); # ifndef RED_BALLOONS /*Check if RED_BALLOONS has not been defined*/ 23 printf("there were no red ballons\n"); 24 #else /*Do this if the previous #ifndef was false*/ 25 printf("there were %d red balloons\n",red_balloons); 26 #endif /*End this conditional block*/ system("pause"); 29 return 0; 30 } Funzioni Le funzioni sono blocchi di codice a sé stante, si possono vedere come miniprogrammi che prendono vari parametri, fanno qualcosa e restituiscono un risultato. Le funzioni si definiscono in questo modo: Return_Type Function_Name (Parameter_Type Parameter_Name, ) { Block of code; } Il tipo restituito può essere sia un tipo di dato come int, float, ecc, che un puntatore ad una locazione di memoria, un tipo di dato definito dall utente come una struct, o void. Nel caso di void si sta dicendo che la funzione non restituirà niente. La funzione finisce quando incontra l istruzione return, (o finisce il blocco di codice se il tipo da restituire è void). Qualsiasi

62 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 53 di 150 istruzione dopo un return è detto Unreachable code (codice irragiungibile) dato che non verrà mai eseguito. Il nome di una funzione può essere qualsiasi solo con qualche regola. Il nome deve essere unico, quindi non si può creare una funzione chiamata printf se c è #include stdio.h, dato che confonderebbe il compilatore. Inoltre il nome deve rispettare le stesse regole delle variabili. È buona regola dare alla funzione un nome che ne indichi l uso, per es. DisplayMenu anziché MyThingyFunction. Una funzione può avere un qualsiasi numero di parametri o nessuno. Ogni parametro deve avere un nome ed un tipo associato. Questi tipi di dati sono gli stessi discussi in precedenza. All interno della funzione, i parametri agiscono come una variabile con una visibilità (scope) locale. Nei programmi C si userà sempre almeno una funzione, questa è quella principale main, ed è una funzione speciale dato che l esecuzione del programma parte all inizio di tale funzione e termina alla fine di essa. main segue le stesse regole delle altre funzioni, ha un tipo di ritorno int, che viene usato per indicare se il programma sia stato eseguito con o senza errori. Prende anche dei parametri che le vengono passati all avvio del programma. Le funzioni hanno un duplice uso. Prima di tutto consentono di suddividere il programma in sotto-unità più piccole per facilitarne la comprensione. In secondo luogo consentono il riutilizzo di pezzi di codice più e più volte anziché ripeterne la scrittura nello stesso blocco di codice. Creeremo un programma che usa un paio di funzioni elementari per cominciare a prenderne dimestichezza. Ci si assicuri che wxdev-c++ sia stato avviato. Si crea un nuovo progetto C chiamato Functions E lo si salva in una cartella chiamata Functions nella cartella Project. Il codice è quello seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 /*This function has no parameters and returns nothing*/ 5 void DisplayMenu() 6 { 7 printf("\n1. Calculate 5 + 4\n"); 8 printf("2. Print 3 Names\n"); 9 printf("3. Quit this lunacy\n"); 10 } /*This function has two parameters both are integers it adds 13 these together and returns a integer which is the result*/ 14 int Calculate(int FirstNumber, int SecondNumber) 15 { 16 return FirstNumber + SecondNumber; 17 } /*This function has no parameters and returns nothing*/ 20 void DisplayNames() 21 { 22 printf("\nthree Names\nHumphrey\nIngrid\nPeter\n"); 23 } 24

63 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 54 di int main(int argc, char *argv[]) 26 { 27 int UsersChoice = 0; while (UsersChoice!= 3) 30 { 31 /*Call function to show menu*/ 32 DisplayMenu(); 33 /*Function from stdio.h which reads the users input*/ 34 scanf("%d",&userschoice); if(userschoice == 1) 37 /*Call the Calculate function from within the printf function*/ 38 printf("\n5 + 4 = %d\n",calculate(5,4)); 39 else if (UsersChoice == 2) 40 /*Call the DisplayNames function*/ 41 DisplayNames(); 42 } return 0; 45 } Il programma comincia all inizio della funzione main. Dichiara una variabile UsersChoice e ne imposta il valore a 0. Quindi entra in un ciclo condizionale, e, fin quando la variabile UsersChoice resta diversa da 3, esegue continuamente le istruzioni. All interno del ciclo, la prima chiamata è alla funzione DisplayMenu, stampa il menù sullo schermo. Poi chiama una funzione per noi nuova, scanf. (Parleremo di scanf diffusamente in seguito.) Il programma entra quindi in un area di esecuzione condizionale, dove, a seconda del valore di UsersChoice, o chiama la funzione Calculate o la funzione DisplayNames. Infine, quando UsersChoice sarà uguale a 3, viene eseguito il comando return e, come abbiamo imparato, ciò pone termine alla funzione principale (main) e quindi il programma finisce. È importante dove si mette una funzione nel codice? La risposta è sì e no. Per illustrarlo creiamo un altro progetto. Eseguiamo le solite operazioni per creare il nuovo progetto chiamato PostFunction. Si crea una nuova cartella chiamata PostFunction e vi si salva il progetto. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 DisplayBoringMessage(); 7 system("pause"); 8 return 0; 9 } 10 /*This is a boring function*/ 11 void DisplayBoringMessage() 12 { 13 printf( "This is a boring message\n"); 14 } Prima di compilare questo programma, provate a immaginare cosa succederà durante il funzionamento. Premete <F9>. Si dovrebbe notare che il programma non parte e nella finestra dei messaggi in basso nella IDE, si vedranno i seguenti errori.

64 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 55 di 150 Figura 3.4 Il messaggio di errore. Progredendo nella programmazione di tali messaggi se ne incontreranno parecchi. Ma cos è andato storto? Proviamo ad immaginarlo seguendo i messaggi. La prima riga dice conflicting types for DisplayBoringMessage (Tipi in conflitto per DisplayBoringMessage), che è il nome della nostra funzione quindi vi è qualcosa di sbagliato. Bene, il primo errore si ha alla riga 12 del sorgente. Il messaggio successivo ci dice che nella riga 6 c è una previous implicit declaration of DisplayBoringMessage (precedente dichiarazione implicita di DisplayBoringMessage ). Perché questo? Perché prima di usare una funzione, il C la deve conoscere. Possiamo aggirare l errore Dichiarandone la funzione dicendo al compilatore il nome della funzione, il tipo restituito ed i parametri che prende. Provate ad aggiungere la seguente riga nel codice alla riga 3. void DisplayBoringMessage(); Essendo una dichiarazione finisce con un punto e virgola. Si preme <F9> per compilare ed avviare. Si dovrebbe vedere che ora il programma si compila e gira perfettamente. La riga aggiunta è detta Dichiarazione della funzione ed il codice nelle righe è detto Definizione di una funzione. Quando si include un file di intestazione (header) in pratica si includono dichiarazioni di funzioni come printf in modo da poterle utilizzare. Prima di dare uno sguardo a qualche utile funzione inclusa nella libreria standard del C vediamo le funzioni che accettano un numero variabile di parametri in ingresso. Q uesto tipo di funzione è definita con per dire che la funzione accetta un numero variabile di parametri come argomenti. La funzione deve contenere almeno un parametro conosciuto prima dell elenco variabile di argomenti. Il motivo di questo parametro noto viene spiegato dopo l esempio. La funzione più nota che usa tale formato è la printf. Il prototipo per questo tipo di funzioni è int MyFunction(int AnInteger, float AFloat = 5.4, ); Fin quì tutto bene, ma come si fa a sapere quanti altri argomenti l utente ha passato? E come vi si accede? Per cominciare bisogna includere <stdarg.h> che definisce varie macro necessarie. Diamo prima uno sguardo ad un programma di esempio che usi un numero variabile di parametri poi lo analizzaremo. Facciamo il solito progetto chiamandolo VariableFunction. Si crea una nuova cartella chiamata VariableFunction e vi si salva il progetto. 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdarg.h> 4 5 int AutoSumFunction (int NumberOfArguments,...);

65 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 56 di int main(int argc, char *argv[]) 8 { 9 int Total = 0; 10 Total = AutoSumFunction (6, 12,54,24,75,45,23); 11 printf("the total is %d\n", Total); 12 system("pause"); 13 return 0; 14 } int AutoSumFunction (int NumberOfArguments,...) 17 { 18 int Sum = 0, CurrentValue = 0; 19 va_list ArgumentPointer; /*We need to use va_start to get the start of the 22 argument list and store this in the argument pointer. 23 The macro va_start does this*/ 24 va_start(argumentpointer, NumberOfArguments); /*Now we will create a loop that counts down the number 27 of arguments.*/ 28 for(;numberofarguments;numberofarguments--) 29 { 30 /*We get the next value from the list of arguments, 31 we need to tell va_arg what type of value we expect*/ 32 CurrentValue = va_arg(argumentpointer,int); 33 Sum = Sum + CurrentValue; 34 } /*We must call va_end otherwise the program could crash*/ 37 va_end(argumentpointer); /*Return the total*/ 40 return Sum; 41 } Si preme <F9> per compilare e si spera che l output sia The total is 233. Poi andiamo ad analizzare cosa è avvenuto. Riga 3 - Abbiamo incluso il file header <stdarg.h> che ci da accesso a va_list, va_sta rt, va_arg e va_end. Riga 5 - Abbiamo creato il prototipo della nostra AutoSumFunction. Vi è definito un int come parametro di ritorno che sarà la somma di tutti i suoi argomenti. Essa prende un valore intero, che è il numero di argomenti che le passeremo. Quindi prende qualsiasi numero di altri argomenti. Riga 10 - Usiamo la funzione passandole 6 per dire che le passeremo sei argomenti. Poi le passeremo sei valori interi. Riga 19 - Si usa il tipo di dati va_list per creare un puntatore chiamato ArgumentPointer. Questo è un puntatore che useremo per accedere all elenco di argomenti. Diremo dell altro sui puntatori nella sezione Puntatori. Riga 24 - Chiamiamo la macro va_start passandole il puntatore ArgumentPointer ed il nome della prima variabile NumberOfArguments. Questa inizializza il puntatore affinché punti al primo argomento subito dopo NumberOfArguments.

66 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 57 di 150 Ri ga 28 - Creaiamo un ciclo for che useremo per accedere alla lista di argomenti. Non riempiamo la prima parte del ciclo for dato che NumberOfArguments ha già un valore. Se si ricorda, la seconda parte del ciclo for controlla valori di tipo vero/falso. Qui usiamo NumberOfArguments, in altre parole se NumberOfArguments è uguale a 0 allora ferma il ciclo. L ultima parte del ciclo for decrementa il valore di NumberOfArguments ogni volta di 1. Riga 32 - Assegniamo il valore di ritorno di va_arg a CurrentValue. I parametri di va_arg sono il puntatore ArgumentPointer ed il tipo di dato che ci si aspetta che sia l argomento successivo. Riga 37 - Chiamiamo va_end passandole ArgumentPointer. Sbagliando qui probabilmente il programma va in crash. Abbiamo visto come accedere ad una variabile lista di argomenti, ma cosa rispondere all altra domanda su come si possa sapere di quale tipo siano gli argomenti? Sfortunatamente la risposta è che non lo si può sapere. Ecco perché c è bisogno del primo argomento. Per sperimentarlo proviamo questo: Modifichiamo la riga 10 in Total = AutoSumFunction (6, 12,54,45,23); Quindi avviamo il programma. Si dovrebbe vedere che il risultato è molto diverso dalla somma di 12, 54, 45 & 23. Si potrà sperimentare anche il caso in cui si aggiungano altri argomenti lasciando il primo a 6. ATTENZIONE: La riga 28 è alquanto pericolosa in quanto la usiamo per controllare il valore di NumberOfArguments. Il ciclo si fermerà quando NumberOfArguments sarà uguale a 0. Ma se qualcuno modifica la riga 10 in Total = AutoSumFunction(-6, 12,54,45,23);, allora NumberOfArguments non diventerà mai uguale a zero. Diremo di più sulle funzioni nelle prossime due sezioni, Input/Output ed altre utili funzioni e I Puntatori. Input/Output ed altre utili funzioni All inizio ho detto che il C non contiene parole chiavi che abbiano a che fare con l output sullo schermo mentre invece si sono usate tali funzioni. Finora abbiamo visto due funzioni che si occupano dell input e dell output, printf e scanf. La buona notizia à che se si impara bene il funzionamento di queste due, le altre funzioni di input/output risultano facilissime. Oltre alle funzioni di input/output, vedremo la ricchezza di funzioni del C messe a disposizione del programmatore. Input/Output sullo schermo Output Partiremo dall output, dopotutto è molto più eccitante creare un programma che faccia qualcosa in modo vi sibile, anziché uno in cui si vi si digitano un sacco di cose ma non sembra succedere niente.

67 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 58 di 150 Il C ha tre funzioni di output putchar, puts, printf. Le prime due sono semplici, putchar richiede un argomento di tipo char e lo stampa sullo schermo. Il secondo prende una costante stringa e la stampa sullo schermo. L ultima printf è quella più complessa e la analizzeremo approfonditamente. Il prototipo della funzione printf è: int printf(const char* string, ); Il valore di ritorno di printf o è il numero di caratteri scritti sullo schermo o un valore negativo se c è stato un errore. Il primo argomento di printf è la stringa da mostrare a video. Per esempio: printf( C Programming is amazing ); Si dovrebbe ottenere che la riga C Programming is amazing appaia sul video. Ma cosa dire del secondo argomento, i puntini? Come ci si ricorderà su quanto detto a proposito delle funzioni, questi rappresentano una lista variabile di argomenti. Abbiamo già usato questa funzione nei programme di esempio. Nella stringa passata a printf come primo argomento, possiamo racchiudere le specifiche del formato nei punti in cui si vogliono inserire tali valori. Questi specificatori di formato iniziano con % e vengono usati anche nella funzione scanf. Ogni volta che la funzione incontra un segno di % racchiuso nella stringa, cerca un argomento corrispondente e, a seconda del codice che segue il simbolo di %, preleva l argomento in tale formato. Per esempio: printf("i am %d today and my name is %s",200,"rip Van Winkle\n"); In questo esempio printf scriverà I am poi incontrando il segno % vede cosa segue, in questo caso una d. Ora cerca il primo argomento variabile, che è 200, dato che il formato del codice è d lo em ette come un intero. Poi continua a scrivere today and my name is ancora una volta incontr a un simbolo di % e cerca il segno del formato, in questo caso s quindi formatta il secondo argomento come stringa. Segue una lista di tutti gli specificatori di formato. Codice printf scanf %a Output esadecimale nella forma di 0xh.hhhhp+d (C99) Input di un numero in virgola mobile (C99) %A Output esadecimale nel formato 0xh.hhhhP+d (C99) %c Output di un carattere Input di un carattere %d Output di un intero decimale con segno Input di un intero decimale %e Output in notazione scientifica con e minuscola Input di un numero in virgola mobile %E Output in notazione scientifica con E maiuscola %f Output decimale in virgola mobile Input di un numero in virgola mobile %g Output nell abbreviazione di %e o %f Input di un numero in virgola mobile

68 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 59 di 150 %G Output nell abbreviazione di %E o %f %i Output di un intero decimale con segno Input di un intero decimale, ottale o esadecimale %n Memorizza il numero di caratteri scritti in Memorizza il numero di caratteri letti in un puntatore a intero un puntatore a intero %o Output di un ottale senza segno Input in ottale %p Mostra un puntatore Input di un puntatore %s Ouput di una stringa di caratteri Input di una stringa %u Output di un intero decimale senza segno Input di un intero decimale senza segno %x Output in esadecimale senza segno (minuscolo) Input di un esadecimale %X Output in esadecimale senza segno (maiuscolo) %% Output del segno % Input del segno % %[] Legge un insieme di caratteri Gli specificatori di formato in printf si possono modificare in diversi modi. Questi sono: Ampiezza minima del campo Ponendo un intero tra il segno % ed il codice del formato ci si assicura che l output sia riempita con spazi fino a raggiungere la lunghezza indicata. Se è più lungo di tale lunghezza viene scritto tutto. Precisione dell output Il modificatore dell ampiezza del campo può essere seguito da un punto decimale ed un altro intero. Per i valori in virgola mobile questo indica il numero di posizioni decimali da mostrare. Per le stringhe indica il numero massimo di caratteri mostrati. Per gli interi indica quante cifre vengono mostrate poste a zero per per riempire la differenza Allineamento dell output Per default l output è giustificato a destra, aggiungendo un segno meno dopo il % si può modificare l output affinché sia giustificato a sinistra. Modifica dei tipi long e short Si possono aggiungere i modificatori l per long e h per short agli specificatori di formato d,i,o,u,x ed n per modificarli in tipi di dati long o short. Allo stesso modo si può usare il modificatore L con gli specificatori e,f, e g per indicare un long double. Mostra il separatore decimale Con un segno # dopo % prima di g,g,f,e o E indica che si deve mostrare un segno decimale. Mostra il segno di un esadecimale Con un segno # dopo il % e prima di x o X mostra il prefisso 0x. Precisione variabile dell output Anziché usare il formato %5.4f è possible usare %*.*f. Per ci ascun * printf cercherà il valore da sostituirgli nella lista variabile di argomenti.

69 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 60 di 150 NOTA: Quando abbiamo discusso delle funzioni con un numero variabile di argomenti, abbiamo detto che va_arg deve essere informato sul formato che deve aspettarsi. Questa è la ragione dei diversi specificatori di formato. Ogni volta che printf trova un segno % nella stringa, cerca il successivo argomento variabile e lo restituisce come il tipo visto nella tabella precedente. Se l output da una funzione printf appare strano o da risultati sbagliati, assicuratevi di usare gli specificatori di formato corretti. Assicuratevi, inoltre, di avere lo stesso numero di argomenti degli specificatori di formato. Input In corrispondenza delle tre funzioni di output il C fornisce tre funzioni di input getchar, gets e scanf. Anche qui le prime due sono semplici funzioni, getc har restituisce un char dal buffer di input, gets prende un array stringa (diremo di più sugli array nelle sezioni Puntatori, Allocazione di Memoria, Array e Stringhe ). L ultima funzione scanf è parente di printf una funzione complessa che andremo a esaminare. Il prototipo della funzione scanf è: int scanf(const char* string, ); Il valore di ritorno di scanf è il numero di elementi cui è stato assegnato un valore oppure in caso di errore restituisce EOF. EOF è una costante il cui valore può cambiare da un compilatore ad un altro quindi basta usare il nome della costante EOF. Il primo argomento della funzione scanf è la stringa degli specificatori di formato, per ciascun specificatore di formato si deve includere un argomento che sarà il posto in cui scanf memorizzerà i valori letti dalla tastiera. Funziona in maniera molto simile a printf, la sostanziale differenza è che gli argomenti variabili devono essere tutti degli indirizzi di variabili. Analizzeremo gli indirizzi quand o si discuterà dei puntatori, ma per il momento basterà sapere che significa anteporre il segno & a ciascun argomento. Per esempio: scanf("%d%f%s",&int, &Float,&String); Nella riga precedente scanf legge il primo input dalla tastiera e lo memorizzerà nella variabile Int, il secondo input verrà posto in Float e l input finale in String. Ci sono un paio di pericoli con scanf. Il primo è che in alcune implementazioni bufferizza le righe. Questo vuol dire che se si usa scanf per leggere un solo carattere non succederà nulla finché non si preme [Enter]. Il secondo è che durante la lettura di stringhe, viene letto qualsiasi cosa finché non si incontra un primo carattere spazio vuoto ovvero spazio, tab, tab verticale, salto pagina o salto riga. Per esempio scanf leggerà la riga Welcome friends and Romans come Welcome. Per leggere tutta la riga, inclusi gli spazi, si deve usare gets. Lo specificatore di formato per l insieme di scansione %[] dice a scanf di leggere solo quei caratteri contenuti nell insieme. Per esempio: scanf( %[GgeRhdW],&String); Nell esempio precedente scanf memorizza l input dell utente nella variabile String. Verranno memorizzati solo i caratteri G,g, e,r,h,d,w. Appena scanf incontra un carattere non contenuto nell insieme ferma la lettura. Anche l insieme di scansione è case sensitive quindi G non è lo stesso di g.

70 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 61 di 150 Come printf, scanf supporta vari modificatori di formato e sono i seguenti: Dimensione massima del campo Modificatori del tipo di dati long e short Campo da scartare Inserendo un numero tra il % ed il codice di format si otterrà che vengano letti solo un tale numero di caratteri. Questi sono gli stessi di printf l, h & L. Essi alterano la lunghezza dei tipo di dato. Inserendo un * tra il % ed il codice del formato si avrà che venga letto l input, ma non verrà assegnato a nessuna variabile. Dato che quanto detto può sembrare troppo, creiamo un programma di esempio che usi queste funzionalità. Facciamo i soliti passi per creare un nuovo progetto C. Il progetto lo si chiama InputOutput. Si salva nella cartella InputOutput. Si cambia il codice col seguente 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 char FirstNameString[200]; 7 char LastNameString[200]; 8 int AgeInteger, Count; 9 float MyAgeFloat; 10 printf( "Hello what is your first name\n"); 11 scanf( "%s",&firstnamestring); 12 printf( "\nhello %s, what is your last name?\n", FirstNameString); 13 scanf( "%s",&lastnamestring); 14 printf( "\nso you are %s %s\n", FirstNameString, LastNameString); 15 printf( "How old are you %s\n", FirstNameString); 16 scanf( "%hd", &AgeInteger); 17 MyAgeFloat = AgeInteger + 0.2; 18 printf( "\nthat's funny I am %*.*f\n",4,2,myagefloat); 19 printf( "\nthis is right justified"); 20 printf( "\n%23s\n",firstnamestring); 21 printf( "\nthis is left justified"); 22 printf( "\n%-23s\n\n",lastnamestring); 23 printf( "%s%n contains ",FirstNameString,&Count); 24 printf( "%d characters\n\n",count); 25 system( "PAUSE"); 26 return 0; 27 } Si preme <F9> per compilare e lanciare. L output dovrà somigliare a questo

71 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 62 di 150 Figura 3.5 L output dal programma InputOutput. La maggior parte del programma è autoespicativo le note alle righe sono: Riga 18 Riga 20 Riga 22 Riga 23 Si usa lo specificatore di formato %*.*f. I successivi due argomenti indicano il numero totale di caratteri da mostrare ed il numero di cifre che devono apparire dopo il separatore dei decimali. Indica che l output dobrebbe essere largo almeno 23 caratteri. Con questo il testo verrà giustificato a destra. Indica che l output sarà ampio 23 caratteri ed il segno - lo giustificherà a sinistra. scrive il nome dell utente poi memorizza il numero di caratteri emessi nella variabile Count. Questa verrà usata nella riga successiva per dire quanto sia lungo il nome dell utente. Guardiamo ora cosa mette a disposizione il C per leggere e scrivere file. Input/Output per i File La progettazione del C è stata influenzata da Unix nella cui filosofia c è il concetto che tutto sia un file. Lo si vede nella costruzione delle funzioni di input/output. Ne risulta che le funzioni per leggere e scrivere file sono molto simili a quelle già incontrate. In realtà l output su video e l input da tastiera vengono trattati come file. Questi hanno i nomi predefiniti STDOUT e STDIN. La differenza è che printf, scanf e simili lo usano in modo trasparente. Per leggere e scrivere file bisogna prima aprirli e quando l operazione è conclusa si devono chiudere. Il file header (di intestazione) da includere è <stdio.h> che consente l uso del tipo FILE come un puntatore a file. Per aprire si deve usare la funzione fopen, il prototipo di tale funzione è definito nel modo seguente. FILE * fopen(const char * filename, const char * mode); Se la funzione ha successo il tipo restituito è un puntatore ad una struttura FILE valida. Se fallisce restituisce un puntatore NULL. (Se quanto detto non ha più senso del Klingoniano allora si dia uno sguardo più Avanti alle sezioni Puntatori e Strutture ). Il primo argomento è una

72 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 63 di 150 costante stringa che contiene un nome di file valido o un intero path. Per esempio Readme.txt o C:\\Windows\\Readme.txt. Il secondo argomento è un flag che indica il modo con cui aprire il file. Le scelte possibili sono elencate nella seguente tabella. Flag Significato a r w ab rb wb Apre o crea un file di testo ed accoda alla fine. Apre un file di testo per leggerlo. Crea un file di testo per scriverci. Apre o crea un file binario ed accoda alla fine. Apre un file binario per leggerlo. Crea un file binario per scriverci. a+ Accoda o crea un file di testo per leggere/scrivere. r+ Apre un file di testo per leggerlo o scriverlo. w+ Crea un f ile di testo per leggerlo o scriverlo. a+b r+b w+b Accoda o crea un file binario per leggere e scrivere. Apre un f ile binario per leggerlo o scriverlo. Crea un file binario per leggerlo o scriverlo. Una volta finite le operazioni sul file lo si deve chiudere. Per farlo si deve usare la funzione fclose. Il prototipo di fclose è dichiarato in questo modo. int fclose(file * FilePointer); Se ha successo la funzione fclose restituisce 0 altrimenti EOF. Output Le funzioni di output per i file sono molto simili a quelle di output su console. Sono tanto simili che hanno gli stessi nomi preceduti solo da una f, quindi c è fputc(), fputs() e fprintf(). L altra differenza principale consiste nel fatto che richiedono un puntatore FILE ad un file valido. fprintf() è la sola funzione di cui parleremo. Il suo prototipo è dichiarato così: int fprintf(file * filepointer, const char * string, ) ; Si noterà che oltre all aggiunta del puntatore a FILE, appare esattamente come il prototipo della precedente funzione printf(). Infatti anchessa funziona esattamente allo stesso modo come dimostra il programma di esempio della prossima sezione. Input Come le funzioni descritte nella sezione precedente, quelle di input sono le stesse delle funzioni di inpu t da console solo con una f che precede il nome ed un argomento extra che è un puntatore a un FILE valido. Quindi abbiamo fgetc(), fgets() e fscanf(), anche stavolta parleremo solo di fscanf(). La dichiarazione del prototipo è la seguente: int fscanf(file * filepointer, const char * string, );

73 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 64 di 150 Quindi diamo uno sguardo all esempio sull uso di queste due funzioni fprintf e fscanf. Come al solito Si comincia un nuovo progetto per console in C. Lo si chiama SingleFile. Lo si salva in una propria cartella di nome SingleFile. Si sostituisce il sorgente generato col seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 char Name[100]; 7 int Age; 8 char NameFromFile[100]; 9 int AgeFromFile; FILE * OurFile; /*Demonstrate that we can read and write to and from the console 14 using fprintf and fscanf with the pointers stdout and stdin*/ 15 fprintf(stdout, "Please enter your first name and your age\n"); 16 fscanf(stdin, "%s%d", Name, &Age); /*Try to open a file to write to, check it is valid*/ 19 if((ourfile = fopen("test.txt", "w")) == NULL) 20 { 21 /*If the file pointer is NULL complain and exit*/ 22 fprintf(stdout,"sorry but I can't open a file to write to\n\n"); 23 exit(1); 24 } fprintf(stdout,"\nwriting your information to file\n"); 27 /*Use the OurFile pointer to write information to the file*/ 28 fprintf(ourfile, "%s %d", Name, Age); 29 /*Close the file now we have finished with it*/ 30 fclose(ourfile); /*Try to open a file to read from, check it is valid*/ 33 if((ourfile = fopen("test.txt", "r")) == NULL) 34 { 35 /*If the file pointer is NULL complain and exit*/ 36 fprintf(stdout,"sorry but I can't open a file to read from\n\n"); 37 exit(1); 38 } fprintf(stdout,"reading your information from file\n"); 41 /*Use the OurFile pointer to read information from a file*/ 42 fscanf(ourfile,"%s%d", NameFromFile, &AgeFromFile); 43 fclose(ourfile); fprintf(stdout,"\nyour name is %s, ", NameFromFile); 46 fprintf(stdout,"and your age is %d\n", AgeFromFile); system("pause"); 49 return 0; 50 } Si compila e si lancia.

74 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 65 di 150 Una parte di questo programma dovrebbe essere abbastanza ovvia, visti i programmi usati per testare printf e scanf. Ma analizzeremo le righe che differiscono. Riga 15 - L effetto di questa riga è lo stesso di usare printf ma solo che si usa fprintf ed il puntatore chiamato stdout. Tale puntatore, come abbiamo detto in precedenza, scrive direttamente sulla console. Riga 16 - Questa riga fa lo stesso della 15 ma usa fscanf assieme al puntatore stdin per sostituire scanf. Riga 19 - Usiamo la funzione fopen per tentare di aprire un file chiamato Test.txt per poterlo scrivere. Confrontiamo il valore del puntature restituito col valore NULL. Se coincidono c è stato un errore durante l apertura del file e non possiamo usarlo. Riga 23 Se il puntatore del file è NULL si chiama la funzione exit col valore 1. Con questo si termina il programma segnalando che si è verificato un errore. Riga 28 Scriviamo nel file i valori presi in precedenza. Riga 30 Chiudiamo il file appena finito di usarlo. Riga 42 Rileggiamo i valori dal file, per provare che variabili. Riga 43 Ancora una volta chiudiamo il file quando abbiamo finito. non sono quelli in memoria usiamo altre Anche se fscanf e fprintf sono molto potenti e facili da usare non sono molto efficienti, dato che implicano la conversione da binario a caratteri. Per grandi quantità di dati da leggere o scrivere ci sono scelte migliori che verranno brevemente menzionate nella prossima sezione, ma vanno oltre o scopo di questo libro. Altre funzioni per la gestione dei file Le routine per la gestione dei file sono solo la punta dell iceberg. Se siete interessati (e so che lo siete) allora fate i compiti a casa e studiatevi fseek, ftell, feof, ferror, rewind, remove, fflush, fread e fwrite. Tali funzioni ampliano le possibilità del C nella gestione dei file oltre la semplice lettura e scrittura di file di testo. Alcune delle altre utili funzioni La tabella seguente elenca alcune delle altre utili funzioni del C. Varie funzioni Contenute in <stdlib.h> double atof(const char* str) int atoi(const char* str) long int atoll(const char* str) int rand(void) void srand(unsigned int seed) Converte la stringa str in un double che restituisce. Come sopra ma converte un valore intero. Come sopra ma per un intero long. Restituisce un numero casuale tra zero e RAND_MAX (che è almeno 32767). Imposta un punto di partenza per la funzione rand.

75 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 66 di 150 Ci sono molte altre funzioni contenute nell ambito dei file header di cui non abbiamo parlato. Sarebbe bene scoprire cosa è disponibile, anche se è un po noioso, ma si eviterà di riscrivere una funzione già pronta. Puntatori Finora abbiamo citato i puntatori un paio di volte ed in effetti è quasi impossibile parlare del C senza menzionare i puntatori. Questi costituiscono uno dei maggiori punti di forza del C. Sfortunatamente costituiscono anche un grande pericolo per la programmazione in C. Quindi che cos è un puntatore? La memoria in un computer è come un unica lunga strada. Lungo la strada ci sono abitazioni. Ogni casa contiene un po di dati. Quindi come si può localizzare un certo dato. Beh ogni casa ha un indirizzo quindi usiamo tale indirizzo per individuare il dato. Per alcuni edifici importanti ci può essere un segno che identifichi tale edificio con un nome. Un puntatore C è esattamente lo stesso. Il segno è la variabile, e il valore che contiene è l indirizzo di partenza del dato, all interno della memoria del computer. Per definire una variabile come puntatore si usa un * dopo la definizione del tipo e prima del nome della variabile. Per esempio: int * MyIntPointer; Ma come ottenere l indirizzo di un pezzo di dato cui puntare? L operatore & posto prima del nome della variabile restituisce l indirizzo dei dati di tale variabile. Un esempio d uso lo abbiamo visto nella funzione scanf. Il più delle volte, però, non si vuol sapere dove venga memorizzato il dato, mentre risulta più interessante sapere cosa vi sia memorizzato. Per recuperare il valore immagazzinato all indirizzo cui si riferisce un puntatore si può usare l operatore *. Per esempio: int AnInteger = *MyIntPointer; Questo assegna il valore referenziato da MyIntPointer alla variabile AnInteger. ATTENZIONE: Come ogni variabile in C quando si definisce un puntatore come sopra esso punterà ad un valore a caso quindo è buona norma assegnarvi un valore nel definirlo. Avendo un valore cui puntare lo si può definire in questo modo int * MyIntPointer = &AnInteger; Altrimenti gli si può assegnare il valore NULL. int * MyIntPointer = NULL; Si usa NULL quanto garantisce che punti a niente. La maggior parte delle funzioni che restituisce un p untatore ad una porzione di memoria, restituirà NULL in caso di errore. In questo caso è necessario controllare il valore di ritorno del puntatore prima di usarlo. I puntatori non inizializzati sono una causa comune di errori nella programmazione in C. Il meglio che ci si possa aspettare è un output strano. Il peggio è il blocco del programma o, su vecchi sistemi operativi, il blocco del computer. Il motivo è che si sta operando nella memoria appartenente ad un

76 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 67 di 150 altra parte del programma addirittura di un altro programma. Questi sono problemi molto difficili da risolvere. Come già visto si possono usare i puntatori per puntare a variabili già dichiarate. Si possono usare puntatori per allocare nuova memoria, come vedremo nella prossima sezione. Per mostrare l uso dei puntatori e dei diversi operatori che li usano, creiamo un altro programma di esempio. Al solito Se crea un nuovo progetto C. Lo si chiama Pointy. Lo si salva in una nuova cartella chiamata Pointy. Si cambia il codice generato con quello seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 int Number1 = 5, Number2 = 12, Total = 0; 7 int * MyIntPointer; 8 9 /*Use MyIntPointer to reference Total. We need to use '&'*/ 10 MyIntPointer = &Total; 11 /*Use MyIntPointer to display value and location of variable Total*/ 12 printf("the value of Total = %d.\n", *MyIntPointer); 13 printf("the Location of Total is %d\n", MyIntPointer); 14 /*Use MyIntPointer to alter the value of Total*/ 15 *MyIntPointer = Number1 * Number2; 16 /*Display the location and value of Total 17 displaying that MyIntPointer changed it*/ 18 printf("the value of Total = %d.\n", Total); 19 printf("the location of Total is %d\n", &Total); system("pause"); 22 return 0; 23 } Questo programma mostra l uso dei puntatori per modificare il valore contenuto in una locazione di memoria. Al momento, le righe fino alla 9, dovrebbero esservi chiare. Prendiamo in considerazione alcune delle altre righe. Riga 10 - Usa l operatore indirizzo & per assegnare l indirizzo della variabile Total al puntatore MyIntPointer. Riga 12 - Usa l operatore * per stampare il valore contenuto nella locazione di memoria puntata da MyIntPointer. Riga 13 Stampa il valore di MyIntPointer che è la locazione di memoria di Total. Riga 15 Assegna il valore di Number1 * Number2 alla locazione di memoria puntata da MyIntPointer. Riga 18 - Stampa il valore di Total mostrando che è stato modificato tramite MyIntPointer.

77 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 68 di 150 Ne sapremo di più sui puntatori nelle seguenti sezioni Allocazione di Memoria, Array e Stringhe. Allocazione di Memoria Nella programmazione C viene fatta una distinzione a seconda di come sia stata allocata la memoria usata. Ci sono due termini usati lo stack e lo heap. Non è fondamentale conoscerli ma sono termini che si incontreranno spesso quindi è utile capirne la differenza. Appena viene eseguito il programma alloca memoria dallo stack. Ogni chiamata di funzione viene p osta nella memoria dello stack, anche tutte le variabili dichiarate nella funzione vengono messe nello stack. Appena la funzione termina si rimuove dallo stack e tutte le variabili locali alla funzione vengono distrutte (come ci si ricorderà dalla discussione sulla visibilità o scope). Talvolta si vogliono memorizzare i dati in una funzione per poi riutilizzarli in seguito. Se questa informazione venisse posta sullo stack verrebbe distrutta al ritorno dalla funzione. Per evitarlo è possibile allocare della memoria su quello che è chiamato heap. È responsabilità del programmatore decidere quando la memoria richiesta allo heap debba essere creata e distrutta. Il C fornisce una libreria di funzioni dedicate all allocazione ed alla distruzione della memoria. Vediamole subito. Il file di intestazione (header) da includere per usare queste funzioni è <stdlib.h>. Ci sono quattro funzioni che si possono usare malloc, calloc, realloc e free. Le vediamo una alla volta. malloc Il prototipo della funzione è void* malloc(size_t SizeInBytes); Per usare la funzione è necessario indicare la quantità di memoria che desidera richiedere, malloc quindi restituisce un puntatore che referenziala locazione di tale memoria. Questo è un puntatore ais void di cui si deve fare il cast al tipo corretto da usare. Se la funzione non è in grado di allocare la memoria voluta, restituisce un puntatore a NULL. Per esempio: int * MyIntPointer = NULL; MyIntPointer = (int*) malloc(sizeof(int)); If(MyIntPointer)... Prima si dichiara MyIntPointer ad essere un puntatore ad un tipo int, e gli si assegna il valore NULL. Poi si usa malloc e si richiede della memoria della stessa dimensione di un int. Eseguiamo il cast del puntatore restituito da malloc dal tipo void a int. Quindi lo si assegna a MyIntPointer. Infine si controlla che MyIntPointer non punti a NULL prima di usarlo. calloc La memoria restituita da malloc contiene valori casuali. calloc ne inizializza tutti i bit a zero. Il prototipo di calloc differisce da malloc ed è dichiarato così: void * calloc (size_t Number, size_t Size); Per usare calloc si deve indicare il numero di unità volute e la dimensione di tali unità. Per esempio: int * MyIntPointer = NULL;

78 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 69 di 150 MyIntPointer = (int*) calloc(1,sizeof(int)); If(MyIntPointer)... Questo è lo stesso esempio di quello di malloc la differenza è che si fa una richiesta per una unità della dimensione di un int. La memoria restituita verrà impostata a zero. realloc Talvolta si trova che la memoria allocata non è sufficiente e se ne vuole dell altra, qui è dove occorre realloc. Il prototipo per realloc è void * realloc(void * ExistingPointer, size_t SizeInBytes); Per usare realloc si deve usare il puntatore al blocco di memoria esistente. Seguito dalla dimensione di cui abbiamo bisogno per il nuovo blocco. realloc restituisce un puntatore al nuovo blocco di memoria. Inoltre potrà essere NULL se c è stato un errore. free Una volta finito di operare con la memoria creata con le funzioni precedenti, la si deve liberare. Lo si può fare con la funzione free. Il prototipo per free è dichiarato come void free(void * ptr); free si chiama col puntatore restituito da una delle operazioni precedenti. ATTENZIONE: È vitale liberare tutta la memoria precedetemente allocata. Altrimenti quando il programma finisce tale memoria resta allocata. Questa porzione di memoria non verrà più liberata per essere utilizzata da altri programmi. Questo è detto memory leak. In situazioni con poca memoria, dei programmi con memory leaks possono provocare il blocco dei sistemi operativi. Array Un array è un blocco di memoria consistente di un numero di unità di dati dello stesso tipo. Ci sono molti casi in cui ha senso usare gli array. Per esempio per memorizzare le età dei membri della propria famiglia. Lo si può fare creando una nuova variabile per ogni membro. Per es. int Member1 = 34, Member2 = 54, Member3 = 23; Per stampare l elenco delle età si potrebbe fare così prinf( Member 1 = %d, Member 2 = %d, Member 3 = %d, Member1,Member2,Member3); Questo va bene per pochi familiari. Ma cosa succede se si ha una famiglia numerosa? L istruzione printf diventa ingombrante. La risposta è un array. Un array viene definito allo stesso modo di una variabile, la differenza è che dopo il nome della variabile si deve ra cchiudere il numero di unità tra le parentesi quadre []. Per esempio: int FamilyMembers [10]; Questo vi darebbe un array di 10 interi chiamato FamilyMembers. Un array non è molto utile se non si può riempire con dei valori e rileggerli. Quindi come riempirlo? Il primo modo consiste

79 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 70 di 150 nel riempirlo nella dichiarazione, per farlo si mette il segno = dopo le parentesi quadre e poi si immette l elenco dei valori tra le parentesi graffe {}. Per esempio: int FamilyMembers[3] = {24,54,63}; Questo viene detto inizializzazione dell array. Nell inizializzazione dell array è anche possibile ometterne la dimensione tra le parentesi quadre. Automaticamente il compilatore ne dedurrà la dimensione dal numero e questo per grossi array o stringhe è una benedizione. Alternativamente si può riempire ciascuna sezione dell array riferendosi ad essa tramite il suo numero d indice. Un punto importante è che in C gli array cominciano con l indice 0. Quindi nel precedente esempio FamilyMembers inizia all indice 0 e finisce all indice 2. Quindi ci si può riferire in questo modo: FamilyMembers[1] = 45; printf( Uncle Fred is %d years old,familymembers[1]); Quello che non è immediatamente chiaro è che tutti gli array in C implicano l uso dei puntatori, questo perché il nome dell array è appunto un puntatore alla locazione di memoria del primo eleme nto dell array. Quindi quanto sopra si può riscrivere come: *(FamilyMembers + 1) = 45; printf( Uncle Fred is %d years old,*(familymembers + 1)); Cerchiamo quindi di seguire un programma di esempio che mostra l uso di array e puntatori. Come al solito Si crea un nuovo progetto C. Lo si chiama TodaysArray. Lo si salva in una cartella chiamata TodaysArray. Si sostituisce il codice col seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 /*Create a define for our array size*/ 5 #define DAYS_IN_A_WEEK int main(int argc, char *argv[]) 8 { 9 /*Create array and fill it*/ 10 int TodaysLuckyNumber[DAYS_IN_A_WEEK] = {35,64,23,86,23,12,43}; 11 int ArrayIndex = 0; /*Loop through array and print out the days lucky number*/ 14 for(;arrayindex < DAYS_IN_A_WEEK; ArrayIndex++) 15 printf("for day number %d the lucky number is %d\n", 16 ArrayIndex + 1,TodaysLuckyNumber[ArrayIndex]); /*Reset the index*/ 19 ArrayIndex = 0; 20 /*Print a new line*/ 21 printf("\n"); /*Now do it all again using pointers*/ 24 for(;arrayindex < DAYS_IN_A_WEEK; ArrayIndex++) 25 printf("for day number %d the lucky number is %d\n", 26 ArrayIndex + 1,*(TodaysLuckyNumber + ArrayIndex)); system("pause");

80 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 71 di return 0; 30 } Come a l solito estraiamo le righe che ci interessano. Riga 5 - Si definisce un valore costante da usare nella creazione dell array e nel ciclo che ne indicizza i vari elementi. Il bello è che se si deve ridimensionare l array basta cambiare il valore della costante, questa ci aiuta anche a rendere il programma autoesplicativo. Riga 10 Si crea un array di interi chiamato TodaysLuckyNumber. Contemporaneamente lo si riempie. Riga 14 Si crea un ciclo for con la prima parte vuota in quanto abbiamo già inizializzato ArrayIndex a 0. Si controlla se ArrayIndex è inferiore a DAYS_IN_A_WEEK ricordandosi che l array parte da 0 e finisce alla sua dimensione 1. Riga 16 Stampiamo il valore dell indice più uno, e il valore contenuto in TodaysLuckyNumber[index]. Riga 26 Si ripetono le azioni della riga 16 con la differenza che nella seconda parte si usa il nome della variabile come puntatore. Si usa * per ottenere il valore da TodaysLuckyNumber. Si aggiunge ArrayIndex al valore di TodaysLuckyNumber per spostare il puntamento. Questo lo si deve racchiudere tra parentesi tonde altrimenti si aggiungerebbe il valore di ArrayIndex al contenuto di TodaysLuckyNumber (ricordatevi della precedenza degli operatori). È possibile creare array di 2, 3 o più dimensioni, ma questo va oltre lo scopo di questo libro. Se siete interessati ci sono molte eccellenti risorse su Internet che vi possono aiutare. La discussione sugli array ci porta a prendere in esame la gestione delle stringhe in C. Stringhe La gestione delle stringhe in C è da molti considerato il suo punto debole. La ragione principale è che tali stringhe sono implementate utilizzando gli array di tipo char. Questo differisce da altri linguaggi di programmazione che considerano le stringhe un tipo di dato a se stante. Ne risulta che le stringhe sono solo imbastite e richiedono delle funzioni per farci le operazioni basilari. Abbiamo visto nella sezione precedente come dichiarare e contemporaneamente inizializzare gli array, si può fare lo stesso con le stringhe. Ci si ricordi che la stringa è solo un array di caratteri. Quindi la possiamo inizializzare in questo modo: char MyString[] = {'I',' ','a','m',' ','b','o','r','e','d','\ 0'}; Wow! Che cosa lunga e contorta. Ci dev essere un modo più semplice per inizializzare le stringhe. Fortunatamente c è. L esempio sopra si può dichiarare ed inizializzare in un modo più umano : char MyString[] = I am bored ; Ah, ma aspetta un momento, quelle due righe non hanno lo stesso significato! La prima ha un \0 alla fine mentre la seconda no. Lo \0 finale è il terminatore nullo. Questo dice alle funzioni che trattano le stringhe quando questa finisce. Viene omesso nella seconda riga perché usando la

81 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 72 di 150 forma abbreviata il metodo di inizializzazione aggiunge automaticamente il null alla fine. Quindi il secondo metodo non è soltanto più facile, ma più rapido, intelligente e lava i piatti. Cosa si può fare con le stringhe? Abbiamo già visto che le possiamo stampare e leggerle. Tuttavia usando le varie funzioni che ci sono possiamo farci di tutto. Possiamo confrontare stringhe, aggiungerle ad altre stringhe, calcolarne la lunghezza ed altro ancora. La tabella seguente mostra alcune delle funzioni per operare sulle stringhe e sui caratteri coi relativi file di intestazione in cui sono contenute. Funzioni su stringhe Contenute in <string.h> char * strcpy (char * str1, const char * str2) Copia str2 in str1. str2 deve terminare col null. char * strcat (char * str1, const char * str2) char * strchr (const char * str, int ch) int strcmp (const char * str1, const char * str2) size_t strlen (const char * str) char * strstr (const char * str1, const char * str2) Accoda str2 a str1 ed aggiunge un terminatore null, ci si deve assicurare che str1 sia abbastanza lunga per fare ciò Restituisce un puntatore a char alla prima occorrenza del carattere ch nella stringa str Confronta str1 con str2. Restituisce uno zero se le stringhe sono identiche, un valore negativo se str1 è inferiore a str2 ed un numero positivo se str1 è maggiore di str2 Restituisce un intero contenente la lunghezza della stringa str terminata con null. Il terminatore non viene conteggiato. Restituisce un puntatore a char alla prima occorrenza della stringa str2 nella stringa str1 Funzioni su caratteri Contenute in <ctype.h> int isalnum(int ch) int isalpha(int ch) Restituisce un valore diverso da zero se il carattere ch è una lettera o un numero. Restituisce un valore diverso da zero se il

82 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 73 di 150 carattere ch è una lettera int isspace(int ch) int isdigit(int ch) int isupper(int ch) int islower(int ch) int ispunct(int ch) int tolower(int ch) int toupper(intch) Restituisce un valore diverso da zero se il carattere ch è uno spazio bianco. Per es. tab, spazio, ecc Restituisce un valore diverso da zero se il carattere ch è un numero Restituisce un valore diverso da zero se il carattere ch è una lettera maiuscola Restituisce un valore diverso da zero se il carattere ch è una lettera minuscola Restituisce un valore diverso da zero se il carattere ch è un segno di punteggiatura. Per es.! o? Restituisce l equivalente minuscolo del carattere ch Restituisce l equivalente maiuscolo del carattere ch Ci occuperemo di un breve esempio d uso eseguiamo le seguenti operazioni: di tali funzioni. Q uindi avviamo wxdev- C++ ed Si crea un nuovo progetto C Lo si chiama MyStringThing Si crea una nuova cartella chiamandola MyStringThing Vi si salva il progetto Si sostituisce il codice generato col seguente 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <ctype.h> 4 #include <string.h> 5 6 int main( int argc, char *argv[]) 7 { 8 /*Declare and initialise our variables*/ 9 char FirstName[50] = ""; 10 char SecondName[50] = ""; 11 char FullName[110] = ""; 12 int LoopIndex = 0; 13 int UpperCase = 0; 14 int LowerCase = 0; 15 int Punctuation = 0;

83 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 74 di printf("please enter your first name\n"); 18 scanf("%s",firstname); 19 printf("please enter your family name\n"); 20 scanf("%s",secondname); /*Copy FirstName into FullName*/ 23 strcpy(fullname,firstname); 24 /*Use strcat to add a space after first name*/ 25 strcat(fullname," "); 26 /*Use strcat to append the FamilyName*/ 27 strcat(fullname,secondname); printf("\nyour full name is %s\n",fullname); 30 printf("your first name is %d characters long\n",strlen(firstname)); /*Loop through each letter in the string and keep a count of 33 upper and lower case letters plus punctuation marks*/ 34 for(loopindex = 0; LoopIndex < strlen(fullname); LoopIndex++) 35 { 36 if(islower(fullname[loopindex])) 37 LowerCase++; 38 else if (isupper(fullname[loopindex])) 39 UpperCase++; 40 if(ispunct(fullname[loopindex])) 41 Punctuation++; 42 } printf("\nyour full name contains:\n"); 45 printf("%-3d Lower case letters\n",lowercase); 46 printf("%-3d Upper case letters\n",uppercase); 47 printf("%-3d Punctuation mark",punctuation); /*use the shorthand if?: to add an s to the end of the previous 50 output if punctuation equals anything other than 1*/ 51 printf("%c\n\n",punctuation == 1?' ':'s'); system("pause"); 54 return 0; 55 } Si compila e si avvia il programma. Si dovrebbe ricevere un output come il seguente Figura 3.6 L output del programma MyStringThing. Analizziamolo come al solito (il programma)

84 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 75 di 150 Riga 3 - Riga 4 - Riga 23 - Riga 25 - Riga 26 - Riga 30 - Riga 34 - Riga 36 - Riga 38 - Riga 40 - Riga 51 - Si include il nuovo file di intestazione <ctype.h> contenente le funzioni di gestione dei caratteri. Si include il file <string.h> che contiene le funzioni di gestione delle stringhe. Si usa la funzione strcpy per copiare il contenuto della stringa FirstName nella stringa FullName. Si usa la funzione strcat per accodare la stringa costante alla fine della stringa FullName ponendo uno spazio tra il nome ed il cognome. Si usa la funzione strcat per aggiungere il contenuto della stringa FamilyName alla fine della stringa FullName. Si usa la funzione strlen per stampare la lunghezza del nome. Si avvia un ciclo for per vedere la stringa carattere per carattere. Si usa la funzione islower per vedere se il carattere è minuscolo o meno. Se il carattere non è minuscolo si usa la funzione isupper per vedere se è maiuscolo o meno. Si usa la funzione ispunct per vedere se il carattere è un segno di punteggiatura o meno. Si usa l operatore if abbreviato?: per stampare una s [ndt: per il plurale] dopo il segno di punteggiatura se ce ne sono più di uno, rendendo il programma un po professionale. più Ora qualcosa di diverso, la creazione di un proprio tipo di dato. Consideriamo la creazione di tipi di dati che consistono in diversi pezzi di dato nella prossima sezione Strutture. Strutture Finora abbiamo visto come usare gli array per mettere assieme pezzi di dati dello stesso tipo. Ma per quanto riguarda il raggruppamento di elementi di tipo diverso? Per questo il C fornisce le strutture. Ci sono molti usi per le strutture. Uno di questi è quello di aggirare la limitazione che le funzioni possono restituire un dato di un solo tipo. Creando tale dato come struttura, si possono restituire più elementi contemporaneamente. Per creare una struttura bisogna usare l omonima parola chiave struct. struct Abbiamo già incontrato una struttura quando abbiamo avuto a che fare con l input/output dei file. Il tipo FILE è in effetti una struttura. Oltre la parola chiave struct bisogna avere un nome cui riferirsi e dei dati membri. Un esempio di struttura è la seguente. struct CarDetails { int Age; char Model[30]; char Registration[10]; };

85 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 76 di 150 Dopo la parola chiave struct viene il nome della struttura quindi, dentro le parentesi graffe {} la struttura dei membri. Se si conosce la programmazione in Pascal o i database la struttura corrisponde ad un record ed i membri ai campi. Siamo in grado di usare la struttura come tipo di dato con l unica avvertenza che si deve usare la parola struct davanti ad essa. Per esempio per usare l esempio sopra dobbiamo scrivere come segue: struct CarDetails MyCarDetails; Nell esempio sopra creiamo una nuova struttura chiamata MyCarDetails. Ma avendo creato la nuova struttura come accediamo ai membri? Questo viene fatto con l operatore punto.. Per esempio: MyCarDetails.Age = 10; printf( My car is %d years old\n,mycardetails.age); Finora tutto bene. Tuttavia, se alla struttura ci si riferisce tramite un puntatore il metodo per accedere ai membri varia. Nel caso si usa -> anziché.. Per esempio: struct CarDetails ACarDetails; struct CarDetails * MyCarDetails = &ACarDetails; MyCarDetails->Age = 10; printf( My car is %d years old\n,mycardetails- >Age); È anche possibile usare l operatore punto. coi puntatori ma con la seguente notazione. (*MyCarDetails).Age = 10; Data le regole sull ordine di precedenza è necessario usare le parentesi tonde per aggirare * MyCarDetails. Anche se la struttura è diventata come un tipo definito dall utente non è proprio la stessa cosa in quanto si deve anteporre la parola chiave struct al nome della struttura quando se ne vuole creare una nuova istanza. Tuttavia facendo uso di un altra parola chiave del C, typedef possiamo aggirare questa limitazione. typedef viene usato per assegnare un altro nome ad un tipo di dato, per esempio typedef int MyInt; Questo consente di usare MyInt come tipo di dato. Lo possiamo accoppiare con le strutture nel modo seguente. typedef struct { int Age; char Model[30] ; char Registration[10]; }CarDetails; CarDetails MyCarDetails; MyCarDetails.Age = 10;

86 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 77 di 150 Questo ci consente di usare la struttura allo stesso come un qualsiasi altro tipo di dato. Oltre la struttura il C fornisce un opzione simile detta union. union La union appare esattamente come una struttura, la differenza è che nella union ciascun membro occupa la stessa area di memoria, quindi in una union si può usare un solo membro per volta. Pertanto, mentre la dimensione di una struttura è la somma di quella dei suoi membri, la dimensione di una union è quella del membro più grande. Una union serve per diversi scopi, uno dei quali è risparmiare memoria quando si deve operare su un solo membro per volta. Per il resto la union si usa come una struttura. Un esempio è il seguente: Se non chiave typedef union { int Age; char Model[30]; char Registration[10]; }CarDetails; CarDetails MyCarDetails; MyCarDetails.Age = 10; avessimo usato typedef avremmo dovuto mettere il nome CarDetails dopo la parola union ed anteporre la parola chiave union prima di CarDetails MyCarDetails;. NOTA: Questa restrizione è stata rimossa nel C++, quindi quanto sopra lo si può fare in C++ senza ricorrere a typedef e la struttura funzionerà come qualsiasi altro tipo di dato. Per darvi un idea delle strutture e delle union creiamo un programma di esempio. Come al solito Si crea un nuovo progetto C Lo si chiama UnitedStructures Lo si salva in una cartella propria chiamata UnitedStructures Si cambia il codice generato col seguente. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef struct 5 { 6 int NumberOfCows; 7 int NumberOfSheep; 8 int NumberOfPigs; 9 }FarmYardStruct; typedef union 12 { 13 int NumberOfCows; 14 int NumberOfSheep; 15 int NumberOfPigs; 16 }FarmYardUnion; int main(int argc, char *argv[]) 19 { 20 /*Create a structure*/ 21 FarmYardStruct OldMacsFarm; 22 /*Create a union*/ 23 FarmYardUnion YoungMacsFarm; 24

87 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 78 di /*Fill the members of OldMacdonaldsFarm structure*/ 26 OldMacsFarm.NumberOfCows = 12; 27 OldMacsFarm.NumberOfSheep = 54; 28 OldMacsFarm.NumberOfPigs = 6; /*Fill the members of YoungMacdonaldsFarm union*/ 31 YoungMacsFarm.NumberOfCows = 12; 32 YoungMacsFarm.NumberOfSheep = 54; 33 YoungMacsFarm.NumberOfPigs = 6; /*Lets tell the world all about the Macdonalds*/ 36 printf("old Macdonald had a farm\n"); 37 printf("on that farm he had %d cows\n",oldmacsfarm.numberofcows); 38 printf("and on that farm he had %d sheep\ n",oldmacsfarm.numberofsheep); 39 printf("and on that farm he had %d pigs\n\n",oldmacsfarm.numberofpigs); printf("young Macdonald also had a farm\n"); 42 printf("on that farm he had %d cows\n",youngmacsfarm.numberofcows); 43 printf("and on that farm he had %d sheep\n",youngmacsfarm.numberofsheep); 44 printf("and on that farm he had %d pigs\n\n",youngmacsfarm.numberofpigs); /*Print out the sizes of the structure compared to the union*/ 47 printf("sizeof Farmyard struct is %d\n",sizeof(farmyardstruct)); 48 printf("sizeof Farmyard union is %d\n",sizeof(farmyardunion)); system("pause"); 51 return 0; 52 } Come al solito lo si compila e si esegue. Si dovrebbe ottenere qualcosa di simile. Figura 3.7 L output dal programma UnitedStructures Allora perché non c è alcuna differenza tra la fattoria di Old Macdonald e quella di Young Macdonald? La differenza è che i dettagli della fattoria di Young Macdonald sono contenuti in una union. Dato che il numero di animali viene scritto in ciascun membro, esso sovrascrive il valore precedentemente assegnato in quanto tutti i membri condividono lo stesso spazio di memoria.

88 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 79 di 150 Questo è mostrato alle righe 47 & 48. La dimensione di FarmYardStruct è 2 o 3 volte la dimensione di un intero. Mentre la dimensione di FarmYardUnion è 4 volte quella di un solo intero. enum Anche se la enum non appartiene alle strutture, fornisce un altro modo per crere dei propri tipi di dati e viene dichiarata allo stesso modo. Un esempio di enum è il seguente: enum Monsters { Godzilla, KingKong, Predator, Alien, GeorgeClooney }; Quello sopra è un elenco di costanti intere. Il primo Godzilla è il numero 0 e tutti gli altri è pari al precedente più uno. Ora si può usare l etichetta Monster come tipo di dato, per es. enum Monsters MyMonster; MyMonster = Godzilla; È anche possibile inizializzare i valori di ciascuno di essi o di tutti. Per es. enum Monsters {Godzilla = 5, KingKong, Predator = 12, Alien}; In questo caso Godzilla vale 5, KingKong dato che è successivo nella sequenza ha il valore 6, Predator vale 12 ed Alien 13. Le enumerazioni sono ampiamente usate nei comandi switch per migliorare la leggibilità da parte degli umani del codice. Per esempio: switch (MyMonster) { case Godzilla: printf( Hey what a cool monster\n ); break; case KingKong: printf( He s not so scary\n ); break; case Predator: printf( Now you re talking\n ); break; case Alien: printf( Now I am getting worried\n ); break; case GeorgeClooney: printf( Agh, keep it away from me!\n ); break; default: printf( No body is scared of the default monster\n ); } Questo ci porta alla fine della discussione sulle strutture ed anche alla fine della discussione sulla programmazione in C, ora siete ben messi ed avviati nella schiera dei programmatori in C. Sommario Con questo si conclude il nostro brevissimo tutorial sulla programmazione in C. Abbiamo preso in considerazione i tipi di dati base, le parole chiavi più comuni ed alcune delle tante funzioni disponibili nelle librerie standard. Questo non copre tutta la programmazione C e se siete arrivati fin qui probabilmente vorrete andare oltre. La parte 4 di questo libro ed in particolare la sezione Risorse vi indicheranno le innumerevoli risorse disponibili e basate su web che vi consentiranno di continuare lo studio.

89 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 80 di 150 Ora si continua con l evoluzione del C, il C++, in cui sono state aggiunte al C molte funzionalità per renderlo più adatto al paradigma della programmazione orientata agli oggetti. Per saperne di più basta continuare col prossimo capitolo Fondamenti di Programmazione C++.

90 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 81 di 150 Capitolo 4 Fondamenti di Programmazione C++ Introduzione La vita del C++ è cominciata come miglioria del C. Il nome deriva dall operatore di incremento del C ++, mostrando che il C++ è il successore del C. Fu progettato da Bjarne Stroustrup mentre lavorava presso i Bell Labs. Stroustrup ha voluto rendere il C più adatto alla programmazione di grandi applicazioni. È stato influenzato dalle funzionalità che si trovano in altri linguaggi, particolarmente dall Orientamento agli Oggetti. (Daremo uno sguardo all Object Oriented nella sezione Classi ). Il C++ migliora il C principalmente in due modi. Primo, con delle aggiunte al linguaggio. Ora il C++ ha 62 parole chiavi, quelle extra implementano le nuove funzionalità alcune delle quali sono rientrate nel C99. In secondo luogo modificando le librerie. Il C++ introduce delle nuove librerie di Input/Output, i namespace e soprattutto le STL (Standard Template Libraries). Il C++ è come il C accresciuto nel linguaggio e ci sono diversi standard che sono stati adottati e pubblicati. Il primo è stato nel 1998 ed il secondo nel 2003 diverse funzionalità disponibili nell ultimo standard come le STL non sono disponibili nello standard del Al momento è allo studio il nuovo standard C++0X. Il C++ introduce le seguenti funzionalità. I commenti su una sola riga cominciano con //. Spazio nomi per creare l incapsulamento. Le Classi per consentire la programmazione Orientata agli Oggetti. Allocazione e rilascio della memoria con new/delete. Sovrapposizione (Overloading) di funzioni ed operatori. Gestione degli errori, template e RTTI (RunTime Type Identification). Ci sono molte altre modifiche ma per le quali non abbiamo spazio. Uno dei più richiesti benefici del C++ è stata la compatibilità all indietro col C. Ciò è parzialmente vero. La maggior parte dei vecchi programmi C, si compilano senza troppi problemi col C++. Uno dei problemi sono le nuove parole chiavi del C++ che possono essere state usate come nomi di variabili, o cose simili, in un vecchio programma C. Dopo l introduzione del C99, anche al linguaggio C sono state aggiunte delle parole chiavi che non esistono nel C++, quindi, interrompendone la compatibilità. Andiamo avanti osservando un semplice programma C++ che presenta alcune delle nuove funzionalità. Cominciamo con un semplice esempio Come fatto nella Introduzione alla programmazione C, creeremo un piccolo esempio in wxdev-c++ di un programma C++, lo compiliamo e vediamo cosa fa. In seguito lo analizzaremo in dettaglio. Si avvia wxdevc++ e si crea un nuovo progetto. Si seleziona Console Application e si spunta il pulsante radio C++ Project. Il nome del progetto sarà SimpleC++.

91 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 82 di 150 Figura 4.1 Le impostazioni di progetto per la nuova applicazione SimpleC++. Nella finestra successiva si crea una nuova cartella chiamandola SimpleC++ e vi si salva il progetto. Ora l IDE dovrebbe presentare il seguente codice già pronto. 1 #include <cstdlib> 2 #include <iostream> 3 4 using namespace std; 5 6 int main(int argc, char *argv[]) 7 { 8 system("pause"); 9 return EXIT_SUCCESS; 10 } Lo si sostituisca con quello seguente 1 #inc lude <cstdlib> 2 #include <iostream> 3 4 using namespace std; 5 6 const int TOP_MAN = 2; 7 const int THE_P RISONER = 6; 8 9 int main(int argc, char *argv[]) 10 { 11 cout << "Who are you?" << endl; 12 cout << "I am the new number " << TOP_MAN; 13 cout << ", You are number " << THE_PRISONER << endl << endl; 14 //Just a comment to show off C++'s single line comment style 15 for(int i = 0; i < THE_PRISONER; i++) 16 { 17 cout << "Thinking...\n" << endl; 18 } cout << "I am not a number, I am a free man!" << endl; system("pause"); 23 return EXIT_SUCCESS; 24 }

92 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 83 di 150 Una volta fatto, si preme <F9> per compilare e lanciare. L output dovrebbe essere esattamente lo stesso del programma SimpleC nell ultimo capitolo. Analizziamo il codice per vederne le differenze e su come il C++ lo ottiene rispetto al C. Le righe 1 e 2 dovrebbero essere familiari, esse includono le librerie che dobbiamo usare. La prima differenza che si nota è che i file da includere non terminano con.h. Non sono sicuro di questo ma ho il sospetto che sia dovuto al fatto che prima della standardizzazione diversi compilatori creavano le proprie versioni di librerie che più tardi sarebbero diventati standard. Quindi si sono vuluti evitare gli headers chiamati iostream.h e simili. La riga 4 presenta due delle nuove parole chiavi del C++ usando i namespace. I namespace sono un modo per creare funzioni con gli stessi nomi e parametri usandoli negli stessi programmi. <More here about namespaces> Le righe 6 e 7 mostrano una alternativa ai define del preprocessore. Tali righe usano la parola chiave const indicando che il valore della variabile non può essere modificato. Diversamente dai define le costanti hanno un tipo come int o float, ecc. La riga 11 ci presenta la nuova funzione di output del C++, cout. cout usa <<, qualcosa su std::cout e std::endl dell altro sulle funzioni di input/output. Riga 14 commento Riga 15 dichiarazione di un int nel ciclo for non consentita nel C. Riga 17 mostra i caratteri di escape come \n che continuano a funzionare assieme a endl; Fondamenti di C++ Funzioni Il C++ modifica in meglio le vecchie funzioni. Una volta usate ci si chiede come sia stato possibile farne senza per tanto tempo. Valori predefiniti Ricordate nell ultimo capitolo in cui abbiamo parlato delle funzioni che accettano un numero variabile di argomenti? Bene, al C++ è statta aggiunta la possibilità di creare funzioni che hanno dei valori di default pre-impostati. Questo viene ottenuto impostando i valori nel prototipo della funzione. Per esempio int MyFunction(int AnInteger, float AFloat = 5.4, double ADouble = 43.7); Non è necessario definire tutti i valori, ma una volta definitone uno, si devono definire tutti i successivi. Ora si può usare questa funzione come MyFunction(2); o MyFunction(2,5. 3,64); Col primo modo si riempiono automaticamente i valori per afloat e ADouble rispettivamente a 5.4 e Passaggio per riferimento Quando abbiamo visto le funzioni in C abbiamo citato l uso dei tipi di dato come argomenti di una funzione. Per esempio:

93 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 84 di 150 int MyExampleFunction( int AnInt, int AnotherInt ); Il problema nell uso di questo tipo di funzione è che la copia della variabile che si passa alla funzione viene creata nella memoria del computer. Questo richiede tempo e memoria. Se si usa ripetutamente la stessa funzione o si fa un ampio uso di strutture di dati definite in proprio si può incorrere in un inaccettabile livello di sovraccarico. La risposta a questo problema in C sono i puntatori. Per esempio: int MyExampleFunction( int * AnInt, int * AnotherInt ); Tuttavia il problema, è che i puntatori sono intrinsecamente pericolosi e si raccomanda di usarli il meno possibile. Il C++ fornisce una nuova funzionalità che prende il meglio dai due mondi. Viene detto passaggio per riferimento. Per usare questa funzione si usa l operatore & anteposto ai nomi degli argomenti. Per esempio: int MyExampleFunction( int & AnInt, int & AnotherInt ); Questa funzione si richiamerà semplicemente come qualsiasi ReturnValue = MyExampleFunction( FirstInt, SecondInt); altra funzione. Per esempio: Diversamente dall uso dei puntatori non si deve anteporre un & a FirstInt e SecondInt. Ma si agirà direttamente sulle variabili anziché su delle copie. Inline A volte si ha una funzione che viene richiamata migliaia di volte nel programma, creando un possibile collo di bottiglia. Il computer ha diversi trucchi per accelerare l esecuzione delle varie parti del programma. Aggiungendo la parola chiave inline, prima della funzione, si indica al compilatore che tale funzione deve essere ottimizzata. Per esempio: inline int MyExampleFunction( int AnInt, int AnotherInt ); Il compilatore quindi tenta di fare del suo meglio. Non è però garantito che vi riesca. La sola garanzia è che il compilatore ci proverà. Overloading Per me questa è la migliore delle funzioni aggiunte. Talvolta si vorranno scrivere due o più funzioni che facciano quasi esattamente la stessa cosa, ma su argomenti diversi. Per esempio consideriamo il caso in cui si abbiano tre funzioni che restituiscono la somma dei loro argomenti. La prima prende due interi, la seconda due float e la terza due double. La domanda è: che nome dare a queste funzioni. Nel C non si possono avere due funzioni con lo stesso nome, così si finisce a fare in questo modo: int SumInt(int AnInt, int AnotherInt); float SumFloat(float Afloat, float AnotherFloat); double SumDouble(double ADouble, double AnotherDouble); Come sarebbe più semplice se si potessero semplicemente chiamare Sum e passargli ognuno dei tre argomenti. Bene, col C++ si può fare. Per esempio: int Sum(int AnInt, int AnotherInt); float Sum( float Afloat, float AnotherFloat); double Sum(double ADouble, double AnotherDouble);

94 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 85 di 150 Questo è molto più ordinato (ed evita a noi pigri programmatori di scervellarci nella ricerca di nuovi nomi di funzioni). Non ci sono molte regole per creare funzioni sovrapposte (overloaded), queste sono: 1. La funzione deve differire almeno per un argomento oltre al tipo restituito. Questo non è consentito: int Sum( int AnInt, int AnotherInt); float Sum ( int AnInt, int AnotherInt); La ragione è che il compilatore non sarebbe in grado di capire la funzione che si vuol richiamare. 2. Gli argomenti non devono essere ambigui. Questo non è consentito: int Sum( int AnInt, int AnotherInt); int Sum( int AntInt, int AnotherInt, int OneMoreInt = 40); In quanto il compilatore non saprebbe se con la riga ReturnValue = Sum(4, 6); si intende richiamare la prima funzione con due argomenti, o la seconda col terzo argomento col valore di default. 3. Dovete spedire all autore (ndt: ed al traduttore) di questo libro $20 ogni volta che usate una funzione sovrapposta (overloaded ). (Ok, abbiamo mentito sull ultimo punto... però fate come volete). Quindi come vedete ci sono stati notevoli miglioramenti nell area delle funzioni. Allocazione della memoria Sono sicuro che ricorderete che nell ultimo capitolo abbiamo accennato all allocazione della memoria. Per farlo in C si deve far uso delle varie funzioni alloc, malloc, ecc. Il C++ ha un approccio diverso fornendo due nuove parole chiavi new e delete per gestire l allocazione e la de-allocazione della memoria. Allocare la memoria Anziché usare malloc abbiamo usato il comando new, che restituisce un puntatore all indirizzo di memoria dove risiede il nuovo blocco di memoria. Deallocare la memoria Una volta finito di usare la memoria si deve dire al computer che questa non serve più. In C lo si fa con la funzione free. In C++ c è il nuovo comando delete. Per esempio per liberare i due blocchi di memoria allocati nella sezione precedente, potremmo usare delete in questo modo. ATTENZIONE: È importante non mischiare le funzioni di gestione della memoria del C e del C++. Per esempio non si deve scrivere. MyClass * AClass = new MyClass(); Free(AClass); Se si usa new la memoria va liberata con delete. Se si usa malloc o alloc allora la memoria va liberata con free. Classi Le classi costituiscono una parte essenziale della programmazione orientata agli oggetti (OOP: object oriented programming). Fondamentalmente l OOP è tutto ciò che riguarda la creazione di modelli della vita reale, di oggetti e dell uso di questi nei propri programmi. Per esempio se si

95 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 86 di 150 deve creare un programma che imiti un sistema di illuminazione, si dovrebbe creare il modello di una luce, quello di un interruttore, e forse quello di un timer o quello di un sensore di luminosità. Questi modelli sono detti oggetti. Quindi di cosa è fatto un oggetto? Esso consiste di dati, le cose che l oggetto conosce e degli attributi del modello, contiene anche i metodi, il modo con cui l oggetto agisce o con cui ci si ha a che fare. Per esempio il modello di un bambino può avere i dati riguardanti il colore dei capelli (HairColour), quello degli occhi (EyeColour), l età (Age), l altezza (Height) ed il peso (Weight). Inoltre può fare cose come camminare, parlare, mangiare e dormire. Ovviamente questo è un modello molto elementare di bambino. Uno dei vantaggi nell uso degli oggetti è quella cosa detta incapsulamento. Tutti i dati ed i metodi relativ i ad un oggetto sono contenuto dentro di esso. È possibile organizzare le cose in modo che solo l oggetto possa accedere e modificare i propri dati. Ancora con l esempio del bambino, si potrebbe avere un metodo chiamato Birthday (compleanno) per aumentare l età di un anno. Non avrebbe molto senso che l età venisse incrementata da un altro oggetto diverso dal bambino. Ci sono altri benefici come l ereditarietà, di cui parleremo in seguito. Introduzione alle Classi (Basic Classes) Quindi come appare un oggetto in C++? Per cominciare gli oggetti in C++ vengono chiamati classi. Inizieremo con un esempio semplicissimo basato sul nostro modello di bambino. class Child { public: string HairColour; string EyeColour; int Age; int Height; int Width; }; Se state pensando Hey! Questa sembra una struct, allora siete nel giusto. Qui ci sono due differenze: la prima è l uso della parola chiave class anziché struct. La seconda è la prola chiave public:. Ci sono tre parove chiave a riguardo public:, protected: e private:. Prenderemo in considerazione la prima e l ultima, rimandando protected: in seguito. La parola chiave public: indica che tutti i dati ed i metodi che seguiranno sono accessibili da altri oggetti e dal programma. La parola chiave private: indica che solo la classe può accedere a questi dati o ai metodi. Prima di continuare è meglio cominciare ad usare una terminologia corretta. I dati ed i metodi contenuti nella classe sono detti membri, quindi la classe ha dati membro e funzioni membro (o metodi). Per illustrare la differenza tra le parole chiavi public: e private: vediamo come si accede ai dati membro di una classe. Prima si deve creare un istanza della classe, poi possiamo accedere ai membri. L uso è simile a quello delle strutture. Child MyChild; MyChild.Age = 5; Questo funziona con la classe precedente ed un programma che usa il codice sopra si compilerà senza errori. Modifichiamo la dichiarazione della classe in class Child {

96 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 87 di 150 }; string HairColour; string EyeColour; int Age; int Height; int Width; Se si tenta di usare tale codice ci saranno degli errori di compilazione, perché? Per default tutti i membri sono privati quindi la classe sopra è equivalente a class Child { private: string HairColour; string EyeColour; int Age; int Height; int Width; }; Quindi usare MyChild.Age = 5; è un errore perché solo la classe può accedere al dato membro Age, non il codice esterno che è quello che si è tentato di fare. È buona norma di programmazione dichiarare le variabili membro come private evitando che il codice esterno accidentalmente ne modifichi il valore. A questo punto potreste chiedere come si possa fare a cambiare i valori? La risposta è scrivendo delle funzioni di accesso [accessors] (talvolta dette funzioni setter e getter). Se lo vogliamo fare con la classe precedente questa ora apparirà così: class Child { private: string HairColour; string EyeColour; int Age; int Height; public: void SetHairColour(string haircolour){haircolour = haircolour;}; string GetHairColour(){return HairColour;}; void SetEyeColour(string eyecolour){eyecolour = eyecolour;}; string GetEyeColour(){return EyeColour;}; void SetAge(int age){age = age;}; int GetAge(){return Age;}; void SetHeight(int height){height = height;}; int GetHeight(){return Height;}; }; Ora possiamo scrivere MyChild.SetAge(5); ed il codice funzionerà senza errori. Inheritance Friends Polymorphism Typecasting Type identification Input/Output Abbiamo visto che in C tutto è considerato essere un file. Il C++ adotta un approccio diverso per l input e l output e tutto ha a che fare con un flusso (stream). Utilizzando la potenza delle classi si definisce una classe stream astratta e tutti i flussi di un input/output derivano da questa. Questo

97 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 88 di 150 vuol dire che condividono tutte la stessa interfaccia, la buona notizia è che sono al 100% più facili da usare delle funzioni printf/scanf del C. Input Output Strings Namespaces Exceptions Templates

98 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 89 di 150 Capitolo 5 Cercare la propria strada per l IDE Da scrivere

99 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 90 di 150 Capitolo 6 Il Debugging con wxdev-c++ Introduzione Un po di tempo fa ho letto un articolo che forniva la dimostrazione matematica che ogni programma per computer contiene dei bachi (bug=insetto). All epoca avevo idee idealistiche sulla programmazione e non c ho creduto. Ora sono d accordo, tutti, anche il programma più banale, contengono bug. Anche il sistema operativo che state usando per far girare il programma per leggere questo, contiene dei bug. Non ripercorrerò la storia alla ricerca del perché si chiamano bug. Ve lo lascerò come compito a casa. Andrò invece a descriverne le tipologie. Ci sono tre categorie principali. Alcuni bloccano il programma durante la fase di compilazione. Alcuni fanno fallire la fase del linker ed altri appaiono quando il programma è in funzione. Questi bachi si suddividono in tre livelli: critico, medio e basso. I bachi critici sono quelli che cancellano tutti i dati dell hard disk dell utente del tuo programma. Quelli medi bloccano il programma ogni tanto. I bachi di basso livelo sono quelli che irritano l utente ma non fanno veri danni, come un controllo testuale più basso di un pixel rispetto agli altri. In qualsiasi applicazione professionale l area dello sviluppo in cui si spende più tempo consiste nella correzione degli errori. Una cosa che tutti i bachi hanno in comune è che sono difficili da individuare, specie quelli che appaiono durante il funzionamento del programma (a runtime). Questo capitolo ha lo scopo di mostrarvi dei metodi per cercare ed eliminare tali bachi. Vedremo in special modo gli strumenti forniti da wxdev-c++. Compile Time Bugs Link Time Errors Run Time Errors

100 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 91 di 150 Domande Frequenti (FAQ) relative a DevC+ + Q. Ho sentito parlare di Easter egg (Ovetto con sorpresina) in Dev-C++? A. Uno degli sviluppatori ha creato un Easter egg nella versione 4 di Dev-C++. Questo è sopravvissuto in forma leggermente diversa nell ultima versione di wxdev-c++. Per accedere all Easter egg nell ultima versione Si avvia Dev-C++ (o wxdev-c++). Si apre la finestra about, accedendovi con Help About Dev-C++ Si clicca sul disegno in alto della finestra e la si trascina giù sul pulsante Authors. Apparirà un pesce che attraverserà la finestra. A seconda della vostraa velocità, e di quella del computer potete provare a cliccare sul pesce. Se ci riuscite cambierà direzione. Q. Perché il mio programma non viene ricompilato quando uno dei file header viene modificato? A. Di norma se un file sorgente viene modificato, il compilatore lo rileva e ricompila il progetto. Questo viene gestito dall impostazione della voce Use fast but imperfect dependency generation in Tools Compiler Options. Questo velocizza la compilazione del progetto omettendo dei passi, ma ne viene fuori che le modifiche ai file di intestazione (headers) vengono omesse. La soluzione a lungo termine consiste nel deselezionare tale voce, ma se le modifiche ai file di intestazione sono rare si può optare di ricompilare tutto il progetto e con questo verranno inclusi i file header modificati. Figura x.x La voce Use fast but imperfect dependency generation.

101

102 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 93 di 150 Parte 2 Elementi per lo Sviluppo con wxwidgets e wxdev-c++

103 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 94 di 150 Capitolo 7 La creazione di un semplice Editor HTML Introduzione Finora abbiamo discusso della programmazione C e C++ soltanto con le funzionalità di DevC++ dell IDE. Ma le funzioni aggiunte da Guru Kathiresan e gli altri sviluppatori di wxdev-c++ hanno creato un applicazione RAD (Rapid Application Design [Progettazione Rapida di Applicazioni]) di grande potenza. Con la seconda parte vedremo l uso di wxdev-c++ per sviluppare programmi e presentarvi i vari aspetti sull uso per progettare i programmi in modo che appaiano come desiderato. In questo capitolo cominceremo con la progettazione di un piccolo editor HTML. Non è molto bello, non c è la colorazione della sintassi o cose simili. Quello che creeremo è un programma con un menù elementare, una barra di stato, e la possibilità di salvare e caricare file. La caratteristica speciale di questo programma è che ha due finestre ridimensionabili. Quella sotto, è dove si digita il testo formattato per html, quella in alto verrà aggiornata dinamicamente per mostrare come apparirebbe in un browser web. Quindi cominciamo. Iniziare un Progetto wxwidgets Abbiamo già visto come avviare un nuovo progetto, quindi usiamo il solito metodo. Dalla finestra New Project, si sceglie wxwidgets Frame. Si seleziona il pulsante radio C++ Project. Si immette HTMLEditor come nome del progetto. Figura 7.1 Le impostazioni del progetto per l editor HTML. Si crea una nuova cartella chiamandola 'HTMLEditor dentro quella di Projects. Verrete accolti da una finestra sconosciuta Create New Project. Per il momento modificate le impostazioni nel modo seguente, eccetto dove vi viene chiesto il nome e trovate Sof.T. Quindi cliccate sul pulsante [Create].

104 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 95 di 150 Figura 7.2 La finestra Create New Project L IDE sfarfallerà mostrando diverse pagine di apertura, poi verrà aperto il form designer. L IDE apparirà così: Figura 7.3 L IDE che mostra il form designer La sezione seguente mostrerà come usarlo per creare la vostra applicazione killer. L uso del Form Designer Al centro c è una finestra grigio-scura. Questa è la rappresentazione visuale dell applicazione. Sulla destra c è una tavolozza su cui compaiono i diversi componenti usati. Sulla sinistra c è l editor delle proprietà che si usa per modificare i vari aspetti della form. Proprio sopra questa, c è una combo box che elenca tutti i componenti usati dall applicazione e ne consente una rapida selezione.

105 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 96 di 150 Cominceremo piazzando i componenti necessari al programma. L elenco completo è: una barra di menù, una barra di stato, un divisorio per finestre (splitter), un controllo testuale ed un controllo html. Quindi cominciamo con questi. Prima ci sarà la barra del menù. Cosa significa che non vedete una barra di menù? Se guardate nella tavolozza dei componenti sulla destra, vedrete che c è una barra di scorrimento sulla destra. Con questa, potranno apparire molti altri controlli e si dovrà scorrere per localizzarli. In alternativa si va nella combo box con scritto All e la si usa per ridurre il numero di componenti presentati. Usando uno di questi metodi: Si cerca e si seleziona Menu. Ora si clicca sul componente della barra dei menù e questa verrà evidenziata in blu. Figura 7.4 La selezione di un componente Si clicca sulla form grigio-scura al centro del designer. Si noteranno due cose: la prima è che è apparso un piccolo rettangolo col disegno di una barra di menù sulla form con 8 quadratini attorno. L altra cosa è che l oggetto Menubar sulla tavolozza dei componenti non è più evidenziato in blu. I quadratini sono manigliette per il controllo visuale della barra del menù. Diversi componenti appaiono in questo modo e non c è niente di cui preoccuparsi; è normale e non ha nulla a che vedere col posizionamento fisico del componente. Si procederà ponendo gli altri componenti necessari nella finestra del designer. Dopo c è la barra di stato. La troverete sotto Controls e potrà essere necessario scorrere giù perché è quasi in fondo. Si clicca su 'status bar', e quando si evidenzia, si clicca sulla form. Si noterà che questa volta è saltato automaticamente nel posto giusto nella parte bassa dello schermo. Ora tocca al divisorio (splitter). La si trova nella tavolozza sotto Window. Si cerca e si seleziona 'splitter window' poi si clicca sulla form. Automaticamente la finestra splitter riempirà la form. Ora si vuole la finestra html. Questa è nella stessa tavolozza quindi: Si seleziona 'HTML window' e la si posiziona sulla finestra splitter. Si vedrà che la form improvvisamente si restringe ed appaiono le barre di scorrimento sul lato destro e su quello inferiore, niente paura è una funzione prevista. Infine vogliamo un controllo

106 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 97 di 150 testuale, che si trova nei controlli. La chiamiamo Memo. In realtà questo è solo un controllo testuale multiriga, il nome è un eredità Delphi di wxdev-c++. Si seleziona il componente Memo e lo si pone nella form. Questo troverà automaticamente la posizione sotto la finestra html. Non è quello che si vuole. Per metterre a posto si clicca sulla Finestra Splitter in modo che appaia la form, in questo modo Figura 7.5 Il Design Form con la Finestra Splitter selezionata. Figura 7.6 Il Property Inspector. Si cerca la proprietà Orientation (Orientamento) Figura 7.7 La proprietà Orientation Lo si cambia in wxvertical. Si clicca sul Design Form per vederne le modifiche. Impareremo altro sull uso del Property Inspector nella sezione successiva. Per il momento abbiamo una form come questa.

107 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 98 di 150 Figura 7.8 La form completata nella finestra di progettazione. Questo è il momento della verità. Si preme <F9> per compilare e lanciare l applicazione. Si noterà che l applicazione compilata appare un po come la form di progettazione. Il testo è scomparso dalla finestra html ma non dal controllo testualo. Da notare anche che pur avendo posto la barra del menù sulla form, nell applicazione compilata non si vede niente. Figura 7.9 L applicazione compilata. Nella prossima sezione vedremo la configurazione della form nel designer per renderla più simile ad una applicazione funzionante reale. Modifica delle Proprietà Se l applicazione è ancora in funzione, la si chiuda, come qualsiasi altra applicazione windows, cliccando sul pulsante rosso di chiusura sulla barra del titolo. Ora possiamo configurare i componenti nel form designer. Prima correggeremo il controllo testuale. Nel form designer: Si seleziona il controllo del testo cliccandoci sopra. Si potrà avere conferma della selezione perché appariranno gli otto quadratini sui lati e sugli angoli (quello in basso potrebbe essere nascosto dalla barra di stato). Questi quadratini vengono

108 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 99 di 150 detti maniglie (handles). Si noterà che selezionando un componente, il testo nella combo box sopra l editor delle proprietà cambia. Questo testo indica il nome del componente, seguito dal nome del tipo. Per es. Selezionando il controllo testuale si vedrà WxMemo1:wxTextCtrl. WxMemo1 è il nome del controllo e wxtextctrl è quello del tipo. Anche il contenuto dell editor delle propriertà si modifica a seconda dei componenti selezionati, riflettendo le proprietà di ciascun componente. Quindi avendo selezionato il controllo di testo, l editor delle proprietà dovrebbe apparire così: Figura 7.10 L editor delle proprietà per il controllo testuale. Prima di tutto sbarazziamoci del testo mostrato inizialmente nel controllo. Nell editor delle proprietà la prima colonna contiene i nomi delle proprietà; sono in nero e non si possono modificare. La seconda colonna, con le scritte in blu, contiene i valori di tali proprietà e sono modificabili. All inizio non è facile vedere cosa modifica. La proprietà che cerchiamo è sotto Strings. Se si Clicca nella seconda colonna, dopo Strings dove c è Edit Strings Appare un pulsantino con tre puntini. Si clicca su questo pulsante [...] per attivare la finestra di modifica del testo.

109 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 100 di 150 Figura 7.11 L editor della stringa Ogni testo che appare nell editor apparirà nel controllo testuale. Si cancella tutto il testo contenuto nel controllo. Si preme il pulsante [Ok]. Si vedrà che il testo è scomparso dal controllo testuale nel form designer. Volendo controllare che sia sparito anche dall applicazione compilata, lo si può ancora compilare e lanciare. Ora occupiamoci della barra del menù. Perché non appare? La ragione è che non contiene ancora niente. Per porvi rimedio: Si seleziona la barra del menù cliccando sul quadratino che la rappresenta. Questa volta l editor delle proprietà mostra solo cinque voci. Quella cercata è chiamata Menu Items, proprio come per la proprietà Strings del controllo testuale cliccandoci a fianco apparirà un pulsantino coi tre puntini. Si clicca sul pulsante [...] per attivare la seguente finestra.

110 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 101 di 150 Figura 7.12 L editor della barra del menù Si clicca sul pulsante [Add Item]. Subito la finestra si riempie con tutte le informazioni già generate. Il rettangolo chiamato Caption ora contiene il valore MenuItem1 ; Si sostituisce 'MenuItem1' con &File e si preme <Enter>. Ora il testo sul rettangolo Menu Items cambia così come ID Name. Si clicca sul pulsante [Apply]. (Il motivo per usare & nei titoli delle voci del menù è per creare dei rimandi mnemonici e verranno spiegati nel Capitolo 12 sotto Tasti Acceleratori e Mnemonici ). Ora abbiamo creato il menù File e vogliamo aggiungerci delle voci. Per farlo: Si clicca sul pulsante [Create Submenu]. Questo produce una voce di menù sotto il menù File e lo indenta un po per mostrare che è figlia del menù File. Se ne cambia il titolo in &Open\tCtrl+O e si preme <Enter>. Si clicca sul pulsante [Apply]. Si ripete questa procedura ma questa volta cambiando il nome in &Save\tCtrl+S. (Il motivo per usare \tctrl+o nei numi dei menù è per creare tasti acceleratori e verrà spiegato nel Capitolo 12 sotto Tasti Acceleratori e Mnemonici ). Ora si vuol aggiungere un separatore al menù.

111 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 102 di 150 Si clicca sul pulsante [Create Submenu]. Questa volta sopra la combo box Type : Si seleziona Separator. Si clicca sul pusante [Apply]. Infine si vuol aggiungere al menù una voce per l uscita. Per l ultima volta: Si clicca sul pulsante [Create Submenu]. Si modifica il titolo in E&xit. Infine si clicca sul pulsante [OK]. ATTENZIONE: Se in qualsiasi momento nella creazione di una barra di menù si preme il pulsante [Cancel], tutto il lavoro fatto fino a quel momento verrà perso. Questo può risultare estremamente irritante nella creazione di sistemi complessi di menù. Se si è commesso un errore è meglio continuare. Si clicca su [OK] per salvare il lavoro fatto fino a quel punto, si riapre la finestra della barra del menù e si effettuano le modofiche. Per vedere i risultati di tutte le modifiche: Si preme <F9> per compilare e lanciare. Si vedrà ora che c è una barra di menù. Si clicca su File e si vedrà il menù appena creato scendere giù. Non fa ancora niente, ma lo faremo alla fine della prossima sezione. Figura 7.13 La nuova barra del menù Prima di cominciare col codice si devono aggiungere altri due componenti. Si cambia la tavolozza dei componenti in Dialogs. Si selezionano e posizionano OpenFileDialog ed un SaveFileDialog sulla form. Dopo averli aggiunti alla form:

112 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 103 di 150 Selezionandoli uno alla volta se ne modifica la proprietà Extensions da *.* a *.htm. Ora possiamo andare alla parte seguente Aggiungere il Codice per fare in modo che succeda qualcosa. Aggiungere il Codice La programmazione GUI si fonda su quella che è chiamata programmazione Basata sull Evento (Event based). In sostanza una volta avviato il programma, questo resta in un ciclo, nell attesa di un evento. Quando ciò avviene cerca, se c è, il codice da eseguire in risposta. Gli eventi possono essere qualsiasi cosa, dall avvio del programma, al click col mouse in una sua finestra, il ridimensionamento di una finestra o l interazione con altri programmi. Quindi per far fare qualcosa al nostro programma, dobbiamo decidere a quali eventi rispondere e cosa fare in risposta. Cominceremo con uno facile. Al momento il menu non fa niente. Modifichiamolo e facciamo in modo che venga chiuso tutto quando si clicca sulla voce Exit del menù File. Per fare questo: Si seleziona il componente della barra del menù. Si clicca sul pulsante [Edit MenuItems]. Se il menù ad albero sulla sinistra appare così allora si clicca sul segno + a fianco per far apparire tutte le voci del menù. Figura 7.14 Si clicca sul segno + per espandere il menù ad albero. Si seleziona la voce E&xit. Si clicca sul pulsante [Edit] in basso nella finestra. Ora sulla destra della finestra in basso appare la combo intitolata OnMenu. Questo controllo contiene l evento che avverrà quando si cliccherà su Exit nel menù. Si clicca sul pulsante [Create] (vicino alla combo box). Apparirà la seguente finestra Si clicca sul pulsante [OK].

113 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 104 di 150 Figura 7.15 La finestra di creazione di una nuova funzione. Si clicca sul pulsante [Apply] Si clicca sul pulsante [OK]. Se il designer non vi porterà direttamente alla nuova funzione allora si clicca sul tab di nome (*)HTMLEditorFrm.cpp (nella finestra dell editor). La pagina dovrebbe aprirsi col cursore nel corpo di una funzione come illustrato sotto. 94 /* 95 * Mnuexit1018Click 96 */ 97 void HTMLEditorFrm::Mnuexit1018Click(wxCommandEvent& event) 98 { 99 // insert your code here 100 } Sotto la riga Si aggiunge // insert your code here Destroy(); La funzione Destroy provocherà la chiusura dell applicazione. Si preme <F9> per compilare e lanciare. Si va in File Exit per vedere come funziona il codice aggiunto. Ci si assicuri che il form designer abbia il focus cliccando sul tab HTMLEditorFrm.wxform nella finestra dell editor. Aggiungiamo ora la funzione che crea la parte dell editor testuale. Anche se non è il modo migliore di farlo, aggiorneremo la finestra HTML ogni volta che l utente modifica o aggiunge il contenuto del controllo testuale. Quindi questo è l evento all interno del controllo testuale su cui vogliamo agire. Si seleziona il controllo testuale. Guardando l editor delle proprietà si vedrà un altro tab chiamato Events innestato all interno. Si clicca sul tab 'Events' per scoprire a quali eventi possa rispondere il controllo testuale. Si dovrebbe vedere qualcosa di simile al seguente. Ci si ricordi che si vuol agire quando l utente aggiorna il controllo testuale. Quindi si indovina che l evento OnUpdated è quello cercato.

114 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 105 di 150 Figura 7.16 L editor dell evento Per creare una nuova funzione che risponda all evento, Si clicca in una cella vuota nella colonna a destra. Dovrebbe apparire una list box con l elenco di tutte le funzioni che wxdev-c++ ci ha già creato. Non ne vogliamo usare nessuna di queste quindi: Si seleziona la voce in alto <Create New Function>. Figura 7.17 L elenco delle funzioni disponibili nell editor degli eventi Si dovrebbe essere portati automaticamente alla nuova funzione, altrimenti, si clicca sul tab chiamato (*)HTMLEditorFrm.cpp. Ci si vedrà una nuova funzione come la seguente. 105 /* 106 * WxMemo1Updated 107 */ 108 void HTMLEditorFrm::WxMemo1Updated(wxCommandEvent& event) 109 { 110 // insert your code here 111 }

115 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 106 di 150 wxdev-c++ ci ha gentilmente creato lo scheletro della funzione, e noi la andremo a riempire. Questa volta non vi dirò direttamente cosa fare. Vi voglio insegnare a far uso di una delle maggiori funzionalità di wxdev-c++, il file di help delle wxwidgets. Quindi nella IDE si va in: Help wxwidgets Oppure basta premere F1. Dovrebbe apparire il file di aiuto: Figura 7.18 Il file di aiuto delle wxwidgets, dovrebbe diventare il miglior amico Il nostro è quello di modificare il contenuto della finestra HTML secondo il contenuto del controllo testuale. Quindi vediamo prima come modificare la finestra HTML. Sotto il tab 'Contents' sul pannello a sinistra dello schermo di aiuto, si espande l opzione Alphabetical class reference cliccando sul + al suo fianco. Apparirà un lungo elenco di componenti inizianti tutti con wx. Come si fa a trovare quello che cerchiamo? Beh! Si fa una rapida scorsa fino a wxhtml. Qui ci sono diverse voci che iniziano con questo, ma guardando verso la fine c è wxhtmlwindow. Si clicca su wxhtmlwindow e si legge il testo che riempirà il pannello di destra.

116 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 107 di 150 Figura 7.19 La descrizione di wxhtmlwindow Leggendo nella descrizione di questo controllo arriviamo alla frase: Once the window is created you can set its content by calling SetPage(text), LoadPage(filename) or LoadFile. (Una volta creata la finestra se ne può impostare il contenuto richiamando SetPage(text), LoadPage(filename) e LoadFile). Le ultime due opzioni mi dicono che aprono dei file, mentre la prima SetPage(text), dice che si può impostare il contenuto della finestra HTML chiamandola con questa funzione con del testo. Per averne conferma si clicca sul link SetPage(text) e leggiamo il resto su tale funzione. Ora possiamo aggiungere SetPage(text) nella nostra nuova finestra. Prima si deve avere il nome del controllo su cui lavorare. Per ottenerlo si va nel form designer col mouse sul controllo HTML. Apparirà una finestra con scritto WxHtmlWindow1:wxHtmlWindow. Ci si ricordi che la prima parte prima dei due punti è il nome del componente. Quindi si torna alla funzione e sotto la riga: // insert your code here Si aggiunge il codice WxHtmlWindow1 WxHtmlWindow1 è un puntatore ad una istanza di HtmlWindow, quindi si deve aggiungere -> E finalmente aggiungere la nuova funzione trovata nel file di help SetPage().

117 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 108 di 150 Il comando completo sarà: WxHtmlWindow1->SetPage() Finora tutto bene, ma abbiamo bisogno di un testo come argomento della funzione. Vogliamo inserire del testo da passare al controllo e di conseguenza ad HtmlWindow. Provate a scorrere nell elenco fino a trovare wxmemo. Qualche problema? Ricordate quanto detto a proposito di Memo che è una reminescenza di Delphi? Per trovare quanto cercato, provate il trucco di soffermarsi sul componente nell editor. Figura 7.20 Scoprire il nome ed il tipo di un controllo Il formato è <Control Name>:<Control Type>, quindi la parte che segue i due punti contiene l informazione cercata. Si cerca nel file di help wxtextctrl. Cliccando su wxtextctrl si trovano ben poche informazioni. Si espande l elenco ad albero a sinistra dei contenuti, cliccando sul segno + vicino a wxtextctrl. Ora si possono vedere tutte le funzioni contenute nel componente. Si cercano in basso nella lista quelli idonei. Si cerca qualcosa di plausibile che inizi con get. Dato che non c è GetText né qualcosa di simile, quello più prossimo sembra essere GetValue. Si Clicca su questo e lo si legge per essere sicuri. La prima riga ci dovrebbe convincere. Gets the contents of the control. (Restituisce il contenuto del controllo) Per aggiungerla alla nostra funzione, tra le parentesi tonde () di SetPage, si aggiunge il nome del controllo testuale, e ricordando che è un puntatore, si aggiunge la nuova funzione trovata. Si dovrebbe finire con questo codice. 108 /* 109 * WxMemo1Updated 110 */ 111 void HTMLEditorFrm::WxMemo1Updated(wxCommandEvent& event) 112 { 113 // insert your code here 114 WxHtmlWindow1->SetPage(WxMemo1->GetValue()); 115 } Proseguiamo con la codifica. Che vuol dire che volete vedere quello che è stato fatto! Bene, prima compiliamo e lanciamo. Si preme <F9>.

118 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 109 di 150 Se non conoscete i tag HTML allora immettete quanto segue: <h1>wxwidgets are great</h1>the designers of wxdev-c++ are <b><u>great</u></b> too!. Si potrebbe espandere la finestra per vederne tutto l effetto. Oppure, se avete scaricato il codice di esempio, che accompagna il libro, c è un file incluso chiamato sample.htm da aprire. Si dovrà massimizzare la finestra per vederne il risultato. Ora possiamo continuare? Abbiamo altre due funzioni da creare. Quella per caricare i file HTML e quella per salvarli. In previsione abbiamo creato due voci di menù chiamate Load e Save. Il lavoro effettivo sarà svolto dalle dialog Open/Save File che abbiamo posto nel form precedentemente. Creeremo le funzioni necessarie come abbiamo fatto per la voce di menù E&xit. Si apre il menu dialog editor selezionando il componente che rappresenta la barra del menù. Si clicca sulla cella Edit MenuItems. Si espande l elenco ad albero delle voci di menù. Si seleziona la voce &Open. Si clicca sul pulsante [Edit]. Poi nella combo box OnMenu, si clicca sul pulsante [Create]. Sulla dialog che appare Si sceglie il pulsante [OK], Si clicca sul pulsante [Apply]. Si ripete lo stesso iter per la voce &Save menu. Appena fatto Si clicca sul pulsante [OK]. Dovrebbe esservi stato generato il seguente codice. 116 /* 117 * Mnuopen1015Click 118 */ 119 void HTMLEditorFrm::Mnuopen1015Click(wxCommandEvent& event) 120 { 121 // insert your code here 122 } /* 125 * Mnusave1016Click 126 */ 127 void HTMLEditorFrm::Mnusave1016Click(wxCommandEvent& event) 128 { 129 // insert your code here 130 } Queste funzioni si modificano in modo che appaiono come mostrato in seguito. Spiegherò ulteriormente nel Capitolo 9 nella sezione intitolata Dialog. Ma raccomando di aprire l help delle wxwidgets e cercare le funzioni ed i componenti usati nel codice seguente per capire come funzionano. 116 /* 117 * Mnuopen1015Click

119 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 110 di */ 119 void HTMLEditorFrm::Mnuopen1015Click(wxCommandEvent& event) 120 { 121 // insert your code here 122 if(wxopenfiledialog1->showmodal()) 123 { 124 WxMemo1->LoadFile(WxOpenFileDialog1->GetPath()); 125 } 126 } /* 129 * Mnusave1016Click 130 */ 131 void HTMLEditorFrm::Mnusave1016Click(wxCommandEvent& event) 132 { 133 // insert your code here 134 if(wxsavefiledialog1->showmodal()) 135 { 136 WxMemo1->SaveFile(WxSaveFileDialog1->GetPath()); 137 } 138 } Questo è quanto per questo programma, quindi si preme <F9> per compilare ed avviare. Provate a caricare e salvare file *.htm. Modificate il testo nel controllo testuale in basso e vedete come ciò si riflette nel controllo superiore. Per il momento mi auguro che siate stati impressionati da quanto wxdev-c++ e wxwidgets possano esservi utili. La quantità di codice che avete scritto è comparabile agli esempi C e C++ e ed è ben poco. Questo programma fa molto di più e con meno fatica. Si potrebbe ampliare questo programma in modo che abbia una barra di strumenti (toolbar) e dei pulsanti per inserire vari tag HTML, ed altre fantastiche funzioni. Se volete farlo, andate avanti. Se avete bisogno di saperne di più su come farlo, continuate a leggere.

120 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 111 di 150 Capitolo 8 Lavorare con i Frame e le Dialog Introduzione Alla base di qualsiasi programma GUI a prescindere dalla complessità c è la finestra o le finestre che si useranno. Le wxwidgets fanno distinzione tra Frame e Dialog, sebbene si possano usare in modo interscambiabile. Le dialog generalmente vengono usate per consentire agli utenti di scegliere o porre domande. Di solito la dialog non è ridimensionabile e viene mostrata Modalmente. Una dialog modale indica che l utente non può interagire con nessun altra finestra finché non chiude questa. I frame di solito vengono usati per le finestre dell applicazione principale contenenti i menù, le barre degli strumenti (toolbar), le barre di stato e cose simili. In questo capitolo esamineremo la creazione di nuovi progetti e le differenze tra progetti di Frame e di Dialog. Vedremo le diverse proprietà per i frame e le dialog. Vedremo anche come aggiungere altri frame e dialog ad un progetto. Infine cominceremo la costruzione di un applicazione di esempio. Prima di continuare è necessario spiegare un punto che è causa di confusione per i nuovi utenti. wxdev-c++ è stato progettato in modo che si possa usare come designer di form e dialog da usarsi al di fuori di un progetto. Ne risulta che agli utenti vengono presentate le seguenti dialog all inizio di un nuovo progetto. Figura 8.1 Il menù New per la creazione di nuovi progetti, file sorgenti o form. Molti utenti hanno cliccato la voce New wxframe e progettato una bella GUI. Si sono però molto sorpresi quando hanno tentato di compilare e trovando degli errori di caricamento del linker. Il motivo di ciò è che non ci sono le impostazioni del progetto quindi il linker non sa dove guardare per le librerie wx necessarie. Le opzioni dei menù New wxdialog e New wxframe ci sono sia per aggiungere nuovi frame o dialog in un progetto esistente che per progettare frame e dialog da usarsi altrove. Per creare un nuovo progetto contenente un frame o una dialog cìè bisogno dell opzione Project. Creazione di un nuovo progetto Qui è dove tutto comincia. Finora abbiamo creato un certo numero di nuovi progetti e si dovrebbe aver acquisito una certa familiarità con alcune delle scelte disponibili. La maggior parte di questi progetti è stata di tipo a linea di comando ad eccezione dell esempio dell editor HTML. Cerchiamo quindi di vedere come creare un nuovo progetto di frame o di dialog e le differenze tra loro. Progetto di Frame In questo esempio creeremo programma un elementare: Hello World. Per iniziare Si seleziona il menù File Project

121 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 112 di 150 Apparirà la seguente dialog Figura 8.2 La dialog del nuovo progetto Cliccando su ciascuna delle icone si vedranno delle brevi descrizioni di quello che il tipo di progetto contiene. Dato che vogliamo creare un progetto di frame si devono seguire i seguenti passi. Si clicca su wxwidgetsframe. Si modifica il nome del progetto in FrameProject. Ci si assicura che sia selezionato il radio button vicino a C++ Project. Si clicca sul pulsante [Ok]. Ne risulterà la chiusura della dialog e l apertura di una nuova che assomiglierà alla seguente.

122 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 113 di 150 Figura 8.3 La dialog di salvataggio del progetto Proprio come visto prima questa dialog ci propone le scelte per salvare il progetto in una specifica locazione. Se avete seguito tutti i tutorial in questo libro Si va nella propria cartella dei progetti Si crea una nuova cartella chiamata FrameProject Si entra in tale cartella Si clicca sul pulsante [Save] Dopo che la dialog di salvataggio si è chiusa se ne aprirà un altra. Figura 8.4 La dialog per il nuovo frame Qui ci sono un sacco di opzioni quindi andiamo a vederli uno per uno.

123 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 114 di 150 Class Name Dato che ogni nuovo frame che si crea viene derivato dalla classe wxframe gli si deve dare un proprio nome di classe. Questo vi viene generato automaticamente, ma si ha la possibilità di modificarlo. Se lo si cambia ci sono delle regole da ricordare. Il nome di una classe può contenere solo caratteri alfa-numerici e l underscore _. Il nome della classe, inoltre, non dev essere quello di una parola chiave, deve essere unico e non può cominciare con un numero. Proviamo a modificare il nome della classe con un nome invalido. Si immette 2 Frame ProjectFrm nel campo del nome della classe Si clicca sul pulsante [Create] Apparirà una dialog di allarme come la seguente Figura 8.5 Dialog di attenzione su un nome di classe invalido Se si clicca [No] un promemoria vi ricorderà del problema. Figura 8.7 La dialog che vi ricorda cosa possa contenere un nome valido di una classe. Scegliendo yes wxdev-c++ sostituisce tutti i caratteri invalidi con l underscores, questo potrebbe far apparire il nome della classe un po strano, ma almeno il compilatore non si lamenterà. Figura 8.7 Un nome di classe corretto automaticamente.

124 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 115 di 150 Per questo esempio vogliamo il valore di default per il nome della classe quindi Si riempie il campo Class Name con FrameProjectFrm File Name Questo campo contiene il nome del file in cui verranno salvate le informazioni sulla classe del frame. Ciascun frame o dialog creata da wxdev-c++ viene salvata in un proprio file. Infatti ci sono tre file per ciascun frame o dialog. Hanno tutti lo stesso nome cambia solo l estensione. Una finisce con.wxform, questa è l informazione necessaria a wxdev-c++ per memorizzare l aspetto del file nel designer. Poi ci sono due file di codici sorgenti: il file di intestazione (header) finisce in.h e contiene la dichiarazione della classe del frame e l altra ha estensione.cpp e contiene le definizioni della classe. Ancora una volta questo si può modificare secondo i propri usi. Qualora si scelga un nome di file invalido wxdev-c++ mostrerà un avviso e si offrirà di correggerlo automaticamente. Per questo esercizio accetteremo il valore di default. Figura 8.8 La dialog per ricordarvi come debba essese composto un nome di file valido. Save To Questo campo contiene la locazione selezionata per salvare il progetto della dialog precedente. In genere è meglio lasciare stare tale campo, a meno di non avere un motivo preciso per salvare il codice in un posto diverso. Title Il contenuto di questo campo viene usato come titolo del frame. Il titolo viene scritto nella parte superiore. Figura 8.9 La parte del titolo di un frame. Per questo esempio lasceremo stare il titolo. Author Questo campo contiene il vostro nome. wxdev-c++ tenta di dedurlo automaticamente. Il contenuto di questo campo viene usato per aggiungere le informazioni sul copyright sul codice sorgente ed i file di progetto. Se tale campo è scorretto o si vogliono usare altre informazioni di copyright lo si modifichi di conseguenza. Window Style Questa sezione contiene diversi check box che modificano l aspetto ed il funzionamento del frame. Alcuni vengono riempiti per default. Li analizzeremo ognuno e vedremo cosa significano. Use Caption Questa voce corrisponde al flag wxcaption. La documentazione dell help dice che impostandola si mette un titolo al frame. Infatti sotto windows se non lo si mette il frame apparirà senza bordi.

125 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 116 di 150 Figura 8.10 Differenze tra un frame con titolo ed uno senza. Lasceremo la spunta per il titolo. Resize Border Questa voce corrisponde al flag wxresize_border. Significa che l utente può trascinare i bordi del frame per allargarlo o rimpicciolirlo. Selezioneremo questa voce segnandola. System Menu Corrisponde al flag wxsystem_menu. Essa determina se deve apparire o meno l icona in alto a sinistra delle finestre. Se viene mostrata allora si rende disponibile un menù cliccandoci sopra. Riguarda anche la possibilità di mostrare i pulsanti per minimizzare, massimizzare e chiudere la finestra. Figura 8.11 differenze tra un frame con e senza il menù di sistema. Lasceremo tale voce selezionata. Thick Border Corrisponde al flag wxthick_frame. Quello che la documentazione ci dice è che mostra una piccola cornice attorno alla finestra nelle applicazioni Windows e Motif. Personalmente non ho visto differenze su applicazioni Windows. Sembra che il flag sia in relazione a

126 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 117 di 150 WS_THICKFRAME di Windows che ha poco senso dato che si riferisce a vecchie versioni di Windows. Lo lasceremo com è. Stay On Top Questa voce corrisponde al flag wxstay_on_top. Al momento funziona solo su Windows e significa che tale finestra galleggerà su tutte le altre. È utile se si sta progettando una finestra che verrà usata come toolbox, o una dialog che l utente non deve ignorare. La lasceremo al suo valore di default. No Parent Di questa voce se ne discuterà nella sezione seguente riguardante le applicazioni basate su dialog in quanto non è rilevante per i frame. Lasceremo questa opzione al valore di default. Min Button, Max Button, Close Button Vorrei prendere in considerazione queste tre voci assieme dato che sono in relazione tra loro. Corrispondono ai flag wxminimize_box, wxmaximize_box e wxclose_box. Questi flag determinano se il frame mostra tali pulsanti o meno, come mostrato sotto. Tutte le voci selezionale Il pulsante Min deselezionato Il pulsante Max deselezionato Il pulsante Close deselezionato Selezioneremo Max Button lasciando le altre voci come sono. Selected Profile Questo menù a discesa consente di scegliere un profilo da utilizzare. Riguarda quello che il compilatore userà per compilare il progetto. Al momento si può scegliere tra il compilatore della Microsoft ed il porting di GCC: MingW. Si modifica il contenuto secondo il compilatore utilizzato. Ora che ne abbiamo visto le impostazioni è il momento di creare il progetto. Si clicca sul pulsante [Create]. La dialog verrà chiusa e si aprirà il l editor delle form.

127 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 118 di 150 Figura 8.12 Il form designer che mostra un nuovo frame Ora che abbiamo un nuovo frame cosa ci facciamo? Beh, per prima cosa proviamo a compilarlo. Si preme <F9>. Dopo la compilazione apparirà la finestra come mostrato qui. Figura 8.13 La versione compilata del frame. Ma un momento! Questo non è come lo si vede nel designer, la larghezza e l altezza sono sbagliate. La ragione di ciò è che il codice per cambiare il frame compilato non viene generato finché non si modifica il frame stesso. Proveremo a farlo trascinando leggermente un lato del frame e poi ricompilando. Questa volta il frame è come nel designer.

128 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 119 di 150 Modificare il frame Ci sono due modi per modificare il frame: uno per manipolazione diretta, l altro modificandone le proprietà. Manipolazione diretta del frame La manipolazione diretta del frame si limita al trascinamento del frame stesso tramite la barra del titolo in una posizione diversa nel designer. Con ciò si modificano le proprietà Top e Left del frame, che indicano dove la versione compilata debba comparire sullo schermo. È anche possibile trascinare i bordi per ridimensionare il frame. Questo modifica le proprietà Height e Width. Modifica delle proprietà del frame Le proprietà di un frame si trovano nel Property Inspector mostrato sotto. Figura 8.14 Il Property Inspector Se il Property Inspector non mostra il frame allora si clicca sul menù a discesa e si seleziona la voce che finisce con :wxframe. Figura 8.15 Selezione del frame nel Property Inspector Ora prendiamo in considerazione le proprietà mostrate nella Figura x.x una per una. Modificheremo alcune di queste per creare il progetto di esempio. Center La proprietà Center è un Booleano. Vuol dire che ha valore vero o falso (true/false). Se Center è true viene chiamata la funzione Center() alla creazione del frame. Questo vuol dire che il frame verrà centrato sul monitor alla creazione. Se è impostato a false il frame verrà creato nella posizione sul monitor indicata dalle proprietà Top e Left.

129 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 120 di 150 Quindi lo lasceremo a false. Class La proprietà Class consente di usare delle classi personalizzate. Parleremo in seguito nel libro dell uso di questa proprietà nel Capitolo 13, Creare ed usare altri controlli. Font Questa voce imposta il font usato da questo frame e dai controlli che saranno suoi figli. Lasceremo stare tale impostazione in quanto non vogliamo aggiungere alcun controllo in questo capitolo. Frame Style Uno stile nelle wxwidgets indica come un controllo debba apparire e funzionare. Alcuni stili sono specifici di certe piattaforme altri sono più generici. Un wxframe ha due gruppi di stili, quelli generali applicabili alle classi wxwindow, da cui essa deriva, e dagli stili propri. Questa sezione è dedicata agli stili propri del frame. Per default la proprietà Frame Style appare come una lunga riga di flag. Questa proprietà si può espandere cliccando sul + a fianco della scritta Frame Style. Apparirà l intera lista degli stili. Figura 8.16 L elenco espanso degli stili di un frame. Alcuni di tali stili li abbiamo già incontrati quando abbiamo creato il frame. Sono tutti valori Booleani, quindi vero o falso (true o false). Se la proprietà è impostata a true il flag verrà aggiunto all elenco dei flag passati alla creazione del frame nel runtime. Analizziamoli uno per volta. Nome del Flag Funzionamento del flag o stile wxcaption wxclose_box Abbiamo già incontrato questo flag nella creazione del frame. Ci si ricorderà che impostandolo a false si rimuoverà non solo il titolo, ma anche i bordi del frame. Questa è un altra proprietà che abbiamo già visto ed

130 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 121 di 150 abilita o disabilita il pulsantino di chiusure sul frame. wxframe_ex_contexthelp wxframe_float_on_parent wxframe_no_taskbar wxframe_shaped Questo flag si suppone che aggiunga un pulsante di richiesta alla barra del titolo del frame. Tuttavia, per come è attualmente implementato in wxdev-c++ pare che non faccia nulla. Fa sì che il frame si sposti sul frame genitore ovvero che appaia sempre al di sopra del genitore. Questo flag fa sì che il frame creato non appaia nel taskbar. Su piattaforme Windows il frame verrà minimizzato nell angolo del desktop. Crea un frame che può apparire con i bordi ritagliati come certe schermate di avvio (splash screen). Figura 8.17 L esempio di frame wx shaped wxframe_tool_window Crea un frame con una semplice area per il titolo ed un pulsante di chiusura. Questo tipo di frame viene spesso usato per finestre di tipo tool box. Figura 8.18 Un frame di tipo finestra di strumenti wxmaximize wxmaximize_box wxminimize wxminimize_box wxno_3d wxresize_border wxstay_on_top wxsystem_menu Visualizza il frame nello stato massimizzato. Questa è un altra proprietà già vista ed abilita o disabilita il rettangolino di massimizzazione sul frame. Fa in modo che il frame venga visualizzato in uno stato minimizzato. Già incontrata anch essa, consente di abilitare o disabilitare il rettangolino di minimizzazione sul frame. Questo flag si sovrappone all effetto nativo di disegno 3D per i compenenti figli del frame. Abbiamo già incontrato questo flag nella creazione del frame. Crea un frame che l utente può ridimensionare. Questo è un altro flag noto e fa in modo che il frame resti in primo piano su tutte le altre finestre. Lo si può vedere in funzione con il Task Manager di Windows. È un altro flag noto e che rimuove l icona nell angolo del frame così come il relativo menù. Ha anche l effetto

131 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 122 di 150 collaterale di rimuovere i pulsanti di minimizzazione, massimizzazione e chiusura. wxthick_frame Come detto in precedenza non ha effetto ed è lo stesso di wxresize_border. General Style La proprietà General Style contiene gli stili che riguardano tutti controlli wxwindows. Dato che wxframe deriva da tale classe ha anche la possibilità di considerare questi stili. Per accedervi si clicca sulla piccola + vicino alla proprietà General Style nel Property Inspector. Apparirà l elenco completo come mostrato sotto. Figura 8.19 La lista completa di proprietà General Style Tutti questi stili sono valori Booleani. Se la proprietà è impostata a true il flag verrà aggiunto alla lista dei flag passati al frame alla sua creazione. Li vedremo uno per uno. Nome del Flag Funzionamento del flag o stile wxalways_show_sb wxclip_children wxdouble_border wxfull_repaint_on_resize wxhscroll Se la finestra ha delle barre di scorrimento tale flag fa sì che vengano permanentemente visualizzate anche quando non sono necessarie. Rimuove lo sfarfallio provocato dal ridisegno dei controlli figli. Non riguarda i frame. Ridisegna tutto il frame quando viene ridimensionato. Questo flag si deve usare solo quando ci sono problemi di ritracciamento. Impone alla finestra di visualizzare una barra di scorrimento orizzontale.

132 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 123 di 150 Figura 8.20 Il frame con una barra di scorrimento orizzontale. wxno_border wxno_full_repaint_on_resize wxraised_border wxsimple_border wxstatic_border wxsunken_border wxtab_traversal wxtransparent_window Questo non altera affatto il frame. Viene usato per default e disabilita il ridisegno completo della finestra durante il ridimensionamento. Non ha effetto sui frame. Non ha effetto sui frame. Non ha effetto sui frame. Non ha effetto sui frame. Abilita l attraversamento col tab. Questo flag impedisce alla finestra di rispondere agli eventi di disegno. Di solito si usa per i controlli figli che devono risultare trasparenti. Con i frame farà in modo che tutto il frame o parte di esso non venga disegnato. Figura 8.21 Un frame i cui bordi non sono stati completamente disegnati. wxvscroll Impone alla finestra di visualizzare una barra di scorrimento verticale. Figura 8.22 Un frame con una barra di scorrimento verticale wxwants_chars Questo flag indica che la finestra dovrebbe generare eventi di tastiera per tutti i tasti, anche per il tasto TAB che vengono di norma usati per la navigazione. Height È l altezza in pixel del frame. Lo imposteremo a 100.

133 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 124 di 150 Hidden Questa proprietà è al momento inutilizzata e si può ignorare. Icon Ci consente di scegliere un icona da mostrare sul frame. wxdev-c++ ha una piccola libreria di icone utilizzabili. Per aggiungere un icona bisogna cliccare sul pulsante a destra dela proprietà indicato con Figura 8.23 Modifica della proprietà Icon Con questo si aprirà una dialog come la seguente Figura 8.24 La dialog di caricamento dell immagine Si clicca sul pulsante e nella dialog aperta si naviga verso la cartella di installazione di wxdev- C++. Ci dovrebbe essere una cartella chiamata Icons. La si apra. Figura 8.25 La scelta del file

134 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 125 di 150 Per questo esempio si sceglierà Ufo.ico. Figura 8.26 L icona ufo Si seleziona Ufo.ico Si clicca su [Open] Quindi sulla dialog seguente si clicca [OK] Si noterà che l icona mostrata nel designer non è cambiata. Tuttavia, se compiliamo il programma vedremo che l icona verrà modificata. Si preme <F9> per compilare e lanciare. Figura 8.27 Il frame compilato con la nuova icona ID_Name Questa proprietà assegna un nome ad un valore costante usato per identificare il frame. Tale nome viene usato dal meccanismo di gestione degli eventi. Spesso è meglio accettare il nome pre-generato. Lasceremo stare questo valore. ID_Value Questa proprietà è il valore associato all ID_Name. Come menzionato l ID_Name è una costante uguale a questo valore. Anche qui spesso è meglio lasciarla stare. Lasceremo stare questo valore. Left Indica dove posizionare il lato sinistro del frame relativamente al bordo sinistro del monitor in pixels. Lo metteremo a 200

135 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 126 di 150 Name È il nome usato nella dialog di creazione del frame. Viene usato come nome della classe derivata da wxframe. In genere è meglio lasciarla stare, specie una volta che si comincia a scrivere il codice in quanto il compilatore usa tale nome per referenziare il frame in tutto il codice. Infatti se si tenta di modificarlo si riceverà il seguente avviso. Figura 8.28 Avviso sul fatto che modificando il nome del componente si potranno avere dei problemi Lasceremo stare questo valore. Size to contents Questa proprietà viene usata quando si aggiunge un sizer al frame. Fa in modo da generare la seguente riga di codice. GetSizer()->SetSizeHints(this); Questo dice al sizer si impostare la dimensione minima del frame alla sua dimensione minima. Poi ridimensiona il frame a tale dimensione. Title È una proprietà stringa corrispondente al titolo mostrato sul frame. Lo modificheremo in Hello World Figura 8.29 Il titolo del frame Tooltip Imposta una proprietà stringa che appare in un rettangolino quando il mouse si sofferma sul frame. Lo imposteremo a I Love wxwidgets Figura 8.30 Il tooltip sul frame compilato

136 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 127 di 150 Top Indica dove piazzare il bordo superiore del frame relativamente al bordo superiore del monitor in pixel. Lo metteremo a 200 Width Indica la larghezza del frame in pixel. Lo porremo a 200. Ora vediamo il frame completato in funzione Si preme <F9> per compilare ed avviare. Figura 8.31 Il progetto completato del frame Progetto di una Dialog Ora creeremo l equivalente wxdialog del progetto precedente. Per farlo Si va in File New Project Si avrà la stessa dialog per il nuovo progetto di prima. Si seleziona wxwidgets Dialog Si modifica il nome del progetto in DialogProject Ci si assicura di selezionare il pulsante radio vicino a C++ Project Si clicca su [OK] Verrà richiesta la locazione in cui salvare il progetto. Si crea una nuova cartella nella cartella Project La si chiama DialogProject Si entra in DialogProject Si clicca su [Save] Si vedrà una dialog di opzioni di progetto simile a quella del progetto del frame

137 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 128 di 150 Figura 8.32 La dialog delle impostazioni per il progetto wxdialog Ci sono alcune differenze rispetto alla dialog del progetto del frame. Il titolo è cambiato in New wxwidgets Dialog. I nomi della Classe e del File generati in automatico ora finiscono con Dlg anziché Frm e questo è tutto. Un punto da discutere è la voce No Parent. Questo non fa niente in un frame, ma è necessario nelle applicazioni delle dialog. Essa corrisponde al flag wxdialog_no_parent e dice che l applicazione di questa dialog non ha un frame per genitore. Si lasciano tutti i settaggi come sono Si clicca sul pulsante [Create] Figura 8.33 Il nuovo progetto della dialog

138 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 129 di 150 Una volta che il nuovo progetto è stato completamente creato sarà possibile notare un particolare cambiamento rispetto al progetto wxframe. Il colore della wxdialog è grigio-chiaro mentre mentre quello del wxframe è grigio scuro. Non è un errore. Il designer ha simulato la differenza visiva tra un frame ed una dialog nelle wxwidgets. Una dialog si può modificare esattamente come il frame. Guardando l elenco delle opzioni nel Property Inspector si noterà che sono esattamente le stesse. La sola differenza riguarda l elenco dei flags in Dialog Style. Figura 8.34 I flag di stile della dialog I flag di stile della dialog Nome del flag wxcaption wxclose_box wxdialog_ex_contexthelp wxdialog_no_parent wxmaximize_box wxminimize_box wxno_3d wxresize_border wxstay_on_top wxsystem_menu wxthick_frame Funzionamento del flag o stile Stesso significato del frame Stesso significato del frame Gli stessi commenti di wxframe_ex_contexthelp Dice all applicazione che questa dialog non ha una finestra genitrice. Stesso significato del frame Stesso significato del frame Stesso significato del frame Stesso significato del frame Stesso significato del frame Stesso significato del frame Stesso significato del frame

139 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 130 di 150 Impostazioni del progetto Per completare il progetto della dialog modificheremo le seguenti impostazioni Height si porta a 100 Icon la si cambia con Food.ico Title cambiare in Dialog Hello World ToolTip cambiare in wxdev-c++ rocks Width cambiare in 230 Si preme <F9> per compilare e lanciare Figura 8.35 Il progetto completo della dialog Un Progetto a Frame Multipli In questa sezione, e nella seguente, vedremo come aggiungere più frame e dialog ad un applicazione e come usarli. Per iniziare si crea un nuovo progetto wxwidgets Frame. Si apre wxdev-c++ Si seleziona File New Project Si seleziona wxwidgets Frame Si cambia il nome del progetto in MultipleFrames Si seleziona C++ Project Si clicca sul pulsante [OK] Si crea una nuova carella in Projects La si chiama MultipleFrames Si salva il progetto in tale cartella Sulla dialog successiva si clicca sul pulsant [Create] Siamo ora pronti per iniziare questo progetto. L intenzione è quella di aggiungere un nuovo frame ed una nuova dialog a tale progetto e mostrare il codice necessario per farli apparire. Prima di tutto abbiamo bisogno di un posto dove mettere il codice per aprire il secondo frame e la seconda dialog. Per farlo aggiungeremo due pulsanti al frame e ne useremo uno per aprire dei nuovi frame e l altro per aprire nuove dialog. Sulla tavolozza dei componenti si cerca il componente Button Si seleziona il componente button e si clicca sul frame Lo si ripete per un secondo pulsante Ora si dovrebbe avere un frame come questo

140 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 131 di 150 Figura 8.36 Il frame con i due controlli pulsante aggiunti Si modificano i due pulsanti come segue Per il pulsante chiamato WxButton1 Si immette nella proprietà Left il valore 3 Si immette nella proprietà Top il valore 3 Si immette nella proprietà Width il valore 100 Si immette nella proprietà Change il valore Open New &Frame Si seleziona il tab Events nel Property Inspector Figura 8.37 Il tab degli eventi Nel menù a discesa a fianco di OnClick si seleziona <Add New Function> Figura 8.38 L opzione della nuova funzione Si torna al form designer cliccando sul tab MultipleFramesFrm.wxform

141 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 132 di 150 Figura 8.39 La pagina del form designer Ora creiamo il secondo pulsante Il pulsante chiamato WxButton2 Si immette nella proprietà Left il valore 3 Si immette nella proprietà Top il valore 32 Si immette nella proprietà Width il valore 100 Si immette nella proprietà Label il valore Open New &Dialog Si seleziona il tab Events nel Property Inspector Nel menù a discesa a fianco di OnClick si seleziona <Add New Function> Si torna al form designer Si dovrebbe avere ora qualcosa di simile a questo Figura 8.40 Il frame Ora modifichiamo il frame Si immette nella proprietà With il valore di 200 Si immette nella proprietà Height il valore di 100 Infine ci si ritroverà con questo

142 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 133 di 150 Figura 8.41 Il frame dell aplicazione principale completo Aggiungeremo un altro frame ed una dialog all applicazione. Aggiungere un Nuovo Frame La prima cosa da fare è aggiungere un nuovo frame Si va nel menù delle opzioni File New New wxframe Si clicca sul pulsante [Yes] sulla dialog seguente Figura 8.42 Un nuovo frame al progetto di dialog Si riconoscerà la dialog seguente Si cambia il nome della Classe in SecondaryFrm Si cambia il nome del File in SecondaryFrm Si cambia il titolo in Secondary Frame Si clicca sul pulsante [Create] Sul frame appena generato si modificano le seguenti proprietà Height a 100 Width a 250 Si imposta il flag wxframe_no_taskbar a True Si aggiunge al frame un nuovo pulsante e si impostano le proprietà del pulsante come segue Left a 84 Top a 23 Label a &Close Sul pulsante Event Tab si crea un nuovo evento OnClick Nel codice appena generato si aggiunge la riga seguente Destroy(); La funzione Destroy() viene dalla classe base wxwindow. Si usa per chiudere in modo sicuro la finestra mentre si occupa degli eventi non processati. Ora si deve vedere come usare questo frame nel progetto esistente.

143 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 134 di 150 Nel file del codice sorgente MultipleFramesFrm.cpp si cercano le righe //Do not add custom headers //wxdev-c++ designer will remove them ////Header Include Start ////Header Include End Queste stanno nella sezione dove wxdev-c++ aggiunge tutti i files di intestazione (header) necessari. Dopo la riga ////Header Include End Si aggiunge la riga #include "SecondaryFrm.h" Questo aggiunge al file MultipleFramesFrm.cpp la dichiarazione della classe SecondaryFrm, consentendoci di usare tale classe nel codice del file MultipleFramesFrm.cpp. Ora scorriamo in basso nel codice di MultipleFramesFrm.cpp fino a trovare queste righe. /* * WxButton1Click */ void MultipleFramesFrm::WxButton1Click(wxCommandEvent& event) { // insert your code here } Aggiungiamo le seguenti righe in questo blocco di codice void MultipleFramesFrm::WxButton1Click(wxCommandEvent& event) { // Create a new frame SecondaryFrm * TempFrame = new SecondaryFrm(this); TempFrame->Show(); } La riga SecondaryFrm * TempFrame = new SecondaryFrm(this); Crea un istanza della classe SecondaryFrm e la assegna ad un puntatore temporaneo di tipo SecondaryFrm. Nel costruttore che crea tale istanza della classe MultipleFramesFrm mettiamo l argomento this. Il vantaggio è che alla chiusura o distruzione di una classe genitore anche tutti i figli vengono distrutti. Quindi quando vogliamo uscire da un applicazione basterà chiudere la finestra principale e non tutte. La seconda riga TempFrame->Show(); mostra il frame appena creato. Per vedere quello che abbiamo appena fatto Si preme <F9> per compilare ed avviare l applicazione Quindi si clicca sul pulsante [Open New Frame] Dovrebbe apparire la seguente finestra

144 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 135 di 150 Figura 8.43 Il frame secondario L aspetto di questo frame può sorprendere. Quello che si nota è che il pulsante ne riempie tutta l area. Non è un errore da parte di wxdev-c++, ma è una funzionalità delle wxwidgets. Quando un frame contiene un solo controllo questo ne ricopre l intera area. Si possono provare le seguenti funzioni Si provi ad usare il pulsante close per chiudere un Secondary Frame. Si provi a creare diversi Secondary Frames. (bisognerà spostarli) Si provi a chiudere il frame MultipleFrame. Si vedrà che i nuovi frame secondari non appaiono sulla taskbar. Si possono creare diverse istanze della stessa classe. Tutte le istanze verranno chiuse quando lo sarà il frame genitore. Continuiamo l esempio con l aggiunta di una finestra di dialogo. Aggiungere una nuova finestra di dialogo Così come abbiamo aggiunto un nuovo frame, aggiungiamo una nuova dialog. Si va in File New New wxdialog Click sul pulsante [Yes] Si immette SampleDlg in Class Name Si immette SampleDlg in File Name Si immette Sample Dialog in Title Si deseleziona la voce No Parent Si seleziona la voce Stay On Top Si clicca sul pulsante [Create] Si aggiungono due nuovi pulsanti alla dialog. Quindi si modificano le proprietà della dialog e dei pulsanti come segue. SampleDlg Height a 80 Width a 200 WxButton1 ID Name a wxid_ok Label a &OK Left a 12 Top a 14 WxButton2 ID Name a wxid_cancel Label a &Cancel Left a 102 Top a 14

145 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 136 di 150 Nel file MultipleFrames.cpp si cerca il file include di prima (Riga 16), e si aggiungono queste due righe sotto. #include "SampleDlg.h" #include <wx/msgdlg.h> La prima riga ci consente di usare la nuova dialog, la seconda di usare i messagebox. Si cerca poi questa funzione /* * WxButton2Click */ void MultipleFramesFrm::WxButton2Click(wxCommandEvent& event) { // insert your code here } La si modifica inserendovi il codice seguente. // insert your code here SampleDlg TempDlg(this); if(tempdlg.showmodal() == wxid_ok) { wxmessagebox("user Pressed OK"); } Prima di ulteriori spiegazioni Si preme <F9> per compilare ed avviare il programma. Fate delle prove col pulsante [Open New Dialog] e le dialog Figura 8.44 Il Sample Dialog compilato. Si dovrebbero aver scoperto delle cose interessanti. Quando appare una dialog non è più possibile interagire col frame Multiple Frames. Questo è dovuto alla chiamata della funzione ShowModal(), che disabilita tutte le parti del programma eccetto la dialog finché non viene chiusa. Si troverà anche che premendo i pulsanti [OK] o [Cancel] la dialog si chiude. Ma aspetta un minuto! Non abbiamo aggiunto il codice ai pulsanti per fare in modo che ciò accada. Quello che abbiamo fatto è consistito nel cambiare gli ID Name dei pulsanti. Con le finestre di dialogo ci sono dei valori preimpostati di ID Name che attivano funzioni incluse nella dialog, wxid_ok e wxid_cancel sono due di queste. Infine, si noterà che quando si chiude la dialog col pulsante [OK] un messaggio ci informa che è stato premuto OK. È il risultato di queste righe. if(tempdlg.showmodal() == wxid_ok) {

146 Chap1to8 - Programmare_Con_wxDev-C++.doc Pagina 137 di 150 } wxmessagebox("user Pressed OK"); Quando il pulsante provoca la chiusura della dialog la funzione ShowModal() restituisce il valore dell ID Name del pulsante. Si controlla che il valore restituito sia wxid_ok e se lo è si mostra il messaggio dato che solo il pulsante OK restituisce quel valore. Ci sarebbe altro da sapere sul wxframe e wxdialog e la documentazione di aiuto delle wxwidget è eccellente. Vale anche la pena di cercare wxtoplevelwindow e wxwindow in quanto tutte derivano da quest ultima. Ora che abbiamo imparato un po di cose sui frame e le dialog iniziamo la creazione di un applicazione di esempio. Applicazione di esempio Parte 1 - Lo schema A partire da questo capitolo ci accingiamo a progettare e costruire un applicazione. Sarà basata sul precedente esempio di editor HTML, aggiungendovi però molte funzioni che lo renderanno utile. Una schermata del programma completo è mostrata sotto. Figura 8.45 L editor HTML completato. In questo capitolo creeremo i frame e le dialog necessarie al programma. Nel capitolo 10 vedremo i vari componenti disponibili in wxdev-c++. Finiremo il capitolo aggiungendo le varie parti necessarie a rendere il programma simile alla figura. Nel capitolo 11 vedremo come e dove aggiungere il codice per farle funzionare. Quindi nel capitolo 12 vedremo i vari passi per fare un programma professionale pulito. Prima di iniziare si dovrà scaricare ed installare il TangoImages.devpak dalla sezione Bonus download section ( dal sito del progetto sourceforge. Senza indugiare andiamo a creare i frame. Creiamo un frame extra e 4 dialog. Invece di frenarvi vi dirò le opzioni necessarie per la creazione e la progettzione per ciascun frame/dialog. Se ci

KDiff3 è uno strumento per verificare differenze ed eseguire fusioni tra file e directory, il quale

KDiff3 è uno strumento per verificare differenze ed eseguire fusioni tra file e directory, il quale Manuale di KDiff3 Joachim Eibl Traduzione della documentazione -2004: Stelvio Rosset Aggiornamento e revisione della traduzione - 2005: Andrea Celli Revisione 0.9.87 (2005-01-30)

Dettagli

Il Tutorial per BlueJ

Il Tutorial per BlueJ Il Tutorial per BlueJ Versione 1.4 per BlueJ Versione 1.2.x Michael Kölling Mærsk Institute University of Southern Denmark Tradotto in italiano da Vito Di Viggiano, Orlando Demauro, Gianluca Leo, Gianpaolo

Dettagli

Roberto Giacomelli. Guida tematica alla riga di comando. g u It

Roberto Giacomelli. Guida tematica alla riga di comando. g u It Roberto Giacomelli Guida tematica alla riga di comando b g u It Gruppo Utilizzatori b b Italiani di b TEX 2014/03/14 v.1.2.3 Associati anche tu al g u It Fai click per associarti L associazione per la

Dettagli

Lezione 1. 1 All inizio di ogni capitolo vengono indicati gli obiettivi della lezione sotto forma di domande la cui risposta è lo scopo

Lezione 1. 1 All inizio di ogni capitolo vengono indicati gli obiettivi della lezione sotto forma di domande la cui risposta è lo scopo Lezione 1 Obiettivi della lezione: 1 Cos è un calcolatore? Cosa c è dentro un calcolatore? Come funziona un calcolatore? Quanti tipi di calcolatori esistono? Il calcolatore nella accezione più generale

Dettagli

Guida di Riferimento

Guida di Riferimento Guida di Riferimento Capitoli 1: STATISTICA: Panoramica Generale 1 2: Esempi Passo-Passo 9 Analitici 11 Gestione dei Dati 79 Installazioni Enterprise 107 3: Interfaccia Utente 139 4: Output delle Analisi

Dettagli

Dipartimento del Tesoro

Dipartimento del Tesoro Dipartimento del Tesoro POWER POINT AVANZATO Indice 1 PROGETTAZIONE DELL ASPETTO...3 1.2 VISUALIZZARE GLI SCHEMI...4 1.3 CONTROLLARE L ASPETTO DELLE DIAPOSITIVE CON GLI SCHEMI...5 1.4 SALVARE UN MODELLO...6

Dettagli

Joomla! 2.5 Guida per Principianti

Joomla! 2.5 Guida per Principianti Joomla! 2.5 Guida per Principianti 2 Informazioni sul libro... 5 Introduzione... 9 Vetrina... 16 Installazione... 25 Strutture e Condizioni... 37 Cosa c'è di nuovo in Joomla! 2.5?... 47 Gestione Contenuti...

Dettagli

NONNI SU INTERNET. Guida pratica all uso del PC. Fondazione Mondo Digitale

NONNI SU INTERNET. Guida pratica all uso del PC. Fondazione Mondo Digitale Nonni su Internet NONNI SU INTERNET Guida pratica all uso del PC Fondazione Mondo Digitale Guida pratica all uso del PC Questo manuale è a cura della Fondazione Mondo Digitale, con la supervisione del

Dettagli

Guida introduttiva. Capitolo 1 Cos'è OpenOffice.org

Guida introduttiva. Capitolo 1 Cos'è OpenOffice.org Guida introduttiva Capitolo 1 Cos'è OpenOffice.org Copyright Questo documento è pubblicato sotto copyright 2005 2008 dei collaboratori elencati nella sezione Autori. Il documento può essere distribuito

Dettagli

La finestra di Avvio di Excel

La finestra di Avvio di Excel Con Excel si possono fare molte cose, ma alla base di tutto c è il foglio di lavoro. Lavorare con Excel significa essenzialmente immettere numeri in un foglio di lavoro ed eseguire calcoli sui numeri immessi.

Dettagli

QuestBase. Crea, gestisci, analizza questionari, test, esami e sondaggi. Guida introduttiva

QuestBase. Crea, gestisci, analizza questionari, test, esami e sondaggi. Guida introduttiva QuestBase Crea, gestisci, analizza questionari, test, esami e sondaggi Guida introduttiva Hai poco tempo a disposizione? Allora leggi soltanto i capitoli evidenziati in giallo, sono il tuo bignami! Stai

Dettagli

Guida pratica di base

Guida pratica di base Adolfo Catelli Guida pratica di base Windows XP Professional Dicembre 2008 Sommario Accedere a Windows XP 4 Avviare Windows XP 4 Uscire da Windows XP 5 L interfaccia utente di Windows XP 6 Il desktop di

Dettagli

I.Stat Guida utente Versione 1.7 Dicembre 2010

I.Stat Guida utente Versione 1.7 Dicembre 2010 I.Stat Guida utente Versione 1.7 Dicembre 2010 1 Sommario INTRODUZIONE 3 I concetti principali di I.Stat 4 Organizzazione dei dati 4 Ricerca 5 GUIDA UTENTE 6 Per iniziare 6 Selezione della lingua 7 Individuazione

Dettagli

UNIVERSITA DEGLI STUDI DI TORINO WORD

UNIVERSITA DEGLI STUDI DI TORINO WORD WORD SOMMARIO 1. Muoversi nel testo... 1 2. Taglia, copia e incolla... 2 3. Aprire, salvare e chiudere... 3 4. Trovare e sostituire... 4 5. Visualizzare in modi diversi... 6 6. Formattare e incolonnare...

Dettagli

TeamViewer 8 Manuale Controllo remoto

TeamViewer 8 Manuale Controllo remoto TeamViewer 8 Manuale Controllo remoto Rev 8.0-12/2012 TeamViewer GmbH Kuhnbergstraße 16 D-73037 Göppingen www.teamviewer.com Indice 1 Informazioni su TeamViewer... 6 1.1 Informazioni sul software... 6

Dettagli

OJS in un ora. Introduzione a Open Journal Systems Versione 2.1. OJS in un ora. Ultimo aggiornamento: maggio 2007

OJS in un ora. Introduzione a Open Journal Systems Versione 2.1. OJS in un ora. Ultimo aggiornamento: maggio 2007 OJS in un ora Introduzione a Open Journal Systems Versione 2.1 Ultimo aggiornamento: maggio 2007 OJS in un ora 1 Open Journal Systems è un iniziativa di ricerca sviluppata dal Public Knowledge Project

Dettagli

TeamViewer 7 Manuale Controllo remoto

TeamViewer 7 Manuale Controllo remoto TeamViewer 7 Manuale Controllo remoto TeamViewer GmbH Kuhnbergstraße 16 D-73037 Göppingen teamviewer.com Indice 1 Informazioni su TeamViewer... 5 1.1 Informazioni sul software... 5 1.2 Informazioni sul

Dettagli

Mosè Giordano, Pietro Giuffrida. git commit -m"l A TEX" Una guida introduttiva a Git per progetti LATEX. g u It

Mosè Giordano, Pietro Giuffrida. git commit -ml A TEX Una guida introduttiva a Git per progetti LATEX. g u It Mosè Giordano, Pietro Giuffrida git commit -m"l A TEX" GIT 4 LATEX Una guida introduttiva a Git per progetti LATEX b g u It Gruppo Utilizzatori b b Italiani di b TEX v.1.0 del 2013/10/29 Licenza d uso

Dettagli

Introduzione al software ArcGIS 8.3

Introduzione al software ArcGIS 8.3 Introduzione al software ArcGIS 8.3 Data: Febbraio 2007 CopyLeft 2007 Niccoli Tommaso Indice 1. Introduzione ad ARCGIS... 4 1.1. Struttura di ArcView...5 1.2. Terminologia di ArcGIS...6 2. ArcCatalog...

Dettagli

Data warehouse.stat Guida utente

Data warehouse.stat Guida utente Data warehouse.stat Guida utente Versione 3.0 Giugno 2013 1 Sommario INTRODUZIONE 3 I concetti principali 4 Organizzazione dei dati 4 Ricerca 5 Il browser 5 GUIDA UTENTE 6 Per iniziare 6 Selezione della

Dettagli

IL LINGUAGGIO C. > Guida pratica alla programmazione. 3 a edizione

IL LINGUAGGIO C. > Guida pratica alla programmazione. 3 a edizione IL LINGUAGGIO C - > Guida pratica alla programmazione 3 a edizione Autore: BlackLight < blacklight@autistici.org > rilasciato sotto licenza Creative Commons, 2005-2008, 2010 1 Indice Cenni di programmazione...8

Dettagli

Ultimo aggiornamento.: 18/02/2006 Pagina 1 di 25

Ultimo aggiornamento.: 18/02/2006 Pagina 1 di 25 Introduzione al programma POWERPOINT Ultimo aggiornamento.: 18/02/2006 Pagina 1 di 25 Introduzione al programma POWERPOINT 1 1 Introduzione al programma 3 2 La prima volta con Powerpoint 3 3 Visualizzazione

Dettagli

Full Circle NUOVA SERIE! LINUX LABS : FILE SYSTEM - P. 1. full circle magazine n. 46 1 indice ^

Full Circle NUOVA SERIE! LINUX LABS : FILE SYSTEM - P. 1. full circle magazine n. 46 1 indice ^ Full Circle LA RIVISTA INDIPENDENTE PER LA COMUNITÀ LINUX UBUNTU NUMERO 46 - Febbraio 2011 LINUX LABS : FILE SYSTEM - P. 1 NUOVA SERIE! NUOVA SERIE - LIBREOFFICE PARTE 1 : INTRODUZIONE AL SOSTITUTO DI

Dettagli

L A TEX per l impaziente

L A TEX per l impaziente Lorenzo Pantieri L A TEX per l impaziente Un introduzione all Arte di scrivere con LATEX Gruppo Utilizzatori Italiani di TEX e LATEX http://www.guit.sssup.it/ Ottobre 2009 Lorenzo Pantieri: LATEX per l

Dettagli

lorenzo pantieri & tommaso gordini L arte di scrivere con

lorenzo pantieri & tommaso gordini L arte di scrivere con lorenzo pantieri & tommaso gordini L arte di scrivere con latex lorenzo pantieri & tommaso gordini L arte di scrivere con latex edizione 2012 Prefazione di Enrico Gregorio Gruppo Utilizzatori Italiani

Dettagli

per Scanner Serie 4800/2400

per Scanner Serie 4800/2400 Agosto, 2003 Guida d installazione e guida utente per Scanner Serie 4800/2400 Copyright 2003 Visioneer. Tutti i diritti riservati. La protezione reclamata per il copyright include tutte le forme, gli aspetti

Dettagli

I quaderni del MdS. Come funzionano le newsletter che funzionano. di Maria Cristina Lavazza

I quaderni del MdS. Come funzionano le newsletter che funzionano. di Maria Cristina Lavazza I quaderni del MdS Come funzionano le newsletter che funzionano di Maria Cristina Lavazza dicembre 2007 2007 Maria Cristina Lavazza. Tutti i diritti riservati. I'm an alien I'm a legal alien I'm an Englishman

Dettagli

ADOBE READER XI. Guida ed esercitazioni

ADOBE READER XI. Guida ed esercitazioni ADOBE READER XI Guida ed esercitazioni Guida di Reader Il contenuto di alcuni dei collegamenti potrebbe essere disponibile solo in inglese. Compilare moduli Il modulo è compilabile? Compilare moduli interattivi

Dettagli

Una introduzione a GCC

Una introduzione a GCC Una introduzione a GCC per i compilatori GNU gcc e g++ Brian Gough Prefazione di Richard M. Stallman 2 Una introduzione a GCC I dati di catalogazione per questo libro sono disponibili nella British Library.

Dettagli

Capitolo 2 Acquisire e gestire contenuti Kindle... 15

Capitolo 2 Acquisire e gestire contenuti Kindle... 15 Guida all uso di Kindle 2ª edizione 2 Sommario Sommario Sommario... 2 Capitolo 1 Operazioni preliminari... 5 Registra il tuo Kindle... 5 Comandi di Kindle... 5 Interfaccia schermo touch... 6 Tastiera...

Dettagli