Programmazione 1

Embed Size (px)

Citation preview

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 1Laboratorio del 3 Ottobre 2011

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 1

1.1 Breve Storia del Linguaggio CIl Linguaggio di programmazione C stato creato nel 1972 da Dennis Ritchie nei laboratori della Bell Telephone, con lo scopo di realizzare il sistema operativo Unix. Il C si diffuse rapidamente anche al di fuori dei laboratori della Bell e presto diverse aziende iniziarono a utilizzare versioni proprietarie di questo linguaggio, e nacquero diverse sottili differenze di implementazione che causano ancora oggi notevoli problemi agli sviluppatori. Per ovviare a questo problema nel 1983 listituto statunitense degli standard ANSI (American National Standards Institute) ha formato un comitato con lobiettivo di produrre una definizione del C chiara e indipendente dalla macchina, capace per di preservare lo spirito originale, quindi in modo di definire uno standard per il C che da allora si chiam ANSI C. Tranne poche eccezioni, tutti i compilatori moderni si conformano allo standard. Il C considerato un linguaggio di basso livello, questa definizione non peggiorativa ma significa semplicemente che il C adopera lo stesso tipo di oggetti usati da molti elaboratori, come caratteri, numeri e indirizzi, che possono essere combinati tramite gli operatori aritmetici e logici di cui si servono le macchine reali. Il C permette solo il controllo di un singolo flusso di computazione: condizioni, cicli, raggruppamenti e sottoprogrammi, ma non multiprogrammazione parallele, sincronizzazione o co-rutine.

1.2 Prima di iniziare a programmareQuando si cerca di risolvere un problema bene seguire una cerca metodologia: o o o o definire precisamente il problema, altrimenti non sar possibile individuare la soluzione ideare un piano risolutivo (algoritmo risolutivo) implementare lalgoritmo (metterlo in pratica) controllare i risultati in modo da verificare se il problema stato risolto o meno.

1.3 Ciclo di sviluppo del programmaIl ciclo di sviluppo di un programma si divide in diverse parti: o Creazione del Codice Sorgente: creare attraverso un editor di testo un file contenente una serie di istruzioni o comandi impiegati che combinati in una certa logica per istruire il computer in modo che esegua i compiti desiderati. Ad esempio una riga di codice sorgente C: printf(Forza Cesena!); Questa istruzione ordina al computer di stampare a video la scritta: Forza Cesena!. I file che contengono il sorgente di un programma scritto in C hanno estensione .c, ad esempio: pippo.c Creazione del Programma Sorgente: il computer non in grado di comprendere direttamente quello che lutente indica attraverso il sorgente C, ma necessita di istruzioni binarie o digitali in un particolare formato detto Linguaggio Macchina. Quindi prima che il programma possa funzionare

o

Pagina 2 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 1

su un computer, deve essere tradotto nel formato sorgente al linguaggio macchina. Questa traduzione effettuata da un programma chiamato compilatore che partendo dal sorgente produce un nuovo file su disco contenente le istruzioni in linguaggio macchina che corrispondono ai comandi impartiti in C. Queste istruzioni vengono chiamate codice oggetto e il file creato sul disco viene chiamato file oggetto. Il file oggetto ha estensione .obj. Creazione del File Eseguibile con il Linking: il linguaggio C costituito da un insieme di librerie che contengono il codice oggetto (ovvero pre-compilato) delle funzioni predefinite. Una funzione predefinita contiene codice C gi scritto e fornito in forma pronta per luso con il compilatore stesso. Ad esempio la funzione printf() utilizzata nellesempio precedente una funzione di libreria. Una funzione potrebbe essere vista come un robot da cucina che esegue determinate operazioni ogni volta che lo si attiva chiamandolo per nome. Queste particolari funzioni svolgono compiti frequenti come la visualizzazione di informazioni sullo schermo o la lettura di dati da tastiera. Se il proprio programma contiene alcune di queste funzioni (difficilmente si pu scrivere un programma di qualche utilit senza utilizzarne almeno una), il file oggetto prodotto a partire dal sorgente deve essere combinato con quello delle funzioni di libreria per generare un programma eseguibile. Questo processo detto Linking ed portato a termine da un programma chiamato Linker. Completamento del ciclo di sviluppo: una volta compilato e linkato il proprio programma possibile eseguirlo. Se dallesecuzione del programma non si ottengono i risultati aspettati bisogna tornare indietro al primo passo e individuare gli errori.

o

o

1.4 Primi passiProviamo a scrivere il primo programma che stampi a video la scritta: Forza Cesena!. Per risolvere questo problema dobbiamo essere in grado di redigere il testo del programma, compilarlo con successo. caricarlo, eseguirlo e scoprire dove finito il risultato. Questi sono meccanismi essenziali per capire non solo come programmare con il linguaggio C ma con qualsiasi linguaggio di programmazione. Il programma che risolve lesercizio il seguente: #include int main() { printf(Forza Cesena!\n); return 0; } Il programma una volta compilato ed eseguito (salvo errori!!) dar come risultato: Forza Cesena! Un programma in C di qualunque lunghezza consiste di funzioni e variabili. Una funzione consiste in un insieme di istruzioni o comandi che specificano quali operazioni devono essere effettuate, mentre le variabili memorizzano i valori usati durante lesecuzione del programma. Nellesempio precedente viene definita la funzione main(), di norma si liberi di assegnare qualsiasi nome alle funzioni ma il caso di main particolare in quanto tutti i programmi scritti in C inizieranno con la chiamata alla funzione main(). Quindi ogni programma dovr avere una funzione main.

Pagina 3 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 1

Per svolgere il proprio lavoro la funzione main chiamer altre funzioni in aiuto, alcune scritte dal programmatore altre presenti nelle librerie cui si ha accesso. La prima riga del programma: #include dice al compilatore di includere le informazioni sulla libreria standard per linput/output. Tutte le istruzioni di inclusione delle librerie devono comparire allinizio del programma. Tutte le funzioni hanno un inizio ed una fine, per individuare allinterno del codice dove una funzione inizia e finisce si utilizzano rispettivamente due marcatori: { (parentesi graffa aperta) e } (parentesi graffa chiusa). (premere pulsanti ALT GR + SHIFT + QUADRA APERTA per parentesi graffa aperta e premere ALT GR + SHIFT + QUADRA CHIUSA per parentesi graffa chiusa). Allinterno delle graffe presente il corpo della funzione (insieme di istruzioni eseguite alla chiamata della funzione). Nel esempio precedente allinterno del corpo della funzione main() troviamo 2 righe di codice, in paricolare la prima consiste nella chiamata della funzione printf() printf(Forza Cesena!\n); Una funzione chiamata attraverso il suo nome, seguito da un elenco degli argomenti racchiuso tra parentesi tonde. Gli argomenti sono il metodo di comunicazione tra le varie funzioni in modo che la funzione chiamante riesca a fornire alla funzione chiamata un insieme di valori detti argomenti. Nel nostro esempio la funzione si chiama printf e largomento passato Forza Cesena!. Si tratta di una funzione che produce (in gergo si dice anche stampa) a video o in uscita dei dati, in questo caso in particolare leffetto finale quello di visualizzare a schermo la scritta. Una successione di caratteri comunemente detta stringa di caratteri ed individuata da un doppio apice in apertura e in chiusura. La sequenza \n che compare nella stringa una notazione del C per accedere alla newline, che ha effetto di spostare in avanti di una riga i dati in uscita (in poche parole di andare a capo!). Senza il \n non si va a capo. La funzione printf() non fornisce in automatico landata a capo. Quindi il programma di prima poteva essere scritto anche nel seguente modo: #include int main() { printf(Forza ); printf(Cesena!); printf(\n); return 0; } Listruzione return molto importante in quanto consente di restituire un parametro alla funzione chiamante. Nel nostro caso il chiamate il sistema operativo, il nostro programma terminate le proprie operazioni restituisce il valore 0 (zero) informando il sistema operativo che tutte le operazioni si cono svolte senza errori.

