Introduzione al linguaggio C - Dipartimento di Informatica
Transcript
Introduzione al linguaggio C - Dipartimento di Informatica
Università degli Studi di Bari Corso di Laurea in Informatica Corso di Linguaggi di Programmazione Corso C, sedi Brindisi e Corigliano Introduzione al linguaggio C Pasquale Lops Stefano Ferilli Corrado Mencar Obiettivi del corso Fornire le conoscenze di base per la programmazione nel linguaggio C | Confrontare i costrutti del linguaggio C con quelli del linguaggio Pascal | Fornire gli elementi per sviluppare in C mediante l’ambiente di sviluppo DEV-C++ | | Prerequisito: Conoscenza del Pascal 1 Testi consigliati | Linguaggio C (ANSI C) – II ed. z | B.W. Kernighan, D.M. Ritchie (Jackson) C Corso Completo di Programmazione z H.M. Deitel, P.J. Deitel (Apogeo) Caratteristiche fondamentali del C Linguaggio imperativo | Tra basso livello e alto livello | z Costrutti di alto livello tipo Pascal • Cicli, selezioni, funzioni, etc. • Leggibilità e manutenibilità dei programmi z Costrutti di basso livello tipo Assembly • Aritmetica degli indirizzi, enfasi sui puntatori, corrispondenza con le istruzioni macchina • Efficienza dei programmi 2 Caratteristiche fondamentali del C | Tipizzazione debole z Controlli di tipo poco rigorosi z Possibili effetti indesiderati • Utile per la programmazione di basso livello • Scarsa manutenibilità | Portabilità z z | | Assicurata dallo standard ANSI Possibilità di sviluppare programmi non portabili Nutrito insieme di librerie standard Il C è case-sensitive z Parole chiave in minuscolo Struttura di un programma | Pascal Main program | Procedure | z • Procedure • … • Funzioni | | C Funzione main Funzione … Funzione • … z Funzioni • Procedure • … • Funzioni • … 3 Struttura di un programma Pascal program nome-prog dich-tipi dich-variabili dich-procedure-efunzioni begin istruzioni end. C main() { istruzioni } funzione-1 funzione-2 … funzione-n Struttura di un programma | Pascal z Struttura nidificata | C z • Astrazione funzionale z Apposita sezione dichiarativa • Visibilità: l’intera procedura/funzione • Leggibilità, controllo Struttura appiattita • Funzioni paritarie z Dichiarazioni sparse • Visibilità: il blocco in cui sono dichiarate • Efficienza in spazio 4 Il più semplice programma C main () {} abbreviazione per: int main (void) {} | Le funzioni restituiscono per default un intero void | Parola chiave per specificare l’assenza di parametri o di risultato Funzioni Pascal function nome([var] arg: tipo,…, [var] arg: tipo): tipo; dichiarazioni begin … end; | Passaggio parametri z | tipo nome(tipo arg, …, tipo arg) /* dichiarazioni nel corpo */ { … } | riferimento o valore Valore di ritorno z C nome := valore Passaggio parametri z | valore Valore di ritorno z return valore; 5 Tipi semplici Pascal C Integer int Real float, double Boolean -- Char char Modificatori di tipo | Ampiezza char (8 bit) < short (16 bit) < int < long (32 bit) float < double < long double • Possono coincidere con 1, 2 o 3 ampiezze diverse | Segno signed/unsigned • Applicabili a char e int • Estensione del segno 6 Il pre-processore | Direttive #include “nomefile” #include <nomeheader.h> z Inclusione di file esterni • I file di intestazione raccolgono dichiarazioni di costanti e funzioni definite in altri moduli #define NOME espansione z Definizione di costanti simboliche • Prima della compilazione tutte le occorrenze di NOME vengono sostituite da espansione Variabili - Costanti Pascal var id: tipo; | Dichiarazione obbligatoria z z C tipo id [= valore]; | Dichiarazione obbligatoria Globali se dichiarate nel programma principale Solo dichiarazione e non inizializzazione const id = valore; z z Globali se dichiarate fuori dalle funzioni Possibile inizializzazione const tipo id = valore; | | Costanti matematiche: <float.h> Costanti di piattaforma: <limits.h> 7 Costanti enumerative enum nome { ID [= valore], …, ID [= valore] }; | Valori non necessariamente distinti z z | | Valori progressivi dall’ultimo specificato Se non specificato, il primo valore è 0 Nomi diversi in enumerazioni distinte Esempio z enum mesi {GEN=1, FEB, MAR…} Istruzioni | Pascal z z ; separatore Funzioni elementari predefinite • I/O di base • matematiche z (* … *), { … } | C z ; terminatore Nessuna funzione predefinita #include <stdio.h> #include <math.h> z /* … */ z z z 8 Assegnamento Operatori aritmetici C Pascal | := | var := var op espr var := var + 1 var := var - 1 | | | = var = var op espr var op = espr var++ ++var var---var | +, -, * /, div mod | | +, -, * / % Operatori relazionali Operatori logici | Pascal z z z z z z | C = <> <, <=, >, >= z not and or z z z z z == != <, <=, >, >= ! && || 9 Puntatori &variabile z Indirizzo in memoria di variabile • Utilizzabile per il passaggio di parametri per riferimento *puntatore z Valore contenuto all’indirizzo di memoria puntatore • * operatore di “indirezione” tipo *puntatore z *puntatore è di tipo tipo, ossia puntatore è l’indirizzo di un valore di tipo tipo Puntatori - Esempio int x = 1, int *ip; ip = &x; y = *ip; *ip = 0; ip = &z[0] | y = 2, z[10]; /* ip puntatore ad un intero */ /* ip punta ad x */ /* y vale 1 */ /* x vale 0 */ /* ip punta a z[0] */ Esempi di costrutti validi: *ip = *ip + 10; *ip += 1; ++*ip; y = *ip + 1; (*ip)++ 10 Procedura di scambio di valori void swap(int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp; } | Viene chiamata con i riferimenti: swap(&a, &b); I/O base | Pascal z write(…) | C z • writeln(…) z read(…) printf(“…”, …) • printf(“…\n”, …) z scanf(“…”, …) 11 Funzioni di I/O base printf(“formato”, parametro, …, parametro) scanf(“formato”, ¶metro, …, ¶metro) | formato è la stringa da stampare/leggere z z Possibilità di inserire caratteri speciali Segnaposto per i parametri da stampare/leggere • Corrispondenza fra numero e tipo dei segnaposto e sequenza dei parametri z Numero di spaziature ignorato in lettura Caratteri speciali | Sequenze di escape z z z z z z z z \n \t \v \b \” \’ \? \\ a capo tab orizzontale tab verticale cancellazione doppi apici apice singolo punto interrogativo barra rovesciata | Segnaposto parametri z z z z z z z %d decimale %i intero %f virgola mobile %e esponenziale %c carattere %s stringa %% stampa ‘%’ 12 Programma di benvenuto #include <stdio.h> main () { printf(“Salve, mondo\n”); } #include <stdio.h> main () { printf(“Salve, ”); printf(“mondo”); printf(“\n”); } Somma e media di due valori #include <stdio.h> main() { int a,b,s; printf(“Inserisci due numeri interi:\n”); scanf(“%d %d”,&a,&b); s = a + b; printf(“Somma = %d\tMedia = %f\n”,s,s/2.0); } 13 Sequenza Pascal begin … end[;] C { … } | Località delle variabili Selezione binaria | Pascal z if condizione then istruzione/sequenza [else istruzione/sequenza ] z condizione è una espressione booleana | C z | if (condizione) istruzione/sequenza [else istruzione/sequenza ] condizione è un’espressione che restituisce un numero intero z Se il risultato è zero, la condizione è falsa, altrimenti è vera 14 Parità di un intero #include <stdio.h> main() { int n; printf("Inserisci un intero: "); scanf("%d",&n); if (n % 2 == 0) printf("%d e' pari\n",n); else printf("%d e' dispari\n",n); } Selezione multipla Pascal C case espressione of valori: istruzione; … valori: istruzione[; otherwise istruzione] end; switch (espressione) { case costante: istruzione [break;] … case costante: istruzione [break;] default: istruzione } 15 Stampa numeri #include <stdio.h> main() { char n; printf("Inserisci il numero 1 o 2: "); scanf("%d",&n); switch (n) { case 1: printf(“Uno\n"); break; case 2: printf(“Due\n"); break; default: printf(“Numero non riconosciuto\n",n); } } Segno di un intero #include <stdio.h> main() { signed int n; printf("Inserisci un intero: "); scanf("%d",&n); if (n > 0) printf("Positivo\n"); else if (n < 0) printf("Negativo\n"); else printf("Nullo\n"); } 16 Iterazione | Pascal while condizione do istruzione | C while (condizione) istruzione repeat istruzione until condizione-falsa do { istruzione } while condizione-vera Conto alla rovescia #include <stdio.h> main() { int n = 10; while (n != 0) { printf("%d\n",n); n--; } printf(“GO!\n"); } 17 Inserimento di valori negativi #include <stdio.h> main() { signed int n; do { printf("Inserisci un intero negativo: "); scanf("%d",&n); } while (n >= 0); } Iterazione Pascal for ind := inf to sup do istruzione; ≡ ind := inf; while ind <= sup do begin istruzione; ind := ind + 1 end; C for (espr1; espr2; espr3) istruzione ≡ espr1; while espr2 { istruzione; espr3; } 18 Calcolo dei primi n numeri dispari #include <stdio.h> main() { int n; printf(“Quanti numeri devo generare?\n”); scanf(“%d”,&n); for(int i=0; i<n; i++) printf(“%6d.%10d\n”,i+1,2*i+1); } Vettori Pascal var: array[dim] of tipo; | Indici enumerativi z | C tipo var[[dim]] [= {val, …, val}]; | Intervallo a piacere Accesso: variabile[ind] Indici interi z Partono sempre da 0 | In C var ≡ &var[0] | Accesso: variabile[ind] 19 Vettori multidimensionali Pascal var: array[dim,…,dim] of tipo | Accesso: var[ind,…,ind] C tipo var[[dim]]…[[dim]] [= {{val, …, val}, …, {val, …, val}}] | Accesso: var[ind]…[ind] Strutture Pascal variabile: record id: tipo; … id: tipo; end; | Accesso: variabile.id C struct [nome] { tipo id; … tipo id; } [variabile = {val, …, val}]; | Accesso: variabile.id 20 Strutture p z Puntatore a struttura z Contenuto della struttura *p (*p).el z abbreviato in p->el Elemento della struttura Definizione di nuovi tipi typedef tipo Nome; | Semplici sinonimi di tipi esistenti z | Possibilità di dare un nome a tipi complessi Interpretata dal compilatore (a differenza della #define) Parametrizzazione di programmi (portabilità) z Significatività dei nomi (documentabilità) z 21 Forzatura di tipi (tipo) espressione Operatore di “Cast” | Forzatura di un valore ad un tipo | z Il tipo deve essere compatibile col valore Input & Output (I/O) Gestione dell’I/O tramite funzioni delle librerie standard | Input e Output realizzato attraverso flussi | Flusso (stream) = sequenza ordinata di byte z FILE = sorgente o destinazione di un flusso z Un FILE in C può essere: z • Un file del sistema operativo • Una periferica (tastiera, monitor, stampante, etc.) 22 Flussi standard | stdin (standard input) z z | stdout (standard output) z z | Flusso di dati verso lo schermo Scrittura del flusso mediante printf(…) stderr (standard error) z z | Flusso di dati proveniente dalla tastiera Lettura del flusso con la funzione scanf(…) Flusso di dati verso una periferica per la notifica di errori Spesso stdout = stderr Libreria per l’uso dei flussi standard: stdio.h I formati di file | Testuale File definito da linee di caratteri stampabili, separate da ‘newline’ (‘\n’) z Esempi: documenti di testo (txt), codice sorgente z | Binario File definito da qualunque sequenza di byte z Esempi: immagini, file eseguibili, etc. z 23 La gestione dei flussi | Struttura dati FILE Definita nella libreria stdio.h z Contiene le informazioni necessarie all’accesso (lettura e/o scrittura) ad un flusso z Di norma, non si accede direttamente alle informazioni contenute nella struttura, ma essa viene passata come parametro nelle funzioni per l’I/O z Apertura e chiusura di file | | | | Aprire un file = abilitare un flusso di dati Esempio in C: z FILE* fp; z fp = fopen(nomefile, mode); Modalità di apertura (mode) z “r”: lettura da file testuale z “w”: scrittura di nuovo file testuale z “a”: scrittura (append) su file testuale esistente z “r+”: lettura/scrittura su file testuale esistente z “rw”: lettura/scrittura su nuovo file z mode+”b” (es. “wb”): accesso a file binario Chiusura di un file = disabilitare un flusso di dati z fclose(fp); 24 Lettura e scrittura per caratteri | char fgetc(FILE*) z | fputc(char, FILE*) z | Legge un carattere da un flusso Scrive un carattere in un flusso feof(FILE*) Verifica se un flusso è terminato o no z Vale per tutti i tipi di flusso z Lettura e scrittura per linee di testo | char* fgets(char* s, int n, FILE* stream) Legge una linea di testo (cioè fino alla prossima newline) e la memorizza in s. z Il numero massimo di caratteri che possono essere letti è stabilito da n z | fputs(char* s, FILE* stream) z Scrive una linea in un testo 25 Lettura e scrittura formattata | fscanf(FILE* f, char* format, vars) z z | Legge dal file testuale f e valorizza le variabili in vars secondo il formato specificato in format Esempio: fscanf(f,”%d %c”, &v1,&v2) legge da f un decimale (%d) che memorizza in v1 e un carattere (%c) che memorizza in v2 fprintf(FILE* f, char* format, vars) z z Scrive nel file f la stringa specificata nel formato con i valori delle variabili specificate Esempio: fprintf(f,”%d %c”, v1, v2) scrive in f i valori di v1 e v2 separati da uno spazio. Altre modalità di lettura e scrittura | Per blocchi (file testuali) fread / fwrite z Utili per la lettura/scrittura di record z | Accesso diretto z fseek / ftell 26 La libreria standard | assert.h z | Gestione delle asserzioni. Utile per verificare la correttezza semantica dei programmi ctype.h z Gestione dei caratteri • Riconoscimento di categorie di caratteri (p.e. maiuscole, minuscole, cifre, punteggiatura, etc.) • Trasformazioni di caratteri (p.e. minuscolo Æ maiuscolo) La libreria standard | limits.h z | math.h z | Dimensioni dei tipi di dati dipendenti dall’implementazione Funzioni matematiche complesse stdio.h z Funzioni per l’input e l’output 27 La libreria standard | stdlib.h z | string.h z | Funzioni di utilità generale (p.e. generazione di numeri pseudo-casuali, conversione da testo a numeri, etc.) Gestione delle stringhe di testo (copia, concatenazione, confronto, etc.) time.h z Gestione delle informazioni temporali 28