a = 2
Transcript
a = 2
Fondamenti di Programmazione Variabili e memoria Cos’ è il linguaggio C (1) Sviluppato a partire dal linguaggio B ideato da Thompson Creato all’inizio degli anni ’70 da D. Ritchie ed è diventato uno standard ANSI (American National Standard Institute) nel 1983 (terminato nel 1990) È un linguaggio di programmazione general purpose imperativo a blocchi. È un linguaggio di uso generale ma da sempre legato al sistema operativo UNIX, sul quale è stato sviluppato. Cos’ è il linguaggio C (2) È 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à di dimensioni ridotte, può essere appreso velocemente I principali vantaggi sono efficienza, sinteticità e portabilità Cos’ è il linguaggio C (3) 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 (estensione .h) per l’accesso al sistema operativo (es: leggere e scrivere su file), l’allocazione di memoria, il trattamento delle stringhe. – Le direttive del processore permettono di includere porzioni di codice sorgente esterne ad un dato file Il lessico Alfabeto: utilizzato per scrivere i programmi UNICODE Parole chiave: parole riservate che hanno un significato particolare e non possono essere ridefinite 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 Il lessico Identificatori: nomi usati per indicare variabili, funzioni etc. Separatori: caratteri che permettorno di separare o raggruppare parti di codice: ( ) { } [ ] ; , . Operatori: denotano operazioni Letterali: sequenze di caratteri per rappresentari valori di tipi primitivi : 1234 “questa è una stringa” Il lessico Commenti: devono essere aperti e chiusi attraverso l’uso dei simboli /* e */ oppure se di una sola riga preceduti da // Nomi (o identificatori): − − − − Il C è un linguaggio case sensitive. Ad esempio il carattere “A” è diverso dal carattere “a”, sono due entità diverse e distinte. 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 Note sulla sintassi del linguaggio (1) 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>;} Ogni istruzione per essere valida deve essere terminata da un carattere “ ; ” Norme di buona programmazione scrivere istruzioni chiare, una per riga evidenziare blocchi di istruzioni con le parentesi graffe anche se consistente di un solo comando utilizzare l’indentazione dei diversi blocchi del programma per una più facile lettura del codice stesso. Programmazione Concetti base: − − Dati: − − − Dati (numeri interi o “reali”; caratteri alfanumerici; dati booleani) Istruzioni (operazioni di input/output, artimetiche o logiche,strutture di controllo) Variabili e costanti (variabilità nel tempo) Tipi (elementari o strutturati) classi di memoria (visibilità) Istruzioni: − istruzioni base strutture di controllo − moduli − 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. Istruzioni base Assegnazioni ed espressioni: − comandi per assegnare un valore ad una variabile direttamente o come valutazione di sequenze di operatori e operandi esempio: interest = amount * 0.07; 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 Creare un programma eseguibile Editor − Compilatore − Codice oggetto scritto in linguaggio assembler (nome_file.obj) Linker − Scrittura del programma sorgente (nome_file.c) Collega tra loro i moduli che costituiscono il programma e produce il codice eseguibile (nome_file.exe) Loader (fase di caricamento) L'inizio del programma main (non Main o MAIN) è una funzione speciale che indica l’inizio dell’esecuzione del programma e deve pertanto essere presente in ogni programma. Le parentesi vuote dopo main significano che la funzione non prende nessun parametro in input. Creazione di variabili Tutte le variabili devono essere dichiarate prima di poterle utilizzare Una dichiarazione di variabile associa un nome alle locazioni di memoria ad essa corrispondenti e specifica il tipo di dati che la variabile conterrà: Tipo Variabile_1, Variabile_2, …; Per esempio, per creare tre variabili che memorizzino il numero di cesti, il numero di uova per cesto ed il numero totale di uova: int numberOfBaskets, eggsPerBasket, totalEggs; Tipi fondamentali Rappresentano un singolo valore numerico Tipo Descrizione • • • • char int float double singolo carattere intero virgola mobile a singola precisione virgola mobile a doppia precisione • char<= int <= float <= double Tipo • • • • • char int float double void Bit occupati 8 16 32 64 0 • Intervallo 0 – 255 -32768 – 32767 3.4E-38 – 3.4E+38 1.7E-308 – 1.7E+308 indefinito Esempio: definire una variabile Inizializzazione di una variabile Operatore di assegnamento è: = int total; total=0; Oppure int total=0; il compilatore non segnala errore se si inizializza una variable con un valore fuori range La parola chiave typedef typedef int integer; crea integer sinonimo di int non crea un nuovo tipo! Costanti Una costante è una locazione di memoria di un dato Il valore immagazzinato non può variare durante l’esecuzione di un programma Costanti carattere : ‘A’ Costanti intere : 23 Costanti con virgola (double) :123.456 , 1.23e2, 100. Costanti stringa: “cane” Costanti simboliche Una costante simbolica è una costante che è rappresentata da un nome Una variabile con valore fissato const float PI=3.14159265; #define PI 3.14159265 Variabili e costanti a = 2; b = 3.5; c = 2.; 0xffffa000 0xffffa001 Nota: per brevità 0xffffa002 le variabili intere sono rappresentate 0xffffa003 usando solo 8 bit 0xffffa004 0xffffa005 ???????? ???????? 00000010 ???????? ???????? ???????? Variabili e costanti a = 2; b = 3.5; c = 2.; 0xffffa000 0xffffa001 0xffffa002 00000010 0xffffa003 01000000 0xffffa004 11100000 0xffffa005 00000000 3.5 = (1 + 0.75)*21 NOTA: l’esponente è 0xffffa006 rappresentato in eccesso (cap.1,p.19) 0xffffa007 00000000 a = 2; b = 3.5; c = 2.; 2. = (1 + 0)*21 0xffffa002 0xffffa003 0xffffa004 0xffffa005 0xffffa006 0xffffa007 0xffffa008 0xffffa009 0xffffa00a 00000010 01000000 11100000 00000000 00000000 01000000 10000000 00000000 00000000 a b c d = = = = 2; 3.5; 2.; ‘f’; f ↔ 102 (6616) 0xffffa003 0xffffa004 0xffffa005 0xffffa006 0xffffa007 0xffffa008 0xffffa009 0xffffa00a 0xffffa00b 01000000 11100000 00000000 00000000 01000000 10000000 00000000 00000000 01100110 Modificatori di tipo I tipi di dato primitivi possono essere estesi con l’uso di alcuni modificatori: − − Di dimensione: short, long Di “valutazione”: unsigned Operatori ed Espressioni Espressioni Una espressione è una combinazione valida di costanti, variabili e operatori. Ha un valore numerico e un tipo. • 2+5; /*somma tra costanti*/ • x=a+10; /* assegnazione di una somma tra una costante e una variabile*/ Operatori Un operatore è un simbolo che istruisce C di eseguire una operazione su uno o più operandi. Esistono tre classi di operatori: − − − aritmetici (o matematici) logici e relazionali bit a bit. Operatori aritmetici binari <op1> + <op2> <op1> - <op2> <op1> * <op2> Somma i due operandi Sottrae dal primo il secondo operando Moltiplica gli operandi <op1> / <op2> Divide il primo con il secondo operando <op1> % <op2> Resto della divisione tra il primo e il secondo operando L’operatore % non può essere applicato ai tipi float,double Assegnazione+operatore aritimetico • • • • • <op1> <op1> <op1> <op1> <op1> += -= *= /= %= <op2> <op2> <op2> <op2> <op2> <op1>=<op1>+<op2> <op1>=<op1>-<op2> <op1>=<op1>*<op2> <op1>=<op1>/<op2> <op1>=<op1>%<op2> Ad es. int a=5, b=7; a+=2; b/=3; equivale a: equivale a: a=a+2; (nota: a vale 7) b=b/3; (nota: b vale 2) Operatori matematici int a=2; float b=3.5,c; c = a + b; Nota: nel registro della CPU il numero 2 viene “promosso” a float 0xffffa002 0xffffa003 0xffffa004 0xffffa005 0xffffa006 0xffffa007 0xffffa008 0xffffa009 0xffffa00a 00000010 01000000 11100000 00000000 00000000 01000000 10000000 00000000 00000000 Operatori matematici c = a + b; 0xffffa002 0xffffa003 0xffffa004 0xffffa005 0xffffa006 0xffffa007 0xffffa008 0xffffa009 0xffffa00a 00000010 01000000 11100000 00000000 00000000 ? ? ? ? Operatori matematici c = a + b; 5.5 = (1 + 0.375)*22 0xffffa002 0xffffa003 0xffffa004 0xffffa005 0xffffa006 0xffffa007 0xffffa008 0xffffa009 0xffffa00a 00000010 01000000 11100000 00000000 00000000 01000001 00110000 00000000 00000000 Nota : conversioni int c; int a=2; float b=3.5; c=a+b; c vale 5 Usare le parentesi per rendere chiaro l’ordine di valutazione dell’espressione Non sovraccaricare l’espressione − − Spezzare un espressione complessa in più espressioni Soprattutto se si utilizzano gli operatori (+ +) o (--) Assegnazione: priorità • x=(25-2*(10+(8/2))); • i=j=k=0; = ha priorità più bassa rispetto agli altri operatori ed associa da destra a sinistra Poiché anche l’assegnazione è un operatore si possono scrivere contrazioni: • z=(x=1)+(y=2); Operatori speciali a = 2; b = ++a; 0xffffa002 00000010 0xffffa003 ???????? Operatori speciali a = 2; b = ++a; 0xffffa002 00000011 0xffffa003 00000011 Operatori speciali a = 2; b = ++a; a = 2; b = a++; 0xffffa002 00000011 0xffffa003 00000011 0xffffa002 00000010 0xffffa003 ???????? Operatori speciali a = 2; b = ++a; a = 2; b = a++; 0xffffa002 00000011 0xffffa003 00000011 0xffffa002 00000011 0xffffa003 00000010 Precedenze ++, -- massima *, /, % intermedia +, - minima Espressioni con operatori dello stesso livello sono valutati da sinistra verso destra w*x/y*z; w*x/y+z/y; w*x/++y+z/y; z-(a+b/2)+w*y Problema: conversione di gradi Fahrenheit in Celsius Dobbiamo studiare le diverse temperature rilevate in periodi diversi alcune delle quali sono espresse in Fahrenheit, mentre altre in Celsius. Vorremmo avere tutte le temperature in gradi Celsius. Analisi: Conversione da gradi Fahrenheit a Celsius Dati in ingresso: temperatura in Fahrenheit (tf) Risultato: temperatura in Celsius (tc) Formula: tc=(tf-32)x5/9 Algoritmo (da raffinare): “Acquisisci” i dati Calcola la conversione “Visualizza” il risultato Programmi e variabili main() { float tc, tf = 90., conv; float offset = 32.; conv = 5./9.; tc = (tf – offset) * conv; } ? 90. ? tc tf conv Programmi e variabili main() { float tc, tf = 90., conv; float offset = 32.; conv = 5./9.; tc = (tf – offset) * conv; } ? 90. ? 32. tc tf conv offset Programmi e variabili main() { float tc, tf = 90., conv; float offset = 32.; conv = 5./9.; tc = (tf – offset) * conv; } ? 90. tc tf 0.555 conv 32. offset Programmi e variabili main() { float tc, tf = 90., conv; float offset = 32.; conv = 5./9.; tc = (tf – offset) * conv; } 32.22 tc 90. tf 0.555 conv 32. offset Test Cosa accade se eseguo il programma? Nulla, perché non ci sono istruzioni di output! Input/Output scanf(“%lf”, &tf); Input/Output scanf(“%f”, &tf); 90 Input/Output scanf(“%lf”, &tf); 90 = (1+0.40625)26 010000101011010000000000... (1/4 + 1/8 + 1/32) Input/Output scanf(“%lf”, &tf); 90 = (1+0.40625)26 010000101011010000000000... 90. Input/Output printf(“%f F = %f C\n”, tf, tc); Input/Output printf(“%f F = %f C\n”, tf, tc); Input/Output printf(“%f F = %f C\n”, tf, tc); 90.000000 F = ... Input/Output printf(“%f F = %f C\n”, tf, tc); 90.000000 F = 32.222222 C... Input/Output printf(“%f F = %f C\n”, tf, tc); 90.000000 F = 32.222222 C > Emissione dei dati attraverso printf() Questa funzione permette di formattare l’output int printf(<stringa-formato>[,<espressione>]… ) Emette la stringa indicata nel 1o parametro Se il 1o parametro contiene metavariabili, queste formattano ordinatamente i parametri successivi printf(“Totale fatturato:%d\n” ,12345); Restituisce il numero di caratteri emessi Ancora su printf() La stringa di formato può essere costituita da tre componenti: (obbligatoria) una costante stringa ; (opzionali) metavariabili e sequenze di escape Opzioni di visualizzazione di caratteri 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 Codice di escape \ooo \xhh \\ \0 \a \b \f \n \t Descrizione Notazione ottale* Notazione esadecimale** Singola barra obliqua (\) Il codice NUL Il codice bell (alert) Il codice backspace Il codice formfeed Il codice newline Tabulazione oriz. Tabulazione vert. Acquisizione dei dati attraverso scanf() Questa funzione permette di immettere da tastiera l’input int scanf(<stringa-formato>,&var1,[lista destinazioni]) Copia ordinatamente in memoria i valori digitati da tastiera nelle variabili contenute in lista destinazioni Le variabili nella lista delle destinazioni devono essere precedute da & che ne indica l'indirizzo scanf(“%d%lf”,&count,&average); Restituisce il numero di dati acquisiti scanf() ATTENZIONE: Se si inseriscono spazi o invio nell'immissione di più caratteri (tra un carattere e un altro) è necessario inserire anche questi nella stringa di formato tra i segnaposto %c Importanza della rappresentazione tf =(tc – offset) * 5./ 9.; (tc – offset) * 5./ 9; (tc – offset) * 5 / 9; tf = 5 / 9 * (tc – offset); Imprecisioni numeriche Errore di arrotondamento: 0.1 non ha una rappresentazione finita in binario 0.00011001100110011001100110011001100 11001100110011... Underflow e overflow – Tentativo di rappresentare un numero fuori dal range di valori possibili Errore di cancellazione: – a+b vale a, se a>>b Direttive al preprocessore Preprocessore: programma che “esegue” istruzioni dette direttive di inclusione e definizione #include Consente di includere il contenuto di un altro file #define Definisce un simbolo (Attenzione!!!) #ifdef, #ifndef, #else Compilazione condizionale #include #include <stdio.h> per input/output #include <stdlib.h> allocazione dinamica della memoria, generazione numeri casuali, exit, time #include <math.h> libreria matematica − sin(x), cos(x), sqrt(x), exp(x), pow(x,y), log(x), fabs(x), iabs(x)