1.4.1 Le istruzioniDa notare che nel programma ogni istruzione presente allinterno della funzione main() termina con un punto e virgola. Unistruzione un comando completo che indica al computer di eseguire un particolare compito. Le istruzioni in C terminano sempre con un punto e virgola (tranne il caso delle direttive del preprocessore #define o #include).

Pagina 4 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comQuindi scrivere x = 1 + 3; equivale a scrivere: x = 1 + 3; Mentre scrivere printf(ciao a tutti); non equivale a printf( Ciao a tutti); in quanto genera un errore. Mentre scrivere printf( Ciao\ a tutti);

Corso di Programmazione A.A. 2011-12

Dispensa 1

non genera errore in quanto per andare a capo con una stringa possibile utilizzare il carattere (\) di barra inversa.

1.4.2 La funzione printf()La stringa di formato della funzione printf() specifica la modalit di formattazione delloutput e ha tre componenti possibili: o o o Il testo letterale, che viene visualizzato esattamente come viene introdotto nella stringa Un indicatore di conversione formato da un segno di percentuale(%) seguito da un carattere. Una sequenza di escape che consente di produrre comandi di formattazione particolari. Le sequenze di escare sono formate da una barra inversa (\) seguita da un carattere. Nella sequenza precedente \n una sequenza di escare chiamata carattere di nuova riga, che significa a capo. Le sequenze di escare sono utilizzate per stampare caratteri particolari.Comando Descrizione

\t \b \ \\ \n \? \" \a

Tabulazione blank space Apice singolo (come carattere stampato) Barra inversa (come carattere stampato) Avanzamento di riga (a capo) Punto interrogativo (come carattere stampato) I doppi apici stampati (come carattere stampato) Segnale acustico

Pagina 5 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 1

1.4.3 La funzione system()La funzione system() consente di eseguire comandi della shell del sistema operativo. Per poterla utilizzare allinterno del programma necessario includere la libreria stdlib.h. Il testo letterale che viene passato tra parentesi tonde (argomento della funzione) individua il comando che deve essere eseguito. Ad esempio per attivare il comando pause del sistema operativo DOS: system(pause);

1.5 Come scrivere un programmaLa leggibilit del codice di fondamentale importanza, anche il sorgente di un programma che esegue pochi compiti potrebbe richiedere la scrittura di diverse migliaia di righe di codice quindi esistono diverse regole o consuetudini che vale la pena rispettare fin dallinizio con molta rigorosit e pignoleria.

1.5.1 Indentare il programmaIndentare un programma significa mettere in evidenza nel testo del programma mediante opportuni incolonnamenti, i gruppi di istruzioni che svolgono un problema comune, in modo da evidenziare la funzionalit calcolata da ogni gruppo di istruzioni, rispetto al resto del programma.

1.5.2 Commentare il programmaLe frasi prodotte nel corso del progetto per descrivere lalgoritmo a vari livelli di raffinamento possono comparire nella versione definitiva del sorgente sotto forma di commenti. Anche se lalgoritmo stato progettato utilizzando direttamente il linguaggio di programmazione a disposizione conveniente inserire in ogni caso dei commenti in punti particolari del programma che spieghino cosa il programma fa in quei punti, indipendentemente da come lo fa, cio dalla particolare strategia scelta. I commenti non vengono interpretati dal compilatore e quindi non vanno ad incidere sulloperativit o sulla dimensione del file eseguibile finale. Un commento pu essere scritto su una o pi righe: /* Commento su una sola riga*/ /* Commento che occupa pi di una riga*/ printf(Forza Cesena!); /*Commento che occupa parte di una riga*/

Esiste anche una sintassi diversa per commentare i propri programmi utilizzando una doppia barra: // questa riga un commento printf(Forza Cesena!); // il commento inizia con la doppia barra

La doppia barra indica che il testo della riga da considerarsi come un commento. Anche se molti compilatori C supportano questo tipo di sintassi bene evitarla quando necessario garantire aperta portabilit.

Pagina 6 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 1

1.5.3 Usare nomi di variabili autoesplicativiPer spiegare il ruolo delle variabili, oltre che usare commenti, possiamo scegliere nomi che gi da soli ne spieghino il ruolo. Per esempio il nome della variabile stipendioMensile autoesplicativo, la stessa variabile se fosse stata chiamata xMk il programma sarebbe risultato meno comprensibile ma ugualmente funzionante.

1.5.4 Produrre la documentazione nel corso stesso del progettoE importantissimo scrivere la documentazione durante lo sviluppo del progetto in quanto documentando le decisioni nello stesso momento in cui vengono prese, si certi della efficacia e della completezza della documentazione. E storia di ogni giorno che la documentazione venga prodotta solo al termine del progetto frettolosamente e senza rispettare alcuno standard.

Pagina 7 di 7

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 2Laboratorio

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 2

2.1 La direttiva #includeLa direttiva #include ordina al compilatore C di inserire il contenuto di un file di inclusione nel programma in fase di compilazione. Un file di inclusione un file che contiene le informazioni richieste dal programma o dal compilatore. Sono molti i file di questo tipo (detti anche file di intestazione) supportati dal compilatore. Non mai necessario modificare le informazioni contenute in questi file, ed per questo che vengono mantenuti separati dagli altri file. I file di inclusione dovrebbero avere tutti lestensione .H (ad esempio stdio.h). La direttiva #include significa aggiungi al programma il contenuto del file .h

2.2 La funzione puts()Per visualizzare i messaggi testuali possibile utilizzare la funzione puts(), anche se questultima non pu stampare valori numerici delle variabili. La funzione puts() richiede come argomento una sola stringa che viene visualizzata con laggiunta automatica dei un a capo. Ad esempio listruzione: puts(Ciao a tutti); svolge lo stesso compito di printf(Ciao a tutti\n); Nella stringa passata alla funzione puts() possibile specificare le sequenze di escare che avranno lo stesso effetto di quelle relative alla funzione printf(). La funzione inclusa nella libreria stdio.h.

2.3 La funzione exit()Questa funzione termina il programma e restituisce il controllo al sistema operativo; richiede un solo argomento di tipo intero che viene passato al sistema operativo per indicare il successo o il fallimento del programma. Sintassi: exit(status); Se status vale 0, indica che il programma terminato normalmente, Il valore 1 indica che il programma terminato con un errore. Il valore restituito solitamente interrogato da sistema operativo. Per utilizzare exit() il programma deve includere il file stdlib.h che definisce anche due costanti simboliche da utilizzare come argomenti: #define EXIT_SUCCESS #define EXIT_FAILURE 0 1

Pagina 2 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 2

2.4 La memoria del ComputerI computer utilizzano la memoria ad accesso veloce (RAM) per archiviare le operazioni su cui lavorano. La RAM (Random Access Memory) composta da circuiti integrati che si trovano sulla scheda madre del computer e le informazioni in essa salvate vengono cancellate ogni volta che si spegne il computer. Da qui la definizione che la RAM una memoria volatile. E possibile riscrivere le informazioni allinterno della RAM ogni volta che so vuole. Ogni computer ha un certo quantitativo di memoria installata, la dimensione si misura in kbyte (Kb). Il byte lunit di misura fondamentale delle memorie informatiche. Per farsi un idea del quantitativo di memoria necessario allarchiviazione di alcune tipologie di dati ecco alcuni esempi:Dato Byte Richiesti

La lettera b Il numero 450 il numero 14.3124 La frase il mondo non crea eroi Una pagina di testo

1 2 4 22 Circa 3000

La RAM di un computer organizzata in modo sequenziale: quindi ogni byte messo si seguito allaltro. Ogni byte ha un indirizzo unico attraverso cui viene identificato, che lo distingue da tutti gli altri byte della memoria. Gli indirizzi vengono assegnati dalle locazioni di memoria di ordine progressivo, cominciando dallindirizzo 0. La RAM ha diversi utilizzi in particolare per quanto ci riguarda essa permette di memorizzare i dati. I dati sono le informazioni su cui lavorano i programmi: tutte le informazioni che il programma deve eseguire vengono memorizzate allinterno della RAM durante lesecuzione.

2.5 Le variabiliUna variabile un nome simbolico che si assegna a una allocazione di memoria utilizzata per la memorizzazione dei dati. Le variabili devono essere definite prima di essere utilizzate; la definizione di una variabile indica al compilatore il nome della variabile e il tipo di dati che destinata a contenere.

2.5.1 I nomi delle variabiliI nomi delle variabili in C devono seguire le seguenti regole: o o I nomi possono contenere lettere, numeri e il trattino di sottolineatura (_) I primo carattere di un nome DEVE essere una lettera. Anche il trattino di sottolineatura pu essere utilizzato come primo carattere, ma dato che in questo caso la variabile viene trattata in modo particolare dal compilatore, per il momento il caso di non utilizzarlo come carattere iniziale. Le lettere maiuscole e minuscole sono trattate come entit differenti. Quindi i nomi pippo e Pippo si riferiscono a due variabili differenti. Le parole chiave del C on possono essere utilizzate come nomi di variabili. Le parole chiave sono istruzioni del linguaggio C.Nome variabile

o o

Ecco degli esempi corretti e non di nomi di variabili: Numero valido

Pagina 3 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comstipendio_mensile g7t7_rfg7 _1978_compleanno testo#progetto double 9vincitori valido valido valido ma sconsigliato Sbagliato: contiene il carattere # Sbagliato: una parola chiave del C Sbagliato: il primo carattere un numero

Corso di Programmazione A.A. 2011-12

Dispensa 2

In C generalmente si utilizzano nomi di variabili scritte tutte in minuscolo (anche se non richiesto dal linguaggio); normalmente i nomi scritti in maiuscolo sono riservati alle costanti. Fate molta attenzione in quanto la stessa lettera in maiuscolo e minuscolo viene considerata diversa. Per la maggior parte dei compilatori i nomi delle variabili non possono superare i 31 caratteri; anche se possibile utilizzare nomi pi lunghi il compilatore considera solo i primi 31. Il nome della variabile aiuta a rendere pi chiaro il suo utilizzo allinterno del programma per il programmatore. Al compilatore non fa differenza avere una variabile con nome y o stipendio_mensile, nel primo caso per il significato della variabile non sarebbe stato cos chiaro per chi avesse letto il codice sorgente come invece accade nel secondo caso.

2.5.2 Tipi di variabiliI valori che un programma pu memorizzare possono essere molto diversi e quindi richiedono spazi in memoria diversi per poterli memorizzare. Il C prevede un numero ristretto di tipi di dati fondamentali:Tipo di dato Dimensione Descrizione

char int float double

1 byte 2 byte* 4 byte 8 byte

contiene un carattere dellambiente in cui risiede il compilatore un intero, solitamente pari alla dimensione naturale degli interi sulla macchina in cui risiede il compilatore, quindi non detto che la dimensione sia pari a 2 byte numero con virgola mobile, con precisione singola numero con virgola mobile, con precisione doppia

Rappresentazione a virgola fissa: Dato che in un bit non rappresentabile la virgola il metodo pi semplice per rappresentare numeri frazionari quello di scegliere arbitrariamente la posizione della virgola (ad es. se si sceglie di usare 4 bit per la parte intera e 4 per la parte frazionaria) Rappresentazione in virgola mobile: Esistono innumerevoli modi per rappresentare numeri in virgola mobile ma il sistema pi utilizzato lo standard IEEE P754; questo metodo comporta l'utilizzo della notazione scientifica, in cui ogni numero identificato dal segno, da una mantissa e dall'esponente. In aggiunta possibile qualificare questi tipi di dati in vari modi utilizzando i prefissi: o o o short long unsigned

Gli attributi short e long si applicano solo agli interi. Lidea che short e long denotino interi di diverse lunghezze. Dove possibile int invece di solito la grandezza naturale di riferimento per una macchina.

Pagina 4 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 2

Lattributo unsigned (privo di segno) pu essere applicato a tutte le tipologie, i numeri unsigned sono sempre positivi o al pi nulli. il tipo long double denota numeri con virgola mobile a precisione multipla, come per gli interi al dimensione degli oggetti definita dallimplementazione. Tutte le variabili per default sono di tipo signed. Tipi di dati supportati:Tipo Variabile Parola chiave Byte Intervallo

Carattere Intero* Intero corto* Intero lungo* Carattere senza segno Intero senza segno Intero lungo senza segno Variabile mobile con precisione singola Variabile mobile con precisione doppia *dipende dalla macchina

char int short int (o anche solo: short) long int (o anche solo: long) unsigned char unsigned int unsigned long int (o anche: unsigned long) float double

1 2 2 4 1 2 4 4 8

da -128 a 127 da -32768 a 32767 da -32768 a 32767 da -2147483648 a 2147483647 da 0 a 255 da 0 a 65535 da 0 a 4294967295 da 1.2E-38 a 3.4E308 da 2.2E-38 a 1.8E3082

La dimensione dei tipi di dato pu variare a seconda della piattaforma utilizzata, lo standard ANSI ha definito cinque regole che ogni compilatore tenuto a rispettare a prescindere dalla macchina su cui opera: 1. La dimensione di un char sempre un byte 2. La dimensione di un short minore o uguale a quella di un int 3. La dimensione di un int minore o uguale ad un long 4. La dimensione di un unsigned uguale a quella di un int 5. La dimensione di un float minore o uguale a quella di un double

2.5.3 Dichiarazione di una variabilePrima di poter utilizzare una variabile in un programma C necessario dichiararla. La dichiarazione indica al compilatore il nome e il tipo di una variabile e opzionalmente il valore di inizializzazione da assegnare. Se il programma tenta di utilizzare una variabile non dichiarata il compilatore genera un errore. La sintassi per dichiarare una variabile: tipoDato nomeVariabile; Dove con tipoDato si specifica il tipo di variabile e deve essere una delle parole chiave definite nel paragrafo precedente. Il nomeVariabile indica il nome della variabile e deve rispettare le regole descritte in precedenza. Alcuni esempi di dichiarazione di variabili: int annoNascita;

Pagina 5 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comchar iniziale; int numeroScarpa, anni; double percentuale; float valore; int conta, numero, inizio; Alcuni esempi di dichiarazione con gli attributi: unsigned unsigned unsigned long int unsigned int valoreNumerico; char carattere; double percentualePositiva; valore; long int valoreIntero;

Corso di Programmazione A.A. 2011-12

Dispensa 2

2.5.4 Assegnare un valore ad una variabileQuando si dichiara una variabile si chiede al compilatore di riservare dello spazio in memoria per la stessa. Il valore presente in questo spazio non prevedibile, potrebbe essere qualsiasi cosa. Quindi bene associare alla variabile un valore certo prima di utilizzarla. Questa operazione pu essere fatta in diversi modi: dopo la dichiarazione o contemporaneamente alla dichiarazione. int annoNascita; annoNascita = 1978 Loperatore uguale (=) serve per associare un valore alla variabile. La variabile sempre posta a sinistra dalloperatore. In C il significato di annoNascita = 1978 significa: assegnare il valore 1978 alla variabile di nome annoNascita e NON annoNascita uguale a 1978. Per dichiarare una variabile durante la dichiarazione: int annoNascita = 1978; double percentuale = 0.01; double tasso = 22.4; Bisogna fare attenzione a non inizializzare una variabile con un valore al di fuori dellintervallo consentito dal tipo. Ecco per esempio due dichiarazioni non valide: int peso = 1000000000000; unsigned int valore = -2132; Attenzione perch il compilatore C non individua questo tipo di errori, il programma potrebbe essere compilato e linkato senza errori ma potrebbe dare risultati inaspettati in fase di esecuzione.

2.6 La funzione sizeof()La funzione restituisce il numero di byte necessari per il tipo di dato passato come argomento alla funzione. La sintassi della funzione:

Pagina 6 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comsizeof(tipoDato); Un esempio di utilizzo: #include int main() { printf("\n printf("\n printf("\n printf("\n printf("\n return 0; } Il programma una volta compilato ed eseguito dar come risultato: numero intero (int) byte: 4 numero intero lungo (long int) byte: 4 carattere (char) byte: 1 numero con virgola (float) byte: 4 numero con virgola (double) byte: 8

Corso di Programmazione A.A. 2011-12

Dispensa 2

numero intero (int) byte: %d", sizeof(int)); numero intero lungo (long int) byte: %d", sizeof(long int)); carattere (char) byte: %d", sizeof(char)); numero con virgola (float) byte: %d", sizeof(float)); numero con virgola (double) byte: %d", sizeof(double));

