Laboratorio di Programmazione Contatti Maddalena Poneti Tel. 055 4237454 [email protected] Ricevimento: su appuntamento Informazioni • Orario di lezione: tutti i mercoledì ore 14.00-17.00. (14:0016:15) • Esame Finale: prova pratica al calcolatore di programmazione in C 3 Testi consigliati • A. Bellini, A. Guidi. Linguaggio C-guida alla programmazione, McGraw-Hill • R. Sedgewitck. Algoritmi C, AddisonWesley • B.W. Kernighan, D.M.Ritchie. Linguaggio C, Jackson • B.W. Kernighan, R.Pike. Programmazione nella pratica, Addison-Wesley 4 Introduzione 5 L’elaboratore elettronico è una macchina costituita da un insieme di dispositivi di diversa natura in grado di elaborare dati in modo automatico, veloce e sicuro. • è una macchina, cioè è un dispositivo privo di intelligenza autonoma • è elettronico, cioè il suo funzionamento si basa su componenti elettroniche • è un elaboratore di dati, cioè, opportunamente “istruito”, è capace di ricevere dati dall’esterno, operare su di essi e fornire i risultati dell’elaborazione 6 Algoritmi e Programmi • Algoritmo (informalmente) – Descrizione di un procedimento o di un metodo per la soluzione di un problema • Rappresentazione di un algoritmo: – Diagramma a blocchi – Pseudocodice • Programma – Espressione di un algoritmo in modo che possa essere eseguito da un calcolatore (linguaggio di programmazione) 7 Se vogliamo che l’elaboratore risolva un problema dobbiamo fornirgli i dati su cui lavorare e una sequenza ordinata di istruzioni (cioè il programma) che elabori i dati ricevuti e fornisca i risultati DATI ELABORATORE RISULTATI PROGRAMMI 8 L’elaboratore elettronico è una macchina programmabile, cioè una macchina che può essere utilizzata per problemi diversi, in grado di interpretare ed eseguire una serie di ordini impartiti dall’esterno. L’elaborazione è affidata non solo ai programmi ma anche ai componenti fisici sistema di elaborazione Con il termine programma intendiamo una successione di istruzioni che, eseguite sequenzialmente, consentono all’elaboratore di svolgere determinati compiti. 9 Strutture di controllo • Le strutture di controllo sono istruzioni speciali che consentono di modificare il normale flusso di istruzioni • Due tipi base di strutture di controllo – selezione • permette di decidere tra due o più diverse alternative di proseguimento – cicli • permettono di ripetere una sequenza di istruzioni 10 Moduli • I programmi sono spesso abbastanza complessi da dover essere scomposti in “pezzi” più maneggevoli • Un modulo consiste di istruzioni per svolgere un certo compito raggruppate insieme in un’unità a cui è dato un nome • il nome può essere usato come sostituto dell’intero insieme di istruzioni • Vantaggi: • risparmio di scrittura, organizzazione, riutilizzo 11 Memoria • Un calcolatore usa RAM per immagazzinare le informazioni (dati) sulle quali opera • La RAM è volatile • La RAM è organizzata sequenzialmente • Ogni byte ha un indirizzo • Un dato deve essere codificato in sequenze di bit per poter essere elaborato • Dati di tipo diverso possono richiedere uno o più byte per la codifica 12 I codici dell’elaboratore Alfabeto: insieme di simboli utilizzati in un linguaggio Alfabeto interno della macchina: due simboli, 0 e 1 Alfabeto esterno dell’utente: 26 lettere maiuscole 26 lettere minuscole 10 cifre decimali caratteri vari (segni di punteggiatura, simboli matematici …) 13 … continua Affinchè ci possa essere una “conversazione” con l’elaboratore: ogni simbolo dell’alfabeto esterno CODICE uno e uno solo di quello interno 14 … continua I simboli dell’alfabeto esterno, prima di poter essere memorizzati, devono essere tradotti nei corrispondenti simboli dell’alfabeto interno. I risultati dell’elaborazione dovranno essere tradotti in caratteri dell’alfabeto esterno, prima che l’elaboratore possa comunicarli codifica decodifica All’interno dell’elaboratore tutte le informazioni sono rappresentate in codice 15 … continua Per rappresentare un valore numerico viene utilizzato il sistema di numerazione binario. In tutti gli altri casi ogni simbolo è codificato separatamente. I codici più noti sono: EBCDIC (Extended Binary Coded Decimal Interchange Code) 8 bit ASCII (American Standard Code for Information Interchange) UNICODE 16 bit (216 = 65.536 caratteri) 16 Codifica binaria • Alfabeto binario: due stati • Quanti oggetti posso codificare con k bit? – 1 bit ->2 stati (0,1) -> 2 oggetti – 2 bit ->4 stati (00,01,10,11) -> 4 oggetti –… – k bit ->2k stati -> 2k oggetti 17 Esempio A 01000001 4 00110100 B 01000010 5 00110101 C 01000011 6 00110110 7 00110111 ……. 0 00110000 8 00111000 1 00110001 9 00111001 2 00110010 3 00110011 18 Tipologie di Software • Software di base: Sistema Operativo – Programma supervisore • DOS, Windows, MacOS, UNIX, Linux • Software Applicativo – word-processor/editor – web browser – compilatori o assembler • Applicazioni create dall’utente 19 Linguaggi di programmazione Istruzioni primitive che il calcolatore è in grado di eseguire direttamente e regole per combinare tra di loro le istruzioni primitive • Sintassi: forma in cui l’istruzione primitiva è espressa • Semantica: significato dell’istruzione stessa 20 ...continua • Linguaggio macchina: – sequenze di 0 ed 1 – rigoroso – essenziale • Linguaggio assembler: – simbolico – semplice traduzione aggiuntiva • Linguaggio di programmazione ad alto livello – Indipendente dal processore utilizzato 21 …continua Efficienza del programma Programmazione a basso livello Programmazione ad alto livello Facilità e velocità di programmazione 22 Tipi di linguaggio di programmazione • I linguaggi possono essere suddivisi sulla base del modello astratto di programmazione: Linguaggi di programmazione Imperativi Procedurali Ad Oggetti Paralleli (C,Pascal, (C++, Java) (Occam) Fortran) Dichiarativi Funzionali Logici Relazionali (Lisp) (Prolog) (SQL) 23 …continua • Linguaggi imperativi: (iterazione) – Il modello computazionale è basato sui cambiamenti di stato della memoria della macchina: effettivo cambiamento dei valori dei dati – È centrale il concetto di assegnamento di un valore ad una locazione di memoria – Il compito del programmatore è costruire una sequenza di assegnamento che produca lo stato finale (in modo tale che questo rappresenti la soluzione del problema) • Linguaggi dichiarativi: (ricorsione) – Il modello computazionale è basato sui concetti di funzione e relazione: come evolvono i dati – Il programmatore non ragiona in termini di assegnazioni di valori, ma di relazioni fra entità e di valori di funzione 24 …continua Scelta del linguaggio di programmazione sulla base dell’ambito del problema da risolvere: • • • • • Calcolo Scientifico: Fortran, C Intelligenza Artificiale: Prolog, Lisp Sistemi device driven: Assembler, C Applicazioni gestionali: SQL, C Applicazioni client visuali: C++, Java, Visual Basic • Applicazioni Web: Perl, ASP, Java • Applicazioni distribuite: Java, C, C++ 25 La storia del C • C – Sviluppato da Ritchie da due precedenti linguaggi di programmazione, BCPL e B – Usato come linguaggio di sviluppo del sistema operativo UNIX – Attualmente la maggior parte dei sistemi operativi sono scritti in C o C++ – Indipendente dall’hardware (portabile) • Standard – Esistevano più versioni di C incompatibili fra loro – Nel 1983 si creò un comitato per fornire una definizione del linguaggio “non ambigua e indipendente dalle macchine” – Lo standard fu approvato nel 1989, aggiornato nel 1999 26 Cos’ è il linguaggio C • È considerato un linguaggio di alto livello ma non troppo, nel senso che fornisce un insieme ristretto di costrutti di controllo e di parole chiave, ma un insieme ricco di operatori e strutture dati avanzate • Offre al programmatore potenza e flessibilità • Può essere descritto in uno spazio limitato e appreso velocemente • I principali vantaggi sono efficienza, sinteticità e portabilità 27 …continua • l’assenza di alcune funzionalità di alto livello consente di mantenere il linguaggio di dimensioni ridotte • Il linguaggio non prevede funzionalità esplicite di I/O, non esistono funzioni READ e WRITE (devono essere incluse tramite specifiche chiamate a funzioni di libreria) • Lo standard ANSI ha definito una libreria standard associata al C la quale specifica le funzioni per l’accesso al sistema operativo (es: leggere e scrivere su file), l’allocazione di memoria, il trattamento delle stringhe. 28 Il ciclo di sviluppo del programma Uso Uso di di un un editor editor Codice sorgente Compilazione Compilazione del del file file sorgente sorgente Codice oggetto File di libreria Linking Linking file file oggetto oggetto Programma eseguibile 29 …continua Edit Preprocess Compilazione Link Disk Program is created in the editor and stored on disk. Preprocessor Disk Preprocessor program processes the code. Compile Disk Linker Disk Editor Loader Compiler creates object code and stores it on disk. Linker links the object code with the libraries, creates a.out and stores it on disk Primary Memory Load Loader puts program in memory. Disk .. .. .. Primary Memory CPU Esecuzione .. .. .. CPU takes each instruction and executes it, possibly storing new data values as the program executes. 30 Note sulla sintassi del linguaggio • I commenti devono essere aperti e chiusi attraverso l’uso dei simboli /* e */ • Ogni istruzione per essere valida deve essere terminata da un carattere “ ; ” • Il C è un linguaggio strutturato e la caratteristica che più contraddistingue un linguaggio di questo tipo è rappresentato dai blocchi di codice. Un blocco è un insieme di istruzioni logicamente collegate delimitato da parentesi graffe { } <istruzione>; {<istruzione>; <istruzione>;} 31 …continua • Nomi (o identificatori): – Il C è un linguaggio case sensitive. Ad esempio il carattere “A” è diverso dal carattere “a”, sono due entità diverse e distinte. – Per scrivere un codice portabile evitare di sfruttare caratteristiche speciali del proprio ambiente – Un nome può iniziare con una lettera alfabetica e continuare con lettere, cifre numeriche, simbolo di sottolineatura – NON inziare un nome con il simbolo di sottolineatura (nomi di sistema) – La lunghezza può essere un elemento critico; generalmente la dimensione max è di 32 caratteri • Le direttive del processore permettono di includere porzioni di codice sorgente esterne ad un dato file – Tipicamente si includono librerie i cui nomi terminano con l’estensione .h 32 Norme di una buona programmazione • scrivere istruzioni chiare, una per riga • evidenziare blocchi di istruzioni con le parentesi graffe anche se il blocco consiste di nu solo comando • utilizzare l’indentazione dei diversi blocchi del programma per una più facile lettura del codice stesso. 33 Parole chiave definite dallo standard ANSI • • • • • • • • auto break case char const continue default do • • • • • • • • double else enum extern float for goto if • • • • • • • • int long register return short signed sizeof static • • • • • • • • struct switch typedef union unsigned void volatile while 34 La libreria standard del C • I programmi scritti in C consistono di ”pezzi” o moduli chiamati funzioni – Un programmatore può creare le proprie funzioni • Vantaggio: il programmatore ne conosce a fondo il funzionamento • Svantaggio: dispendio di tempo – I programmatori usano spesso le funzioni della libreria C • Usarle per l’approccio di costruzione a blocchi – Evitare di inventare di nuovo la ruota • Se esiste una funzione già fatta, generalmente è preferibile usare questa piuttosto che scriverne una nuova • Le funzioni di libreria sono scritte con molta cura, sono efficienti e 35 portabili Fondamenti Principali Un programma C è costituito da funzioni e da variabili: • funzioni: contengono le istruzioni che specificano le operazioni che il programma deve effettuare; • variabili: memorizzano i valori usati durante l’esecuzione del programma 36 Esempio: visualizzazione di una linea di testo /* A first program in C */ #include <stdio.h> main() { printf( "Welcome to C!\n" ); return 0; } Esecuzione Esecuzione Questo programma stampa a video la stringa seguita dall’avanzamento del cursore all’inizio della riga successiva. Welcome Welcome to to C! C! 37 Note sulla sintassi del linguaggio • Commenti – Il testo compreso tra /* e */ è ignorato dal compilatore – Sono utili per documentare il programma • #include <stdio.h> – Direttiva per il preprocessore - indica al compilatore di caricare il contenuto di un file – <stdio.h> consente di eseguire le operazioni di input/output standard 38 …continua • main() • (non Main o MAIN) è una funzione speciale che indica l’inizio dell’esecuzione del programma e deve pertanto essere presente in ogni programma. • I programmi C contengono una o più funzioni, una soltanto deve essere main Le parentesi vuote dopo main significano che la funzione non prende nessun parametro in input 39 …continua • Le parentesi graffe racchiudono un blocco. Il corpo di tutte le funzioni deve essere racchiuso fra parentesi graffe • La funzione printf della libreria standard, stampa a video la stringa di caratteri fornita come parametro. All’interno di questa la sequenza di escape \n specifica il carettere speciale di “avanzamento all’inizio della linea successiva”. 40 (Compilazione di programmi C) • I programmi C si memorizzano in file con estensione .c oppure .ccp • Supponendo di avere salvato il programma precedente in un file di nome salve_mondo.c per compilarlo si utilizza il comando gcc nel seguente modo: > gcc (–ansiansi-pendanticpendantic-errors) errors) welcome.c Il risultato del comando precedente è un file binario eseguibile welcome che contiente il codice eseguibile dalla CPU da caricare in memoria in fase di esecuzione. Per eseguire il programma basta invocare il file risultato dalla compilazione: >welcome Welcome to C! 41 Variante dell’ esempio #include <stdio.h> /* main() viene eseguita automaticamente all’avvio */ main() { printf(“Welcome”); printf(“ to C!\n”); return 0; } 42 Notare…. • return 0; – Un modo per uscire da una funzione – return 0, in questo caso, indica che il programma è terminato normalmente 43 Introduzione al linguaggio C Variabili e tipi Programmazione • Concetti base: – dati – istruzioni • Dati: – variabili – tipi – classi di memoria • Istruzioni: – istruzioni base – strutture di controllo – moduli 45 Variabili e tipi • Variabile: – locazione di memoria a cui è dato un nome con cui chiamarla ed utilizzarla (contenitore di dati) • programmatore usa il nome senza necessariamente sapere che esso faccia riferimento ad una locazione di memoria • Tipo: – ogni variabile ha un tipo che indica che genere di dati la variabile può contenere • una variabile può contenere dati di tipo intero (ad es., 15 o 2038), oppure dati di tipo carattere (ad es., ‘a’ o ‘£’) – Le dimensioni delle variabili numeriche dipendono dall’architettura dell’elaboratore sottostante • Classe di memoria: – determina la durata di vita della variabile. 46 Variabili – I nomi di variabili corrispondono alle locazioni di memoria – Ogni variabile ha un nome, un tipo, una dimensione e un valore – Ogni qualvolta un nuovo valore è posto in una variabile (per es. con \scanf), esso sostituisce (e distrugge) il valore precedente – Una operazione di lettura di una variabile dalla memoria non ne modifica il valore integer1 45 47 …continua • Il campo di azione di una variable in C è determinato dalla posizione in cui viene dichiarata e dall’uso di particolari qualificatori • Quanto dichiarato all’interno di una funzione o di un blocco ha valore locale alla funzione o al blocco stesso • Quanto dichiarato all’esterno di una funzione ha valore globale per tutto il file 48 Nomi di variabili • I nomi possono contenere lettere, numeri e il trattino di sottolineatura ( _ ) • Il primo carattere deve essere una lettera • Le lettere maiuscole e minuscole sono trattate come entità diverse Pippo ≠ pippo ≠ PIPPO • Le parole chiave (keywords) non possono essere utilizzate come nomi di variabili 49 Nomi di variabili: esempi Percento y2x5_fg7h profitto_annuale _2000_tasse risparmio#conto double 99summer ok ???? No!! 50 Tipi di variabili Tipo Parola chiave Dimensione (byte) Carattere Intero Intero corto Intero lungo char Intero senza segno Intero corto senza segno Intero lungo senza segno unsigned int unsigned short unsigned long 2 2 4 Virgola mobile float 4 double 8 int short long 1 2 2 4 a precisione singola Virgola mobile a precisione doppia 51 Regole ANSI per la dimensione delle variabili • La dimensione di un char • La dimensione di uno è sempre 1 byte short è minore o uguale a quella di un int • La dimensione di un int è minore o uguale a quella di un long • La dimensione di un unsigned è uguale a quella di un int • La dimensione di un double float è minore o uguale a quella di un 52 Dichiarazione delle variabili • La dichiarazione indica al compilatore il nome e il tipo di una variabile • Non è possibile usare una variabile che non sia stata dichiarata nometipo nomevariabile; 53 …continua •Si possono dichiarare più variabili dello stesso tipo su una stessa riga, separando i nomi con virgole int conta,numero,inizio; /* 3 variabili intere */ float percento,totale; /* 2 variabili a virgola mobile */ •E’ possibile inizializzare una variabile al momento della dichiarazione int conta = 0,numero = 2,inizio = 1; float percento = 0.01; 54 Somma di due numeri interi 1 /* 2 3 Addition program */ #include <stdio.h> 4 5 main() 6 { 7 int integer1, integer2, sum; /* declaration */ printf( "Enter first integer\n" ); /* prompt */ 10 scanf( "%d", &integer1 ); /* read an integer */ 11 printf( "Enter second integer\n" ); /* prompt */ 12 scanf( "%d", &integer2 ); /* read an integer */ 13 sum = integer1 + integer2; /* assignment of sum */ 14 printf( "Sum is %d\n", sum ); /* print sum */ Esecuzione Esecuzione 8 9 Enter Enter first first integer integer 45 45 Enter Enter second second integer integer 72 72 Sum Sum is is 117 117 15 16 return 0; /* indicate that program ended successfully */ 17 } 55 Nota Commenti, #include <stdio.h> e main • int integer1, integer2, sum; – Dichiarazione di variabili • Variabili: locazioni di memoria dove memorizzare un valore – int significa che le variabili possono contenere valori interi (per es. -1, 3, 0, 47) – integer1, integer2, sum - nomi di variabili (identificatori) – Le dichiarazioni devono essere poste prima delle frasi eseguibili 56 …continua • scanf( "%d", &integer1 ); – Ottiene valori dall’utente • scanf usa lo standard input (di solito, la tastiera) – Questa scanf ha due argomenti • %d - indica che il dato deve essere un decimale intero • &integer1 - locazione in memoria dove memorizzare il dato – L’utente risponde a scanf digitando un numero, e premendo successivamente il tasto enter (return) 57 …continua . • = operatore di assegnamento – Assegna un valore ad una variabile – La variabile che riceve il valore si trova a sinistra dell’operatore • printf( "Sum is %d\n", sum ); – Simile a scanf - %d significa che sarà visualizzato un intero decimale • sum indica quale intero sarà visualizzato – All’interno dell’istruzione printf possono essere eseguiti dei calcoli printf( "Sum is %d\n", integer1 + integer2 ); 58 Costanti • Letterali • Simboliche 59 Costanti letterali • Valore digitato direttamente all’interno del codice int conta = 20; /* il numero 20 è una costante letterale */ • Una costante che inizia per una cifra diversa da zero viene trattata come un numero in base 10 • Una costante che inizia per zero viene considerata come un numero ottale (in base 8) • Una costante che inizia con 0x oppure 0X viene considerata come un numero esadecimale (in 60 base 16) Costanti simboliche • Costante rappresentata da un nome (o simbolo) all’interno del programma 1) #define NOMECOSTANTE valore #define PI 3.14159 sostituisce tutte le occorrenze di PI (tranne nei commenti, all’interno di virgolette o se compare come sottostringa) con il valore 3.14159 2) Const: una variabile dichiarata const non può essere modificata const int conta = 100, float tasso = 0.21 61 Le differenze fra #define e const saranno analizzate in seguito Istruzioni • Istruzione: comando completo che indica al computer di eseguire un particolare compito • terminano con punto e virgola (tranne le direttive) • possono occupare più righe • Istruzione nulla: un solo punto e virgola sulla riga • Istruzione composta o blocco: due o più istruzioni racchiuse fra parentesi graffe { area= PI*raggio*raggio; printf(“\n area= %d”,area); } 62 Aritmetica • Operatori aritmetici operazione C operatore aritmetico Espressione Algebrica espressione C Addizione + f+7 f + 7 Sottrazione - p–c p - c Moltiplicazione * bm b * m Divisione / x/y x / y Modulo % r mod s r%s • Regole di precedenza degli operatori Operatore/i () *, /, o % +o- Operazione/i Parentesi Ordine di valutazione (precedenza) 1 moltiplicazione, divisione, modulo 2 addizione, sottrazione 3 63 Gerarchia di promozione per i tipi long double di dato double float unsigned long int long int unsigned int Se due operandi non sono dello stesso tipo, quello “inferiore” viene convertito al tipo “superiore” prima di eseguire l’operazione int short char 64 Modificatori di tipo • I tipi di dato primitivi possono essere estesi con l’uso di alcuni modificatori: – Di dimensione: short, long – Di “valutazione”: unsigned 65 Tipo Abbreviazione Descrizione char Tipo char usato numericamente unsigned char Intero più breve short int short unsigned short int unsigned short Tipo short senza segno Intero normale int unsigned int unsigned Intero senza segno long int long Intero più lungo unsigned long int unsigned long Tipo long senza segno float double long double 66 Double più lungo Esercizio • Programma per calcolare nella propria piattaforma la dimensione dei tipi primitivi • Determinare la dimensione dei vari tipi con modificatori • char <= short <= int <= long <= float <= double <= long double 67 Emissione dei dati attraverso printf() • Questa funzione permette di formattare l’output printf( printf(“Stringa di testo(, %d \n)” (,espressione (valore))); (valore))); Emette la stringa indicata nel 1o parametro Se il 1o parametro contiene metavariabili, queste formattano ordinatamente i parametri successivi 68 Principali caratteri di conversione %c Singolo carattere %d Intero decimale con segno %f Decimale in virgola mobile %e Notazione scientifica %s Costante stringa %u Decimale intero senza segno %o Ottale %e Esadecimale %% Segno di percento 69 Codice di escape Descrizione \ooo Notazione ottale* \xhh Notazione esadecimale** \\ Singola barra obliqua (\) \’ Un apice destro \” Un apice doppio \0 Il codice NUL \a Il codice bell (alert) \b Il codice backspace \f Il codice formfeed \n Il codice newline \r Il codice carriage return \t Tabulazione oriz. \v Tabulazione vert. 70 • (*)\ooo dove ooo è una sequenza di cifre ottale #define VTAB ‘\013’ 013’ /* tab vert. vert. ASCII*/ • (**)\ (**)\xhh dove hh è una sequenza di cifre esadecimali #define VTAB ‘\xb’ xb’ /* tab vert. vert. ASCII*/ 71 Esempio /* stampa la dimensione dei tipi primitivi*/ #include <stdio.h <stdio.h> stdio.h> main() main() { printf( printf(“Il tipo char occupa %d byte \n”, (int) int)sizeof( sizeof(char)); char)); printf( %d\ printf(“int %d\n”, (int (int) int)sizeof( sizeof(int)); int)); printf( %d\ printf(“float %d\n”, (int (int) int)sizeof( sizeof(float)); float)); printf( printf(“double %d\ %d\n”, (int (int) int)sizeof( sizeof(double)); double)); } 72 Opzioni di visualizzazione di caratteri 73 Esempio #include <stdio.h <stdio.h> stdio.h> const int a=2; float h=h=-0.1; main() main() { printf( printf(“\n Visualizza un valore decimale,%d, e un valore float,%f float,%f” ,%f”,a,h); } 74 Esercizio • Scrivere un programma che usa printf() printf() per visualizzare valori numerici: – Definire tre variabili intere a=2,b=10,c=50 e tre variabili in virgola mobile (precisione singola) f=1.05, g=25.5,h=-0.1 – Visualizzare tre variabili sulla stessa linea, senza tabs, con tabs, su tre linee diverse 75 #include <stdio.h <stdio.h> stdio.h> int a=2, b=10, c=50; float f=1.05, g=25.5, h=h=-0.1; main() main() { printf( printf(“\n valori decimali senza tabs:%d tabs:%d %d \ %d” %d”,a,b,c); printf( printf(“\n valori floats con \ tabs: tabs:\t%f\ t%f\t%f\ t%f\t%f” t%f”,f,g,h); printf( printf(“\n valori floats con \ tabs: tabs:\n\t%f\ t%f\n\t%f\ t%f\n\t%f” t%f”,f,g,h); } 76