470 likes | 619 Views
Università dell’Insubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in Informatica Anno Accademico 2004/05. Laboratorio di Linguaggi. Marco Tarini. Laboratorio di Linguaggi. docente : Marco Tarini e-mail: tarini@isti.cnr.it
E N D
Università dell’Insubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in Informatica Anno Accademico 2004/05 Laboratorio di Linguaggi Marco Tarini
Laboratorio di Linguaggi • docente: Marco Tarini e-mail: tarini@isti.cnr.it • ricevimento: Martedì 14:30 - 17:30 o anche su appuntamento • libro di testo consigliato: Kelley Al, Pohl Ira: "C Didattica e Programmazione" ("A Book on C") quarta edizione- anche la terza va bene M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Laboratorio di Linguaggi v= argomanto già trattato • link utile: http://vcg.isti.cnr.it/~tarini/linguaggi/ • guida essensiale di alcuni emementi di C M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Linguaggio C: cenni storici • 1972: nasce il C, • by Brian Kernighan & Dennis M.Richie, AT&T Bell Labs • scopo: poter riscrivere in un linguaggio a più alto livello il codice del sistema operativo UNIX • evoluzione del B • Anni 80: si sviluppa il C tradizionale • 1983: comincia la definizione dello standard ANSI C, • (ANSI = American National Standards Institute) • 1990: nascita ufficiale dello "ANSI C" • (o "ANSI ISO/C") M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Caratteristiche del Linguaggio C • Linguaggio imperativo • con numerosi tipi di dato e strutture di controllo • "Medio" livello • cioè più basso di Java! • gestione memoria diretta • gestione files diretta • puntatori… • Focalizzato su efficienza e compattezza di codice • Linguaggio scarno, ma estendibile • esistono molte librerie per operazioni non definite dal linguaggio… • Possibile sviluppare progetti modulari • composti da più files sorgente (source files) compilabili separatamente • molto utile per progetti complessi M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Caratteristiche del Linguaggio C • Il C è un linguaggio tipizzato • cioè: il tipo di ogni espressione è del tutto noto al momento della compilazione x = y + z ; int int int M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Caratteristiche del Linguaggio C viene definita la variabile globale intera "a", (che vale 5) viene definita la procedura "proc" che… …scrive il valore di a viene definita un altra variabile locale intera "a", (che vale 10) viene invocata la procedura "proc" • Il C usa il Binding statico! inta=5; void proc() { printf("%d",a); } void main() { int a=10; proc(); } bindind statico: il programma scrive "5" se bindind fosse dinamico, il programma scriverebbe "10" ! M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
C e Java a confronto... ma i++ è più elegante dell’ l’equivalente i=i+1 • i costrutti sono simili ... if (x<0) x=-x; ... int x=1, i; for (i=1; i<=10; i=i+1) { x = x * i; } int log2=0, x=100; while (x>1) { x = x / 2; log2++; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
C e Java a confronto... • ma scordatevi... • la programmazione ad oggetti (le classi) • in C niente metodi* ! • (* member functions che si applicano all’oggetto che le chiama)! • solo funzioni globali • ...se volete pensatele come metodi statici • macchine astratte (“java runtime environment”) • il C è molto, molto concreto • gestione diretta della macchina • puramente compilato, non compilato-poi-interpretato • gestione delle eccezioni... M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Un programma in C • Un programma è un’insieme di • funzioni, e • variabili. • La funzione • funzione speciale, è l’inizio del programma • deve esistere main M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Le variabili • Dichiarazioni (semplici) opzionalmente, le variabilipossono essere inizializzate qui, il valore iniziale di z è 5 tipo (delle variabili x, y, z, w): int (intero) int x , y , z = 5, w; float ratio, ratio_bis ; tipo (delle variabili ratio e ratio_bis): float (intero) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Le funzioni int potenza (int b, int e) { int res=1 , i; for (i=1; i<=e; i++) { res = res * b; } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Le funzioni lista dei parametri formali, ciascuno preceduto dal tipo (input della funzione) nome (identificatore) della funzione: “potenza” tipo del risultato: intero (output della funzione) variabili locali • qui, due • visibili solo nel corpo della funzione. • dichiarate all’inizio! corpo della funzione “cosa fa” un blocco delimitato da {} comando “return”: restituzione del risultato, e uscita dalla funzione ci deve essere! int potenza (int b, int e) { int res=1 , i; for (i=1; i<=e; i++) { res = res * b; } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Le procedure • Sono funzioni... ...solo, non restituiscono nessun valore tipo del risultato: “void” (nessuno) void saluta_n_volte (int n) { int i; for (i=1; i<=n; i++) { printf("ciao "); } } nota: niete comando “return” nel corpo. (ma si può usare “return”, senza valore, per uscire dalla funzione) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Chiamare le funzioni int potenza (int b, int e) { int res=1 , i; for (i=1; i<=e; i++) { res = res * b; }; return res; } int main(){ int base=10, milione; milione = potenza( base, 6); ... } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Errori comuni di C... • le variabili locali si possono definire solo all’inizio di una funzione! { int x=1; for (int i=1; i<=10; i=i+1) { x = x * i; }; } { int x=2, z, k=5; z = x+k; int h=4, w; w = w+h; } NO { int x=1, i; for (i=1; i<=10; i=i+1) { x = x * i; } } { int x=2, z,w, k=5, h=4; z = x+k; w = w+h; } SI M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Errori comuni di C... funzione annidata (nested function) male, male... (non compilerà) • Vietato annidare funzioni! • le funzioni in C sono tutte allo stesso livello int funzione_uno (int b, int e) { int x, y; int funzione_due( int a) { ... } ... } • (ma, è vero, si può fare ad esempio in Pascal) M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Passaggio di parametri • Sempre per copia • mai per riferimento ! • esempio... void raddoppia (int x) { x = x*2; } int main(){ int incassi = 5; raddoppia( incassi ); ... }; • ...di errore • nota: compila perfettamente! M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Commenti commento stile C++ facile che non vada bene per il vs compilatore C non ANSI !non va bene a me • Usare /* e */ per delimitare i commenti int main(){ /* commento ansi C */ int x=10,y; while (x<6) { ... }; /* commento ansi C lungo due righe */ y = x / 2; // tentativo di commento } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Commento sui Commenti /* funzione potenza: dati due numeri interi B e E restituisce B alla E */ int potenza (int b, int e) { int res=1 , i; for (i=1; i<=e; i++) { res = res * b; }; return res; } int main(){ int base=10, milione; /* modo scemo di calcolare un milione */ milione = potenza( base, 6); /*resto del codice ... */ }; • Usetali ! M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Strumento: Dev-CPP cioè software “libero”, non “gratis” (lo sapevate, vero?) • un Ambiente Integrato di Sviluppo per C (eC++) • Web: http://www.bloodshed.net/dev/devcpp.html, • Free Software (GNU General Public License). • L’installatore è scaricabile da: http://prdownloads.sourceforge.net/dev-cpp/devcpp4990setup.exe M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP • Installare, eseguire • File → New → Project… M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP 1) "Console Application" 2) "C Project" 3) Immette un nome per il progetto 4) ok! • Installare, eseguire • File → New → Project… • Selezionare: M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP per un maggior ordine, meglio creare una directory per il nuovo progetto. NOTA: a ricevimento se avete domande su un progetto potete portarmi una copia della directory creata (per esempio in un floppy) • Immettere il path M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP premere questo piccolo "+" • Abbiamo un nuovo "progetto" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP codice dentro "main.cpp" unico file del progetto (per ora): "main.c" • Abbiamo un nuovo "progetto" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP questa piccola [*] significa che "main.c" non è ancora stato salvato... …salviamolo premendo su questa icona (ci verrà chisto che nome di file usare. Confermare pure il default) • Abbiamo un nuovo "progetto" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP • Abbiamo un nuovo "progetto" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP oppure premere su questa icona …oppure Ctrl-F9 • Abbiamo un nuovo "progetto": compiliamolo • "Execute → Complile" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP nessun "warining"! nessun errore! • Abbiamo un nuovo "progetto": compiliamolo M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP oppure premere su questa icona …oppure Ctrl-F10 • Ora eseguiamo il progetto • "Execute → Run" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP • Ora eseguiamo il progetto • Risultato dell'esecuzione M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Come Usare Dev-CPP • In seguito, per ritornare sullo stesso progetto… • "Execute → Open Project or File…" …e selezionare il file ".dev" col nome corrispondente M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Cosa fa il programma di prova? dichiaria che verranno usate due librerie standard: “standard Input Output” e “Standard Library” “press any key to continue” utile per permettere di visualizzare l’output del programma prima che la finestra si chiuda • non molto… #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { system("PAUSE"); return 0; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Cosa fa il programma di prova? #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { aggiungiamo printf("Ciao Mondo!\n"); system("PAUSE"); return 0; } • ricompliamo & rieseguiamo • abbiamo ottenuto il nostro primo programma “hello world” M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Cosa è successo esattamente quando abbiamo "complilato" il progetto? (quasi) linguaggio macchia in C ancora in C • Solo operazioni sintattiche: • risoluzioni delle “macro” • inclusioni di files di “header” • codici alternativi • per esempio, per le varie piattaforme Source File "main.c" file precomp. object file "main.o" preprocessor compiler • La compilazione vera e propria M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Cosa è successo esattamente quando abbiamo "complilato" il progetto? file precomp. 1 object file "main.o" pre- process. compiler file precomp. 2 object file "pippo.o" pre- process. compiler eseguibile finale "prova.exe" linker file precomp. 3 object file “pluto.o" pre- process. compiler libreria A libreria B Source File 1 "main.c" Source File 2 "pippo.c" Source File 3 “pluto.c" M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore • #= istruzione per il preprocessore: • ≪d'ora in poi, quando scrivo LIMIT, fai finta che abbia scritto 10≫ • Sostituzioni delle macro(costanti simboliche) • puramente sintattiche! #define LIMIT 10 int main() { ... if (x < LIMIT) { ... ... } else { ... ... } ... } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore int main() { ... if (x < 10) { ... ... } else { ... ... } ... } preprocessor • Sostituzioni delle macro(costanti simboliche) • puramente sintattiche! #define LIMIT 10 int main() { ... if (x < LIMIT) { ... ... } else { ... ... } ... } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore • Sostituzioni delle macro(costanti simboliche) • puramente sintattiche! #define LIMIT x int main() { ... if (LIMIT < 10) { ... ... } else { ... ... } ... } int main() { ... if (x < 10) { ... ... } else { ... ... } ... } preprocessor M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore int fattoriale(int a) { int res=1; printf("valore di a:%d \n",a); while (a>1) { res*= (a--); } return res; } preprocessor • Costrutti condizionali • statici, fatti prima del compilatore! #define DEBUG 1 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore int fattoriale(int a) { int res=1; while (a>1) { res*= (a--); } return res; } preprocessor • Costrutti condizionali • statici, fatti prima del compilatore! #define DEBUG 0 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore la guardia viene controllata solo durante la compilazione risultato: programma efficiente! la guardia viene controllata solo durante ogni esecuzione! risultato: programma inefficiente! • Costrutti condizionali statici • perchè é una tale furbata? #define DEBUG 0 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } int DEBUG = 0; int fattoriale(int a) { int res=1; if (DEBUG) { printf("valore di a:%d \n",a); } while (a>1) { res*= (a--); } return res; } VS. M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore • si possono anche usare #ifndef DEBUG #undef DEBUG #if defined (DEBUG) • Costrutti condizionali statici • due forme sintattiche equivalenti #define DEBUG 1 int fattoriale(int a) { int res=1; #if DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } #define DEBUG int fattoriale(int a) { int res=1; #ifdef DEBUG printf("valore di a:%d \n",a); #endif while (a>1) { res*= (a--); } return res; } M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
Preprocessore questo tipo di flags (SUN, HP9000...) sono definite nell’ambiente. Il compilatore lo sa. Non vanno specificate a mano nel codice • Costrutti condizionali statici • altro tipico uso: • specializzazione del codice per architetture specifiche • (remember: niente macchine virtuali in C) ... #if defined (HP9000) || defined(SUN) /* codice funzionante SOLO per le sun o per le HP9000 */ ... #else /* codice buono per le altre architettutre */ ... #endif ... M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
L’ultima fatica del Preprocessore Inclusione file di header file “cambi.h“ const int LIRE_PER_EURO = 1955; file “main.c“ const int LIRE_PER_EURO = 1955; int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } #include "cambi.h" int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } preprocessor M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a
L’ultima fatica del Preprocessore Inclusione file di header file “cambi.h“ const int LIRE_PER_EURO = 1955; pernacchia :P prrrrrr $£!@&& const int LIRE_PER_EURO = 1955; pernacchia :P prrrrrr $£!@&& int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } file “main.c“ #include "cambi.h" int da_euri_a_lire (int euri) { return euri * LIRE_PER_EURO; } preprocessor pura, meccanica, manipolazione sintattica ! M a r c o T a r i n i ‧ L a b o r a t o r i o d i L i n g u a g g i ‧ 2 0 0 4 / 0 5 ‧ U n i v e r s i t à d e l l ’ I n s u b r i a