Pagina 7 di 7

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 3Laboratorio

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 3

3.2 Output formattato: printf()Per visualizzare un numero, occorre utilizzare le funzioni per loutput formattato. La funzione printf() accetta un numero variabile di argomenti, come minimo uno. Il primo e unico argomento richiesto la stringa di formato, che indica come formattare loutput. Gli argomenti opzionali sono variabili ed espressioni di cui visualizzare i valori Ad esempio: Listruzione printf(Ciao a tutti!); visualizza il messaggio: Ciao a tutti sullo schermo. In questo caso utilizzato un unico argomento: la stringa di formato che contiene la stringa letterale da visualizzare sullo schermo Listruzione printf(%d,i); visualizza il valore della variabile intera i. La stringa di formato contiene soltanto lindicatore %d, che indica di mostrare un singolo intero decimale. Il secondo argomento il nome della variabile Listruzione printf(%d pi %d uguale %d,a, b, a+b); visualizza (supponendo che le variabili a e b contengano rispettivamente 2 e 3) 2 pi 3 uguale 5 sullo schermo. In questo caso vi sono quattro argomenti: una stringa di formato contenente il testo letterale e indicatori di formato, due variabili ed unespressione di cui visualizzare i valori. Zero, uno o pi comandi di conversione che indicano come visualizzare un valore dellelenco degli argomenti. Un comando di conversione costituito da % seguito da uno o pi caratteri I caratteri che non fanno parte di un comando di conversione sono visualizzati cos come sono.

La stringa di formato di printf() pu contenere quanto segue:

Di seguito sono descritti i componenti del comando di conversione. Quelli tra parentesi sono opzionali: %[modificatore][campoMinimo][precisione][modificatoreLunghezza]specificaConversione dove: modificatore pu essere una combinazione (in qualsiasi ordine) dei seguenti simboli (tra parentesi i simboli): o o (-) il risultato della conversione e' allineato a sinistra all' interno del campo definito da campoMinimo, il default e' l' allineamento a destra (+) specifica che il segno davanti al numero verr sempre stampato. Il risultato di conversioni di tipi con segno inizia con + (se positivi) o - (se negativi); il default e' che il segno (-) appare solo davanti ai negativi (spazio) inserisce uno spazio davanti al valore se il primo carattere non e' un segno (#) formato alternativo (con piccole variazioni) per la maggior parte delle specifiche di conversione Se il carattere di conversione e' o (ottale) e se il valore da convertire e' diverso da zero, il primo carattere stampato e' 0. Se il carattere di conversione e' x o X (esadecimale) e se il valore da convertire non e' nullo, i primi caratteri stampati saranno 0x o 0X a seconda che la direttiva sia x o X. 0 (zero) il campo viene riempito con zeri invece che con spazi (il default)

o o

o

campoMinimo: se il valore convertito ha meno caratteri del campo questo viene riempito da spazi, il valore di campoMinimo puo' essere un intero o *. In quest' ultimo caso il valore deve essere un intero inserito nella lista degli argomenti della printf, subito prima dell' espressione interessata da questo formato.

Pagina 2 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com precisione: un valore nella forma .n (con n intero oppure * se viene letto nella lista degli argomenti) dove n e' il : o o o minimo numero di cifre per le specifiche i,d,o,u,x,X minimo numero di cifre dopo il punto decimale per le specifiche a,A,e,E,f,F massimo numero di cifre significative per le specifiche g,G

Corso di Programmazione A.A. 2011-12

Dispensa 3

modificatoreLunghezza: dichiara che la successiva specifica di conversione deve essere applicata a un sottotipo intero particolare modificatore. La lettera h seguita da uno dei caratteri di conversione d, i, u, o, x o X indica che l'argomento e' uno short int o uno unsigned short int. Il modificatore l (elle) con gli stessi caratteri di conversione, indica che l'argomento e' un long int o uno unsigned long int. Il modificatore L seguito da uno dei caratteri di conversione e, E, f, g o G indica che l'argomento e' un long double il successivo specificatore (i o d) si applica ad una espressione o signed o unsigned char o signed o unsigned short int o signed o unsigned long int o signed o unsigned long long int specificaConversione: lunico obbligatorio (a parte %) Sotto sono elencati i caratteri di conversione ed il loro significato: d, i u o x, X c e, E Visualizza un intero con segno in notazione decimale Visualizza un intero senza segno di notazione decimale Visualizza un intero in notazione ottale senza segno Visualizza un intero in notazione esadecimale senza segno. Si utilizza x minuscolo per luotput minuscolo e X maiuscolo per loutput maiuscolo Visualizza un singolo carattere (indicato dal codice ASCII) Visualizza un float o un double in notazione scientifica ( ad esempio 123.45 visualizzato come 1.234500e+002) sei cifre sono visualizzate a destra del punto decimale a meno che non sia specificata unaltra precisione con lindicatore f. si utilizzano e o E per loutput minuscolo o maiuscolo Visualizza un float o un double in notazione decimale (ad esempio 123.45 visualizzato come 123.450000). Sei cifre sono visualizzate a destra. Visualizza una stringa Visualizza il carattere %

f s %

La funzione printf() restituisce un valore che individua il numero di caratteri stampati, se il valore negativo segnala un errore.

3.3 Le IstruzioniUn istruzione un comando completo che indica al computer di eseguire un particolare compito. In generale in C le istruzioni vengono scritte una per ogni riga anche se alcune possono occupare anche pi righe. Tutte le istruzioni in C (eccetto le direttive #define, #include...) devono terminare con un punto e virgola (;).

Pagina 3 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 3

3.3.1 Spazi bianchi e istruzioniCon spazi bianchi ci si riferisce ai veri e propri spazi, ai caratteri di tabulazione e alle righe vuote presenti nel codice sorgente. Il compilatore C non considera gli spazi bianchi e quando legge un istruzione dal codice sorgente cerca il carattere terminatore (il punto e virgola) ignorando tutti gli spazi bianchi presenti. Quindi listruzione: y=4+3; equivalente a quella seguente: y = 4 + 3;

che a sua volta equivalente a: y = 4 + 3; In questo modo viene lasciata al programmatore la scelta sulla modalit di formattazione del proprio codice. Comunque non consigliato utilizzare una formattazione come nellultimo esempio: le istruzioni dovrebbero essere introdotte una per riga seguendo uno schema standard per la spaziatura delle variabili e degli operatori. Guardare i vari esempi inseriti nelle dispense o i sorgenti in allegato per rendersi conto di come poter formattare il proprio codice. Il C ignora gli spazi bianchi eccetto quando questi si trovano allinterno di costanti stringa letterali: infatti in questo caso gli spazi vengono considerati come parti delle stringhe (quindi come caratteri della stringa). Una stringa una sequenza di caratteri e in particolare le costanti stringhe letterali sono stringhe racchiuse tra doppi apici che vengono interpretate dal compilatore in maniera assolutamente letterale, spazi compresi. Quindi per esempio listruzione (anche se solitamente non usata): printf( Forza Cesena! ); corretta, mentre quella che segue genera un errore in fase di compilazione: printf(Forza Cesena); Per andare a capo in unistruzione, quando ci troviamo in corrispondenza di una costante stringa letterale occorre utilizzare il carattere barra inversa (\) prima dellinterruzione. La forma corretta per lesempio sopra riportato quindi sar: printf(Forza\ Cesena);

3.3.2 Istruzioni nulleSe si inserisce un punto e virgola da solo su una riga si ottiene istruzione nulla cio unistruzione che non esegue alcuna operazione.

3.3.3 Istruzioni composteUnistruzione composta, solitamente chiamata blocco, un gruppo di due o pi istruzioni C racchiuse tra parentesi graffe. Ad esempio la porzione di codice che segue un blocco: { printf(Forza Cesena!);

Pagina 4 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comprintf(Devi vincere); }

Corso di Programmazione A.A. 2011-12

Dispensa 3

In C i blocchi possono essere utilizzati in qualsiasi punto in cui sia possibile utilizzare unistruzione singola. Le parentesi graffe possono essere posizionate in qualsiasi punto ad esempio: {printf(Forza Cesena!); printf(Devi vincere);} comunque si consiglia di posizionare le graffe su righe diverse, mettendo cos in evidenza linizio e la fine del blocco. In questo modo, oltre che rendere il codice pi leggibile, possibile accorgersi se ne stata dimenticata qualcuna.

3.4 Le EspressioniIn C unespressione una qualsiasi cosa che deve essere valutata come un valore numerico. Le espressioni in C possono avere qualsiasi livello di complessit.

3.4.1 Espressioni SempliciLe espressioni pi semplici consistono di un unico oggetto, ad esempio una variabile, una costante letterale o simbolica. Le costanti letterali vengono valutate secondo il loro valore, le costanti simboliche invece con il valore assegnato loro dalla direttiva #define, le variabili vengono valutate con il valore assegnate loro dal programma.Espressione Descrizione

TASSO 28 stipendio 3.678

Una costante simbolica Una costante letterale Una variabile Una costante letterale

3.4.2 Espressioni ComplesseLe espressioni complesse consistono di pi espressioni semplici combinate tra di loro attraverso degli operatori. Per esempio: 3 + 9 un espressione formata dalle due costanti letterali 3 e 9 e dalloperatore somma +. Lespressione 3 + 9 viene valutata come 10. Si possono scrivere anche espressioni molto pi complesse: 3.78 + 56 stipendio * mesi / giorni Quando unespressione contiene pi operatori, come nellesempio sopra riportato, il risultato dipende dalla precedenza degli operatori. Consideriamo la seguente espressione: y = b + 17; in questo caso nellistruzione viene calcolato il valore dellespressione b + 17 e viene assegnato il risultato alla variabile y. A sua volta listruzione y = b + 17 unaltra espressione che ha il valore nella variabile a sinistra delluguale, quindi possibile anche la scrittura: k = y = b + 17;

Pagina 5 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 3

in questo caso il risultato viene assegnato sia a y che a k, in particolare prima viene valutata lespressione b + 17, il suo valore assegnato alla variabile y, ed in fine il valore di y assegnato alla variabile k. Quindi alla fine dellespressione k e y avranno lo stesso valore. In C sono possibili anche espressioni di questo tipo: k = 8 + (y = 3 + 4); in questo caso dopo lesecuzione dellistruzione la variabile y avr il valore 7, mentre la variabile x il valore 15. In questo caso per le parentesi sono essenziali per la corretta compilazione dellistruzione.

3.5 Gli OperatoriUn operatore un simbolo che indica al linguaggio di eseguire unoperazione, o unazione su uno o pi operandi. In C tutti gli operatori sono visti come delle espressioni.

3.5.1 Operatore di AssegnamentoLoperatore di assegnamento il simbolo uguale (=). Il suo significato e utilizzo allinterno di un programma diverso dal suo consueto utilizzo in matematica. Scrivendo: y = k; NON significa che y uguale a k ma invece assegna il valore di k a y. In unistruzione di assegnamento la parte a destra del segno uguale pu essere una qualsiasi espressione, mentre la parte di sinistra deve essere il nome di una variabile, quindi la sintassi risulta la seguente: variabile = espressione; Quando listruzione viene eseguita prima viene valutata lespressione poi il risultato viene assegnato alla variabile. Quindi per esempio: y = 8 + 9; prima viene calcolata la somma di 8 + 9 poi il risultato viene assegnato alla variabile y. Alla fine dellistruzione avremo che y avr il valore 17. Considerando invece: y = 11; k = y + 7; prima viene assegnato a y il valore 11 poi, nellistruzione successiva, viene calcolato y + 7 e il risultato assegnato a k. Quindi alla fine delle 2 righe di codice sopra riportate avremo che y sar uguale a 11 e k a 18.

3.5.2 Operatori matematiciGli operatori matematici effettuano operazioni aritmetiche e si dividono in due categorie: operatori unari e operatori binari. Gli operatori matematici binari operano su due operandi. Questi operatori che comprendono anche le principali operazioni aritmetiche sono elencati nella tabella sottostante:Operatore Simbolo Azione Esempio

Addizione Sottrazione Moltiplicazione

+ *

Somma i due operandi Sottrae il secondo operando dal primo Moltiplica i due operandi

x+y x-y x*y

Pagina 6 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comDivisione Resto (modulo) / % Divide il primo operando per il secondo Fornisce il resto della divisione del primo operando per il secondo x/y

Corso di Programmazione A.A. 2011-12

Dispensa 3

x%y

Alcuni esempi di utilizzo: /* Primo esempio di utilizzo degli operatori matematici */ #include int main() { int a, b, ris; a = 10; b = 5; ris = a b; printf(risultato di %d-%d=%d\n,a,b,ris); a = 7; b = 3; ris = a * b; printf(risultato di %d*%d=%d\n,a,b,ris); a = 21; b = 7; ris = a / b; printf(risultato di %d/%d=%d\n,a,b,ris); a = 21; b = 10; ris = a / b; printf(risultato di %d/%d=%d\n,a,b,ris); a = 13; b = 5; ris = a % b; printf(risultato di %d %% %d=%d\n,a,b,ris); return 0; } Gli operatori matematici unari hanno questo nome in quanto richiedono un unico operando. Il C dispone di due operatori unari: incremento e decremento e possono essere utilizzati solo con le variabili e mai con le costanti. Il loro scopo quello di aggiungere o sottrarre ununit dalloperando specificato.Operatore Simbolo Azione Esempio

Incrementa Decrementa Ad esempio le istruzioni: ++x; --y; equivalgono a: x = x + 1;

++ --

Incrementa loperando di una unit Decrementa loperando di una unit

y++ y--

++y --y

Pagina 7 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comy = y y;

Corso di Programmazione A.A. 2011-12

Dispensa 3

Gli operatori possono essere postfissi o prefissi. Queste due sintassi non sono equivalenti, ma differiscono per quanto riguarda il momento in cui viene effettuata loperazione: Gli operatori prefissi modificano il proprio operando prima che ne venga utilizzato il valore Gli operatori postfissi modificano il proprio operando dopo avere utilizzato il valore x = 7; y = x++; Dopo lesecuzione di queste due istruzioni x vale 8 e y vale 7. Prima il valore di x stato assegnato a y e solo allora x stato incrementato. Se consideriamo invece le seguenti istruzioni: x = 7; y = ++x; Dopo lesecuzione di queste due istruzioni x vale 8 e y vale 8. Loperatore = loperatore di assegnamento e non un operatore di confronto. Eventuali successive modifiche al valore di x non hanno effetto su y. Consideriamo un esempio: #include int main() { int a, b; a = 7; b = 7; printf(%d printf(%d printf(%d printf(%d printf(%d return 0; } Il risultato del programma: 7 6 5 4 3 6 5 4 3 2 %d\n,a--,--b); %d\n,a--,--b); %d\n,a--,--b); %d\n,a--,--b); %d\n,a--,--b);

Vediamo un esempio:

La precedenza degli operatori segue il seguente ordine: incrementi e decrementi unari moltiplicazioni, divisioni e resti somme e sottrazioni

Se unespressione contiene pi di un operatore con lo stesso valore di precedenza le relative operazioni vengono eseguite da sinistra a destra. E possibile modificare la precedenza attraverso lutilizzo di parentesi tonde. Ad esempio:

Pagina 8 di 9

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comy = 4 + 2 * 3;

Corso di Programmazione A.A. 2011-12

Dispensa 3

Dopo listruzione y vale 10. Prima viene eseguito 2*3 al risultato viene aggiunto 4 e il risultato assegnato a y. Consideriamo: y = 12 % 5 * 2; Loperatore % (modulo) e * (moltiplicazione) hanno la stessa precedenza quindi le istruzioni vengono eseguite da sinistra a destra: prima viene calcolato 12%5 che viene 2 che moltiplicato per 2 fa 4 quindi alla fine a y viene assegnato il valore 4. Se utilizziamo le parentesi: y = 12 % (5 * 2); Prima viene eseguita la sotto espressione individuata dalle parentesi: 5*2 poi il calcolo del modulo. Quindi alla fine dellistruzione a y viene assegnato il valore 2.

Pagina 9 di 9

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 4Laboratorio

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 4

4.2 Input formattato: scanf()La maggior parte dei programmi necessita di dati forniti dallutente, in particolare da tastiera. Il modo pi flessibile per leggere dati numerici attraverso la funzione di libreria scanf(). La funzione scanf() accetta un numero variabile di argomenti, come minimo due. Il primo una stringa di formato che indica come interpretare linput mediante dei caratteri speciali. Il secondo e li altri sono gli indirizzi delle variabili a cui assegnare i dati di input. Ecco un esempio: scanf(%d,&numero); Il primo argomento %d, la stringa di formato. In questo caso %d indica a scanf() di cercare un valore intero con segno. Il secondo argomento utilizza loperatore di indirizzo (&) per indicare a scanf() di assegnare il valore di input alla variabile intera numero. La stringa di formato pu contenere quanto segue: Spazi e tabulazioni che sono ignorati (possono essere utilizzati per migliorare la lettura della stringa di formato) Caratteri (tranne %), che sono messi in corrispondenza con caratteri diversi da spazi dellinput. Una o pi specifiche di conversione, costituite dal carattere % seguito da caratteri speciali. In genere la stringa di formato contiene ununica specifica di conversione per ogni variabile.

Lunica parte obbligatoria della stringa di formato rappresentata dalle specifiche di conversione, che iniziano con % e contengono componenti opzionali e richiesti in un certo ordine. Scanf() applica specifiche in ordine ai campi di input. Un campo di input una sequenza di caratteri diversi da spazi che termina con il successivo spazio bianco o quando lampiezza del campo, se specificata, viene raggiunta. Modificatori di precisione: Tipo Argomento d i int * int *

SignificatoIntero decimale Intero notazione decimale, ottale (inizia con O) o esadecimale (inizia con 0x o 0X) Intero in notazione ottale Intero decimale senza segno Uno o pi caratteri sono letti sequenzialmente nella locazione di memoria indicata dallargomento, senza aggiungere il caarattere di terminazione \0 Una stringa di caratteri diversi da spazi viene letta nella locazione di memoria specificata Un numero in virgola mobile, in notazione decimale o scientifica Una stringa, soltanto I caratteri elencati tra le parentese sono accettati. Linput termina non appena si incontra un carattere non corrispondente, oppure viene raggiunta lampiezza specificata o viene premuto il tasto invio, Per accettare il carattere ] necessario elencarlo per primo: []]. Un terminatore \0 viene aggiunto alla fine della stringa.

o u c

int* unsigned int * char *

s

char *

e,f,g []

float * char *

Pagina 2 di 4

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com[^] char *

Corso di Programmazione A.A. 2011-12

Dispensa 4

Equivale a [] salvo che sono accettati soltanto i caratteri non elencati tra parentesi. Letterale %: legge il carattere %. Non viene effettuato alcun assegnamento.

%

nessuno

Modificatori di precisione: h Quando inserito prima dellindicatore di tipo d,i,o,u,x indica che largomento un puntatore di tipo short invece che un tipo int. Sui PC i due tipi coincidono perci non serve Quando inserito prima dellindicatore di tipo d,i,o,u,x indica che largomento un puntatore di tipo long. Quando inserito prima dellindicatore e,f,g indica che largomento un puntatore di tipo double Quando inserito prima dellindicatore di tipo e, f, g, indica che largomento un puntatore al tipo long double

l

L

Linput di scanf() bufferizzato, perci non vengono ricevuti effettivamente dei caratteri finch lutente non preme INVIO. Lintera riga di caratteri arriva poi a stdin ed elaborata in ordine da scanf(). Il controllo torna da scanf() soltanto quando stato ricevuto input sufficienza per soddisfare le specifiche della stringa di formato. I caratteri in pi se esistono rimangono in stdin e possono causare problemi. Quando viene eseguita una chiamata scanf() e lutente ha inserito una singola riga, si possono avere tre situazioni: per questi esempi si assume che sia eseguita scanf(%d %d, &x, &y); per cui scanf() in attesa di 2 decimali. Ecco le possibilit: La riga inserita dallutente corrisponde alla stringa di formato. Ad esempio si supponga che lutente immetta 12 14 e prema INVIO. In questo caso non ci sono problemi, scanf() soddisfatta e non rimangono caratteri in stdin. La riga inserita dallutente ha troppo pochi elementi per corrispondere alla stringa di formato. As esempio si supponga che lutente immetta 12 e prema INVIO. In questo caso scanf() continua ad attendere linput mancante e quando lo riceve lesecuzione continua senza che rimangano dei caratteri in stdin. La riga inserita dallutente ha pi caratteri di quelli richiesti dalla stringa di formato. Ad esempio si supponga che lutente immetta 12 14 16 e prema INVIO. In questo caso scanf() legge 12 e 14 e restituisce il controllo lasciando gli altri caratteri (1 e 6) in stdin.

Nella terza situazione possono verificarsi dei problemi, poich i caratteri rimangono in attesa fino alla successiva lettura da stdin. Poi i caratteri rimasti sono i primi ad essere letti, davanti anche allinput dellutente effettuato al momento e questo provoca errori. Per evitare questo problema si utilizza la funzione gets() che legge caratteri rimanenti da stdin, fino al termine della riga incluso. Per eliminare qualsiasi carattere indesiderato possibile utilizzare la funzione fflush() passandogli come parametro stdin.

Pagina 3 di 4

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comEsempio utilizzo della funzione scanf(): #include int main() { int i1, i2; long l1; double d1; char buf1[80], buf2[80]; /*uso del modificatore l per interi long e double*/

Corso di Programmazione A.A. 2011-12

Dispensa 4

puts(Inserire un intero e un numero in virgola mobile.); scanf(%ld %lf,&l1, &d1); printf(Hai inserito %ld e %lf.\n, l1, d1); /* La stringa di formato di scanf() ha utilizzato il modificatore l per memorizzare linput di un tipo long e un tipo double */ fflush(stdin); /*Utilizza la dimensione del campo per suddividere linput*/ puts(inserire un numero di 5 cifre (ad esempio 54321)); scanf(%2d%3d, &i1, &i2); /* Si noti che lindicatore dellampiezza di campo nella stringa di formato di scanf() suddivide linput in due valori */ fflush(stdin); puts(inserire il nome e il cognome separati da uno spazio. ); scanf(%[^ ]%s, buf1, buf2); printf(\n il nome : %s\n,buf1); printf(\n il cognome : %s\n,buf2); /* Si noti che [^ ] nella stringa scanf() escludendo il carattere spazio ha causato la suddivisione dellinput */ return 0; } La funzione fflush() viene utilizzata per eliminare qualsiasi carattere indesiderato dal flusso di input. Poich non ci sono indicatori dampiezza lintero a cinque cifre suddiviso in due interi, uno con due caratteri ed uno con tre. Lultimo esempio utilizza il carattere di esclusione. La stringa %[^ ]%s indica a scanf() di prelevare una stringa fermandosi in corrispondenza di uno spazio, in questo modo linput viene suddiviso in maniera efficace.

Pagina 4 di 4

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 5Laboratorio

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 5

5.2 Operatori compattiGli operatori di assegnamento compatti del C forniscono un metodo veloce di combinare operazioni matematiche binarie a operazioni di assegnamento. Ad esempio, si supponga di voler incrementare di 5 il valore di x, o in altre parole voler sommare 5 a x e assegnare il risultato a x. Si pu scrivere: x = x + 5; Utilizzando un operatore di assegnamento compatto, che si pu considerare come un metodo compatto di assegnamento, si scrive: x += 5; In generale gli operatori di assegnamento compatti hanno la sintassi seguente (dove op sta per operatore binario): exp1 op= exp2; che equivale a scrivere: exp1 = exp1 op exp2; Si possono creare degli operatori di assegnamento compatti utilizzando I cinque operatori matematici binari. Alcuni esempi:Scrittura Compatta Scrittura equivalente

X *= Y Y -= Z * 1 A /= B X += Y / 8 Y %= 3

X=X*Y Y=YZ*1 A=A/B X=X+Y/8 Y=Y%3

5.3 Operatore virgolaLa virgola viene utilizzata nel C come semplice carattere di iterputazione che separa le dichiarazioni delle variabili, gli argomenti delle funzioni e cos via. In alcune situazioni per la virgola diventa un vero e proprio operatore: possibile formare unespressione separando due sottoespressioni con una virgola. Il risultato che: entrambe le espressioni vengono valutate, lespressione a sinistra viene valutata per prima lintera espressione assume il valore dellespressione di destra.

Ad esempio, listruzione seguente assegna a x il valore di b, quindi incrementa a e successivamente incrementa b: x = (a++, b++); Dato che loperatore ++ impiegato in modalit postfissa, a x viene assegnato il valore di b prima che questo venga incrementato. Luso delle parentesi necessario dato che loperatore virgola ha una precedenza molto bassa.

Pagina 2 di 5

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 5

5.4 Costanti5.4.1 Direttiva #defineUna costante simbolica una costante rappresentata da un nome o simbolo allinterno del programma. La direttiva #define una direttiva del preprocessore e ha la seguente sintassi: #define NOMECOSTATNE letterale In questo modo si definisce una costante con il nome NOMECOSTANTE il cui valore letterale. Il funzionamento della direttiva #define quello di istruire il compilatore in modo da comportarsi nel modo seguente: nel codice sorgente, sostituisci tutte le occorrenze di NOMECOSTANTE con letterale.

5.4.2 Parola chiave constIl secondo modo di definire costanti simboliche consiste nellutilizzo della parola chiave const. Const un modificatore che pu essere utilizzato in aggiunta a qualsiasi dichiarazione di variabile. Una variabile dichiarata const non pu venire modificata durante lesecuzione dei programmi, ma pu solo essere inizializzata durante la sua dichiarazione, ad esempio: const int conta = 100; const float pi = 3.14159; const long debito = 1200000, float tasso = 0.21; Leffetto di const si propaga su tutte le variabili della riga di dichiarazione. Nellultima riga debito e tasso sono due costanti simboliche. Se il programma cerca di modificare una variabile const, il compilatore genera un messaggio di errore, come nel caso seguente: const int count = 100; count = 200; /*Il programma non viene compilato! E impossibile rassegnare il valore di una costante!*/ Quali sono le differenze pratiche tra le costanti simboliche create con la direttiva #define e quelle create con il modificatore const? Le differenze riguardano luso dei puntatori e lambito delle variabili.

Pagina 3 di 5

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 5

5.5 Esempi utilizzo scanf(), printf()Esempio 1 #include #define SECONDI_PER_MINUTO 60 #define SECONDI_PER_ORA 3600 int secondi, ris_ore, ris_minuti, ris_secondi; main() { /*Richiedere il numero di secondi*/ printf(\n Inserire il numero di secondi); scanf(%d,secondi); ris_ore = seconds / SECONDI_PER_ORA; ris_minuti = (seconds / SECONDI_PER_MINUTO) ris_secondi = seconds % SECONDI_PER_MINUTO; % SECONDI_PER_MINUTO;

printf(%d secondi equivale a:, secondi); printf(%d h, %d m e %d s, ris_ore, ris_minuti, ris_secondi); return 0; } Esempio 2 #include int main() { int numero1, numero2; printf("Inserire 2 numeri separati da uno spazio: "); scanf("%d-%d",&numero1,&numero2); printf("\n numero 1: %d", numero1); printf("\n numero 2: %d", numero2); return 0; } In questo secondo esempio i numeri per essere letti devono essere separati dal carattere -. Esempio 3 #include int main()

Pagina 4 di 5

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com{ int stringa[80]; printf("Inserire del testo e premere invio: "); scanf("%[^abd]",stringa); printf("\n testo inserito: %s", stringa); return 0; }

Corso di Programmazione A.A. 2011-12

Dispensa 5

In questo secondo esempio la funzione scanf() rimane in attesa fino a quando uno dei caratteri inseriti tra le parentesi quadre non viene digitato (seguito ovviamente dal tasto invio) Esempio 4 #include int main() { int stringa[80]; printf("Inserire del testo e premere invio: "); scanf("%[^\n]",stringa); printf("\n testo inserito: %s", stringa); return 0; } In questo secondo esempio la funzione scanf() legge tutti i caratteri, incluso lo spazio, fino alla pressione del tasto invio.

Pagina 5 di 5

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 6Laboratorio

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 6

6.2 Operatori relazionaliGli Gli operatori relazionali del C vengono utilizzati per confrontare espressioni e rispondere a comande come x pi grande di 100 o y pi piccola di x Unespressione contenente un operatore relazionale viene valutata secondo un valore di verit cio veto (valore 1 o false) o falso (valore 0 o false).

Operatore UgualeMaggiore di Minore di Minore o uguale a Diverso

Simbolo Domanda sottointesa == Loperando x uguale alloperando y?> < y X= y X=

6.3 Istruzione ifListruzione if valuta unespressione e dirige conseguentemente il flusso di esecuzione del programma. La sintassi (ridotta) dellistruzione if la seguente: if(espressione) { istruzioni } Se il valore di verit dellespressione vero viene conseguita listruzione presente nel corpo dellistruzione (tra parentesi graffe). In caso contrario il flusso di esecuzione salta allistruzione che segue quella contenuta nellif. Si potrebbe dire che lesecuzione dellistruzione dipende dal risultato dellespressione. #include int x, y; int main() { /*Input dei valori da tastiera*/ printf(\n Inserire un valore per x: ); scanf(%d,&x); printf(\n Inserire un valore per y: ); scanf(%d,&y); /*Confronta i valori e stampa i risultati*/ if (x == y) { printf(x uguale a y); } if (x > y)

Pagina 2 di 2

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com{ printf(x maggiore di y); } if (x < y) { printf(x minore di y); } return 0; } La clausola else Listruzione if supporta la clausola else, che ha la seguente sintassi: if (espressione) { istruzione1; } else { istruzione2; }

Corso di Programmazione A.A. 2011-12

Dispensa 6

Dove la clausole else facoltativa. Lespressione valutata; se vera (se cio espressione ha un valore diverso da zero), eseguita istruzione1. Se falsa (espressione zero) e se c una clausola else, viene invece eseguita istruzione2. Stante la natura facoltativa della clausola else in un costrutto if-else, si crea ambiguit quando un else omesso da una sequenza di if annidiata. Per convenzione, il compilatore abbina else al pi vicino if precedente che ne sia privo. Per esempio: if (n > 0) { if (a > b) { z = a; } else { z = b; } } la clausola else va con listruzione if pi interna, come segnala la rientranza. Se si vuole un risultato diverso, necessario ricorrere alle parentesi graffe per imporre il giusto annidiamento: if (n > 0) { if (a > b) { z = a; } } else { z = b; }

Pagina 3 di 3

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 6

Vediamo alcuni esempi, schematizziamo con le lettere maiuscole A, B, C, D dei blocchi di istruzioni di codice:

Esempio 1:A if (exp) { B } C Se exp restituisce un valore vero (o un numero diverso da zero) la sequenza delle istruzioni A, B, C Se exp restituisce un valore falso (o un numero numero uguale a zero) la sequenza delle istruzioni A, C. Questo perch solo se la condizione vera si accede al corpo dellistruzione if.

Esempio 2:A if (exp) { B } else { C } D Se exp restituisce un valore vero (o un numero diverso da zero) la sequenza delle istruzioni A, B, D. Se exp restituisce un valore falso (o un numero numero uguale a zero) la sequenza delle istruzioni A, C, D.

Esempio 3:A if (exp1) { B if (exp2) { C } else { D } E } else { F if (exp3) { G } H } I

Pagina 4 di 4

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comEXP1 V V V F V F F F EXP2 V V F F F F V V EXP3 V F F F V V F V SEQUENZA ISTRUZIONI A B C E I A B C E I A B D E I A F H I A B D E I A F G H I A F G H I A F G H I

Corso di Programmazione A.A. 2011-12

Dispensa 6

Consideriamo il seguente costrutto: if (espresione) istruzione else if (espresione) istruzione else if (espresione) istruzione else if (espresione) istruzione else istruzione Questa sequenza di istruzioni if il modo pi generale di analizzare un ventaglio di possibilit in C. Le espressioni sono sempre valutate nellordine, se una di esse vera, listruzione con cui associata viene eseguita, e ci conclude lesecuzione dellintero costrutto. Come sempre il codice per ogni istruzione pu essere unistruzione singola o un blocco (pi istruzioni tra graffe). Lultima clausola else si occupa del caso nessuno dei precedenti in cui, non essendo soddisfatta nessuna delle condizioni, occorre procedere dufficio. Pu succedere che nessuna azione esplicita sia prevista per questo caso e allora il passo: else istruzione Pu essere tralasciato, oppure lo si pu riservare alla gestione degli errori, per rilevare una condizione impossibile. Vediamo un esempio: presi in ingresso 3 numeri stamparli in ordine crescente: #include int main() { int num1, num2, num3; int a, b, b; printf(\n Inserire primo valore: ); scanf(%d,&a); printf(\n Inserire secondo valore: ); scanf(%d,&b); printf(\n Inserire terzo valore: ); scanf(%d,&c);

Pagina 5 di 5

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comif (a < b) { if (a < c) { num1 = a; if (c < b) { num2 num3 } else { num2 num3 } } else { num1 = c; num2 = a; num3 = b; } } else { if (b < c) { num1 = b; if (c < a) { num2 num3 } else { num2 num3 } } else { num1 = c; num2 = b; num3 = a; } }

Corso di Programmazione A.A. 2011-12

Dispensa 6

= c; = b;

= b; = c;

= c; = a;

= a; = c;

printf(numeri in ordine crescente: %d, %d, %d,num1,num2,num3); return 0; }

Pagina 6 di 6

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 6

6.4 Operatore condizionaleLoperatore condizionale lunico operatore ternario disponibile in C. Questo significa che lunico a lavorare su tre operandi senapati. La sua sintassi la seguente: exp1 ? exp2 : exp3; Se exp1 vera (cio non nulla), lintera espressione assume il valore di exp2. Se exp1 falsa (ovvero il suo valore zero), lintera espressione assume il valore di exp3. Ad esempio listruzione seguente assegna a x il valore 1 se y vera, mentre se y falsa assegna ad x il valore 100: x = y ? 1 : 100; Analogamente, per assegnare a x il valore pi grande tra quelli contenuti in x e in y: z = (x > y) ? x : y ; Loperatore condizionale funziona in maniera analoga a listruzione if. Listruzione precedente si sarebbe potuta scrivere anche cos: if (x > y) z = x; else z = y; Listruzione condizionale non pu essere utilizzata al posto di qualsiasi istruzione ifelse, ma quando possibile il codice risultante pi conciso. Loperatore condizionale pu essere utilizzato in alcune situazioni in cui listruzione if non utilizzabile, come allinterno di un istruzione printf(): printf(il valore superiore %d: ((x > y) ? x : y));

6.5 Istruzione switchListruzione switch esamina un ventaglio di possibilit. E devia di conseguenza il flusso dellesecuzione. Ogni condizione esaminata esprime la coincidenza del valore di unespressione con una costante intera. switch (espressione) { case espressione-costante: istruzioni; break; case espressione-costante: istruzioni; break; case espressione-costante: istruzioni; break; default: istruzioni } Ogni caso (clausola case) etichettato da una o pi costanti (o espressioni costanti) intere. Se uno di tali casi coincide con il valore dellespressione, lesecuzione prosegue dal caso in questione. Tutte le espressioni delle clausole case devono essere diverse. La clausola default eseguita se nessuna delle altre soddisfatta, ed facoltativa; in sua assenza, se gli altri casi non sono soddisfatti non accade nulla: listruzione switch non ha alcun effetto. I casi e la clausola default possono trovarsi in un qualunque ordine. Listruzione break provoca luscita immediata dal costrutto switch. Poich i casi fungono solo da etichette, quando lesecuzione del codice relativo a un caso finita, essa passa al successivo, a meno che non si decida esplicitamente di fare altrimenti. Questa gestione del flusso detta a cascata. Le istruzioni break e

Pagina 7 di 7

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 6

return sono le pi comuni vie duscita da switch. Un istruzione break impone anche luscita immediata dai cicli while, for e do, come si vedr nel seguito delle lezioni. Lesecuzione a cascata presenta vantaggi e svantaggi. Il lato positivo la possibilit di associare molti casi una singola azione, ma implica anche che ogni caso termini con un break per evirare il passaggio in cascata al successivo: tale meccanismo, infatti, non robusto ed espone il brano switch a una possibile disintegrazione in caso di modifica del programma. Fatto salvo luso di pi etichette in una singola computazione, lesecuzione a cascata va usata con parsimonia e corredata con appositi commenti.

Pagina 8 di 8

CORSO DI and Split Unregistered TECNOLOGIE INFORMATICHE Simpo PDF MergeLAUREA IN SCIENZE EVersion - http://www.simpopdf.com CESENA

CORSO DI

A.A. 2011-12

PROGRAMMAZIONE

Dispensa 7Laboratorio

Dott. Mirko Ravaioli e-mail: [email protected] http://www.programmazione.info

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 7

7.2 Istruzione forLordine di esecuzione delle istruzioni nei programmi in C per default dallalto verso il basso. Lesecuzione comincia con la prima istruzione di main() e va avanti istruzione per istruzione, fino a quando non viene raggiunta la fine di tale funzione. Nei programmi in C reali, raramente questordine viene rispettato. Il linguaggio prevede infatti una gamma di istruzioni di controllo che permettono di gestire il flusso di esecuzione delle istruzioni. Listruzione for un costrutto di programmazione che esegue un blocco di istruzioni per un certo numero di volte. Spesso il costrutto viene detto ciclo perch il flusso di esecuzione ripete le esecuzioni pi di una volta. Un costrutto for ha la struttura seguente: for (inizio; condizione; incremento) { istruzione; }

inizio, condizione, e istruzione sono espressioni del C, mentre istruzione un blocco di istruzioni. Quando durante lesecuzione viene incontrata listruzione for si verifica quanto segue:1. Viene valutata lespressione inizio. Solitamente questa un istruzione di assegnamento che imposta una variabile a un particolare valore. 2. Viene valutata lespressione condizione. Questa solitamente una espressione relazionale. 3. Se la condizione falsa (cio se vale zero) listruzione for si conclude e lesecuzione passa alla prima istruzione dopo il fot 4. Se la condizione vera (cio se vale uno) vengono eseguite le istruzioni del blocco istruzione 5. Viene valutata lespressione incremento e lesecuzione torna al punto 2 Vediamo schematicamente una rappresentazione di unistruzione for: Inizio

Valuta inizio

Valuta incremento

Valuta condizione

VERA

Esegue istruzioni

FALSA

Fine

Pagina 2 di 6

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 7

Proviamo a scrivere un programma che stampi tutti i numeri che vanno da 1 a 10. Potremo scrivere un listato con 10 istruzioni printf() oppure potremo scrivere un codice pi compatto utilizzando un istruzione for: #include int conta; int main() { /*Stampa i numeri da 1 a 20 */ for (conta = 1; conta 122)); if (lettera == ?) { printf(Inserisci la frase nascosta e premere INVIO: ); i = 0; while ((ch =getche()) != 13 && i < LUNGHEZZA_FRASE) fraseUtente[i++] = ch; fraseUtente[i] = '\0'; if (strcmp(strlwr(frase), strlwr(fraseUtente)) == 0) { printf(Hai indovinato!); exit(0); } else printf(Frase non corretta!); } else { /*parte dedicata alla ricerca della lettera*/ .... } La funzione strlwr() consente di trasformare una stringa tutta con caratteri in minuscolo, mentre la funzione strcmp() consente di confrontare due stringhe. Linserimento della frase da parte dellutente viene gestito come allinizio del programma per inserire la frase da indovinare, per gli stessi motivi descritti in precedenza. Volendo limitare il numero di tentativi per indovinare la frase e un numero massimo di lettere da poter inserire dovranno essere utilizzare due contatori rispettivamente per il numero di lettere inserite e il numero di tentativi di indovinare. Tali contatori verranno di volta in volta confrontati con i massimi consentiti (tutta la parte del gioco viene inserita allinterno di un ciclo per ripetere gli inserimenti fino a quando lutente non raggiunge i limiti dei tentativi o indovina la frase o decide di uscire dal gioco): numeroLettere = 0; numeroTentativi = 0; do {

Pagina 11 di 16

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comdo {

Corso di Programmazione A.A. 2011-12

Dispensa 12

printf(Iserire una lettera [- esci; ? indovina]: ); fflush(stdin); lettera = tolower(getche()); if (lettera == -) exit(0); if (lettera != ? && (lettera < 97 || lettera > 122)) printf(Errore di inserimento: carattere non valido\n); } while(lettera != ? && (lettera < 97 || lettera > 122)); if (lettera == ?) { printf(Inserisci la frase nascosta e premere INVIO: ); while ((ch =getche()) != 13 && i < LUNGHEZZA_FRASE) fraseUtente[i++] = ch; fraseUtente[i] = '\0'; numeroTentativi++; if (strcmp(strlwr(frase), strlwr(fraseUtente)) == 0) { printf(Hai indovinato!); exit(0); } else printf(Frase non corretta!); if (numeroTentativi >= MASSIMO_TENTATIVI) { printf(Hai esaurito i tentativi a tua disposizione!); exit(0); } } else { numeroLettere++; trovato = 0; for (i = 0; i < LUNGHEZZA_FRASE && frase[i] != \0; i++) { if (tolower(frase[i]) == lettera) { fraseCrittografata[i] = frase[i]; trovato = 1; } } if (trovato) printf(Lettera trovata!); else printf(La lettera non presente nella frase!); printf(\n%s, fraseCrittografata); if (numeroLettere >= MASSIMO_INSERIMENTI) { printf(Hai raggiunto il numero massimo di inserimenti!); printf(Prova a indovinare la frase nascosta: ); i = 0; while ((ch=getche())!=\n && ch!=\r && i= 97 && lettera = 97 && frase[i] = 97 && lettera 122)) printf("\nErrore di inserimento: carattere non valido\n"); } while(lettera != '?' && (lettera < 97 || lettera > 122)); if (lettera == '?') { printf("\nInserisci la frase nascosta e premere INVIO: "); i = 0; while ((ch =getche()) != 13 && i < LUNGHEZZA_FRASE) fraseUtente[i++] = ch; fraseUtente[i] = '\0'; numeroTentativi++; if (strcmp(strlwr(frase), strlwr(fraseUtente)) == 0) { printf("\nHai indovinato!"); system("pause"); exit(0); } else printf("\nFrase non corretta!"); if (numeroTentativi >= MASSIMO_TENTATIVI) { printf("\nHai esaurito i tentativi a tua disposizione!"); system("pause"); exit(0); } } else { numeroLettere++; trovato = 0; for (i = 0; i < LUNGHEZZA_FRASE && frase[i] != '\0'; i++) { if (tolower(frase[i]) == lettera) { fraseCrittografata[i] = frase[i]; trovato = 1; } } if (trovato) printf("\nLettera trovata!"); else printf("\na lettera non presente nella frase!"); if (numeroLettere >= numeroMassimoInserimentiLettere) { printf("\nHai raggiunto il numero massimo di inserimenti!"); printf("\nProva a indovinare la frase nascosta: "); i = 0; while ((ch=getche())!=13 && i =, 8 || x < 1) printf(Solo I valori compresi tra 1 e 8 sono ammessi!!); else { f = fattoriale(x); printf(%u fattoriale valr %u,x,f); } return 0; } unsigned int fattoriale(unsigned int a) { if (a == 1) return 1; else { a *= fattoriale(a - 1); return a; } }

15.1.5

Ambito delle variabili

Lambito di una variabile si riferisce allestensione entro cui parti differenti di n programma hanno accesso a una determinata variabile; in altre parole, da dove la variabile risulta visibile. Quando si parla di variabili del C, i termini accessibilit e visibilit vengono utilizzati in modo intercambiabile. In riferimento allambito, con il

Pagina 6 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 15

termine variabile si intende qualsiasi tipo di dato previsto dal linguaggio C; variabili scalari, array, strutture, puntatori e cos via, oltre che costanti simboliche definite tramite la parola chiave const. Inoltre, lambito influisce sul tempo di vita di una variabile: quanto tempo la variabile persiste nella memoria, oppure, quando viene allocato o deallocato dello spazio in memoria per la variabile stessa. Esempio di ambito: /*Versione 1 del listato*/ #include intx = 999; void stampa_valore(void); main() { printf(%d\n,x); stampa_valore(); return 0; } void stampa_valore(void) { printf(%d\n,x); }

Ecco loutput del programma: 999 999 /*Versione 2 del listato*/ #include void stampa_valore(void); main() { intx = 999; printf(%d\n,x); stampa_valore(); return 0; } void stampa_valore(void) { printf(%d\n,x); }

Pagina 7 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comSe si prova a compilare il listato 2, viene generato un messaggio di errore del tipo: Error: undefined identifer x.

Corso di Programmazione A.A. 2011-12

Dispensa 15

Lunica differenza tra I due listati consiste nella posizione in cui la variabile x viene definite. Spostando la definizione di x in punti differenti del codice, se ne modifica lambito. Nel listato 1, x rappresenta una variabile esterna e il suo ambito si estende allintero programma. Nel listato 2, x rappresenta una variabile locale e come tale il suo ambito limitato allinterno della funfione main().

15.1.5.1

Variabili esterne

Una variabile esterna definita esternamente da qualsiasi funzione compresa la funzione main(). Le variabili esterne vengono anche definite come variabili globali. Se una variabile esterna no viene inizializzata al momento della definizione, il compilatore le inizializza automaticamente al valore 0. Lambito di una variabile esterna rappresentata dallintero programma. Ci significa che una variabile esterna visibile dalla funzione main() e da qualsiasi altra funzione allinterno del programma.

15.1.5.2

Variabili locali

Una variabile locale una variabile definita allinterno di una funzione. Lambito di una variabile locale risulta limitato alla funzione in cui definita. Le variabili locali non vengono automaticamente inizializzata ad alcun valore. Se al momento della definizione non vengono inizializzate, contengono un valore indefinito.

15.1.5.3

Variabili statiche e variabili automatiche

Le cariabili locali sono di default automatiche. Ci significa che vengono ricreate da zero ogni volta che viene richiamata la funzione in cui sono dichiarate e distrutte ogni volta che lesecuzione del programma abbandona quella funzione. Ai fini pratici, ci significa che una variabile automatica non mantiene il proprio calore nellintervallo di tempo che intercorre tra due chiamate successive alla funzione in cui definita. E possibile fare in modo che una variabile locale mantenga il proprio valore tra ciascuna chiamata alla funzione in cui definita, e per fare ci necessario definirla come statica utilizzando la parola chiave static. Ad esempio: void funzione(int x) { static int a; /*codice della funzione*/ } Esempio tra variabili locali statiche e automatiche: #include void funzione1(void); main() { int conta; for (conta = 0; conta < 10; conta++) { printf(Alla iterazione %d: , conta); funzione1(); } return 0;

Pagina 8 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com} void funzione1() { static int x = 0; int y = 0; printf(x = %d, t = &d\n, x++, y++) ; }

Corso di Programmazione A.A. 2011-12

Dispensa 15

Ecco loutput del programma : Alla iterazione 0: x = 0, y = 0 Alla iterazione 1: x = 1, y = 0 Alla iterazione 2: x = 2, y = 0 Alla iterazione 3: x = 3, y = 0 Alla iterazione 4: x = 4, y = 0 Alla iterazione 5: x = 5, y = 0 Alla iterazione 6: x = 6, y = 0 Alla iterazione 7: x = 7, y = 0 Alla iterazione 8: x = 8, y = 0 Alla iterazione 9: x = 9, y = 0

15.1.5.4

Variabili di registro

La parola chiave register viene utilizzata per chiedere al compilatore di memorizzare una variabile locale automatica in un registro del processore, anzich in memoria. La parola chiave register una richiesta e non un ordine. La parola chiave _register pu essere utilizzata solo con variabile numeriche semplici e non possibile definire un puntatore alle variabili di registro.

15.1.6

Passaggio di variabili a funzioni

Il modo normale di passare un argomento a una funzione detto passaggio per valore. Con ci si intende che la funzione riceve una copia dellargomento.Quando una variabile passata per valore, la funzione pu accedere al valore della variabile, ma non alla variabile vera e propria. Di conseguenza, la funzione non pu modificare il valore della variabile originale. Il passaggio per valore ammesso per i tipi di dati base (char, int, long, float e double) e per le strutture. Esiste tuttavia un secondo modo di passare argomenti a una funzione: passare un puntatore alla variabile argomento, anzich il suo valore. Questo detto passaggio per riferimento. Le modifiche alle variabili passate per riferimento vengono applicate alla variabile di origine. #include void per_valore(int a, int b, int c); void per_riferimento(int *a, int *b, int *c); main()

Pagina 9 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com{ int x = 2, y = 4, z = 6;

Corso di Programmazione A.A. 2011-12

Dispensa 15

printf( \nPrima della chiamata di per_valore(), x= %d, y = %d, z = %d.,x,y,z); per_valore(x,y,z); printf( \nDopo la chiamata di per_valore(), x= %d, y = %d, z = %d.,x,y,z); per_riferimento(&x, &y, &z); printf( \nDopo la chiamata di per_riferimento(), x= %d, y = %d, z = %d.,x,y,z); return 0; } void per_valore(int a, int b, int c) { a = 0; b = 0; c = 0; } void per_riferimento(int *a, int *b, int *c) { *a = 0; *b = 0; *c = 0; }

Pagina 10 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comEsercizio 1. Passaggio per valore/per indirizzo

Corso di Programmazione A.A. 2011-12

Dispensa 15

Scrivere un programma che esegue lo swap di due variabili intere x e y. Prevedere due funzioni di swap, la prima (swap_val) che utilizzi un passaggio per valore e la seconda (swap_rif) che utilizzi, invece, un passaggio per indirizzo. Visualizzare il valore delle variabili x e y in seguito alla chiamata di ciascuna funzione e commentare il risultato

Esercizio 2. Ricerca di un pattern in una stringa Scrivere un programma che cerca le occorrenze di un pattern allinterno di un insieme di stringhe. Il programma prevede che lutente possa inserire pi stringhe; si considera la terminazione di una stringa con landata a capo (si legge cio una linea per volta). Linput termina quando viene inserita una stringa vuota (nessun carattere+invio). Si implementino e utilizzino due funzioni: int getline(char s[], int lim): legge una linea di input nel vettore s, fino a un massimo di lim caratteri, e ritorna la lunghezza della stringa int ricerca_pattern(char s[]) cerca il pattern dentro la stringa s e ritorna -1 se non ha trovato il pattern, un numero >=0 altrimenti. Per ogni input, il programma stampa il numero di occorrenze trovate fino a quel momento e, nel caso in cui sia stato trovato il pattern, anche la stringa.

Pagina 11 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comSoluzione esercizio 1 #include void swap_val(int,int); void swap_rif(int*,int*);

Corso di Programmazione A.A. 2011-12

Dispensa 15

main() { int x,y; printf("Inserisci x e y:\n"); scanf("%d %d",&x,&y); swap_val(x,y); printf("Dopo lo swap con passaggio per valore: x vale %d, y vale %d\n",x,y); swap_rif(&x,&y); printf("Dopo lo swap con passaggio per indirizzo: x vale %d, y vale %d\n",x,y); } void swap_val(int x, int y) // swap con passaggio per valore { int tmp; tmp = x; x = y; y = tmp; } // swap con passaggio per indirizzo void swap_rif(int *px, int *py) { int tmp; tmp = *px; *px = *py; *py = tmp; }

Soluzione esercizio 2 #include #define LIM 100 int getline(char[], int); int ricerca_pattern(char[]); char pattern[] = "ando"; int trovato=0; // inizializzazione ridondante main() { // cerca le occorrenze di un pattern dentro una stringa char line[LIM]; printf("Inserisci il testo in cui ricercare il pattern ); printf(una linea per volta).\nStringa vuota per terminare.\n"); while (getline(line,LIM) > 0)

Pagina 12 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com{ if (ricerca_pattern(line) >= 0) printf("%s\n", line); printf("\n Finora ho trovato); printf(%d occorrenze di %s\n",trovato,pattern); } } int getline(char s[], int lim) { /* legge una linea di input nel vettore s, fino a un massimo di lim caratteri; ritorna la lunghezza della stringa */ int c, i = 0; while(lim > 1 && (c=getchar()) != '\n') { s[i] = c; ++i; --lim; } s[i] = '\0'; return i; } int ricerca_pattern(char s[]) { /* cerca la stringa pattern dentro s */ int i, j, k, ret=-1; for (i = 0; s[i] != '\0'; ++i) { for (j = i, k = 0; pattern[k] != '\0'; ++j, ++k) if (s[j] != pattern[k]) break; if (pattern[k] == '\0') { ++trovato; ret=i; } } return ret; }

Corso di Programmazione A.A. 2011-12

Dispensa 15

ESEMPI DI SCOPE

#include int counter = 0; void f(void); void f2(void); /* variabile globale */

Pagina 13 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comint main() { ++counter; printf("counter is %2d before the call to f\n", counter); f(); printf("counter is %2d after the call to f\n", counter); f2(); return 0; } void f(void) { int counter = 10; } void f2(void) { printf("counter is %2d within f2\n", counter); }

Corso di Programmazione A.A. 2011-12

Dispensa 15

/* variabile locale

*/

printf("counter is %2d within f\n", counter);

Occorre sempre fare attenzione ai nomi e alla visibilit delle variabili: la variabile globale counter, definita allinizio del programma, visibile e modificabile in tutto il programma, eccetto per la funzione f, dove il nome counter usato per identificare una variabile locale. Nota bene: quello visto sopra non un buon esempio di programmazione, in quanto genera confusione per il lettore. #include void f1(int); int f2(void); void f1(int i) { extern int pippo; pippo = pippo + i; } int f2() { static int pluto; // pluto inizializzato solo alla prima chiamata a f2 pluto = pluto + 1; return pluto; } int pippo; int main() { int j; int i = 2; printf("%d\n",pippo); f1(i); printf("%d\n",pippo);

Pagina 14 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comj = f2(); printf("%d\n",j); j = f2(); printf("%d\n",j); return 0; }

Corso di Programmazione A.A. 2011-12

Dispensa 15

Lo scope di una variabile locale (automatica) la funzione dove stata definita. Lo scope di una variabile globale (esterna) va dal punto in cui essa definita al termine del file sorgente in cui si trova. Se necessario riferire una variabile esterna prima che essa sia stata definita, oppure se essa definita in un file sorgente diverso da quello in cui viene utilizzata, allora necessaria una dichiarazione di extern. La dichiarazione static, applicata ad una variabile esterna, ne limita lo scope al file sorgente nel quale essa si trova. La dichiarazione static, applicata ad una variabile non esterna, consente alla variabile di mantenere il proprio valore anche fra due chiamate successive. Le variabili esterne e static vengono inizializzate a zero, mentre le variabili automatiche hanno valori iniziali indefiniti.

Pagina 15 di 15

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com

Corso di Programmazione A.A. 2011-12

Dispensa 15b

ESEMPIO 1Step 1 Ordine #include void stampa(int i); void incrementa(int k); int main() { int numero = 7; stampa(numero); printf(fine stampa); incrementa(numero); printf(%d,numero); return 0; } void stampa(int i) { printf(%d,i); } void incrementa(int k) { int val = 5; val++; k++; } main() variabili globali numero: 7 1 memoria ordine alloc. deal. Allavvio del programma la prima istruzione ad essere eseguita la dichiarazione della variabile numero con assegnamento del valore 7 in memoria viene allocato lo spazio necessario per mantenere la variabile numero (variabile locale della funzione main())

1

Pagina 2 di 52

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comStep 2 Ordine #include void stampa(int i); void incrementa(int k); int main() { int numero = 7; stampa(numero); printf(fine stampa); incrementa(numero); printf(%d,numero); return 0; } void stampa(int i) { printf(%d,i); } void incrementa(int k) { int val = 5; val++; k++; } memoria ordine alloc. deal.

Corso di Programmazione A.A. 2011-12

Dispensa 15b

La seconda istruzione prevede una chiamata ad una funzione stampa() Quando viene chiamata una funzione, lesecuzione del programma si blocca nel punto della chiamata, il controllo viene ceduto alla funzione chiamata In memoria vengono allocate tutte le variabili locali alla funzione incluse quelle indicate nei parametri

1 2

stampa() main() variabili globali

i: 7 numero: 7

2 1

3

3 4

I parametri vengono passati alla funzione copiando, in base alla posizione, il valore nella nuova variabile locale alla funzione chiamata, quindi nel nostro esempio la variabile i (della funzione stampa()) avr una copia del valore della variabile numero (punto 3) Si procede poi con lesecuzione delle varie istruzioni presenti allinterno del corpo della funzione stampa() (punto 4) e quindi con la stampa a video del valore della variabile i, cio del valore 7.

Pagina 3 di 52

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comStep 3 Ordine #include void stampa(int i); void incrementa(int k); int main() { int numero = 7; stampa(numero); printf(fine stampa); incrementa(numero); printf(%d,numero); return 0; } void stampa(int i) { printf(%d,i); } void incrementa(int k) { int val = 5; val++; k++; } memoria ordine alloc. deal.

Corso di Programmazione A.A. 2011-12

Dispensa 15b

Quando una funzione termina tutte le variabili locali vengono rimosse dalla memoria, quindi nella funzione stampa() presa in esame la variabile i viene rimossa dalla memoria. Il controllo viene ceduto al chiamante, quindi alla funzione main() ripartendo dallistruzione immediatamente dopo la chiamata (punto 5)

1 2 5

stampa() main() variabili globali

i: 7 numero: 7

2 1

3

3 4

Pagina 4 di 52

Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.comStep 4 Ordine #include void s