Le funzioni di input/output - Università degli Studi di Parma
Transcript
Le funzioni di input/output - Università degli Studi di Parma
Dipartimento di Ingegneria dell’Informazione Università degli Studi di Parma Le funzioni di input/output Fondamenti di Informatica Laurea in Ingegneria Civile e Ingegneria per l’ambiente e il territorio <stdio.h> Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini Input / Output n n Input / Output Il linguaggio C consente di definire funzioni aggiuntive raggruppabili eventualmente in librerie . Esiste in particolare una libreria standard s( tandard library) di funzioni ; per rendere disponibili tali funzioni , occorre inserire nelle dichiarazioni globali del programma, la direttiva di precompilazione: #include <stdio.h > n La libreria standard comprende, tra le altre, le seguenti funzioni di input/output Il linguaggio C printf (<stringa di formato > [,<lista di espressioni> ]) n n n per visualizzare dati sullo standard output <lista di espressioni > ::= <espressione> {, <espressione>} q sono espressioni il cui valore deve essere visualizzato <stringa di formato >: contiene caratteri da visualizzare ed i simboli di formato per i valori delle espressioni da visualizzare : q %d per la visualizzazione di un numero intero q %f per la visualizzazione di un numero reale q %c per la visualizzazione di un carattere q %s per la visualizzazione di una stringa 3 Esempi Il linguaggio C Input / Output printf (“Questa è una frase di prova \n”); scanf (< stringa variabili> ) printf ( “La somma di %d e %d risulta: %d\n”, m, n, m+n); printf (“Il codice ASCII visualizzato come %c \n”,61,61) 5 > ,< lista indirizzi n Esempio Ma Il linguaggio C formato n %d\nviene Il codice ASCII 61viene visualizzato come A di consente la lettura di dati dallo standard input <lista di indirizzi di variabili> ::= <indirizzo> {,<indirizzo>} <indirizzo> : : = &<variabile> <stringa di formato> n n q 4 scanf (“%d %f %c ”, &n, &x, &c); scanf (“%s”, nomestringa); Il linguaggio C 6 1 Esempio n Esempio Programma che legge due numeri e ne visualizza la somma n #include <stdio.h> int main(){ int m, n; printf (“Inserire primo numero:”); scanf (“%d”, &m); printf (“Inserire secondo numero:”); scanf (“%d”, &n); printf (“La somma di %d e %d risulta %d\n”, m, n, m+n); return 0; Legge un codice ASCII e ne visualizza il carattere #include <stdio.h> int main(){ char c; printf (“Inserire il codice ASCII:”); scanf (“%d”, &c); printf (“Il carattere corr. è %c\n”, c); return 0; } } Il linguaggio C 7 Il linguaggio C 8 Strutture di controllo Strutture di controllo n Selezione if if (< condizione> ) < istruzioni> [else < istruzioni> ] < istruzioni > ::= <istruzione> | ‘{‘ < istruzione> {< istruzione> } ’}’ A esempio if (x > 0) If, while, for, ... falso ↔ 0 vero ↔ non 0 operatori di confronto maggiore > maggiore o uguale >= minore < operatori logici minore o uguale <= not! uguale == and&& diverso != or| | y = x; else y = -x; printf(“dato %d\n”, y); Il linguaggio C Esempio 10 Strutture di controllo n /* Dati due numeri in ingresso , individua il maggiore* / #include <stdio.h> #include <conio.h> int main(){ int num1,num2; Ciclo for for(< istr .iniziale> ;< condizione> ;< istr . ciclica> )< istr .> A esempio: calcolo della somma dei primi 100 numeri naturali #include <stdio.h> int main(){ int i, somma = 0; clrscr() printf("Immetti i due numeri:"); scanf("%d%d",&num1,&num2); if (num1==num2) printf("I due numeri sono uguali"); else if(num1>num2)printf("Il primo è maggiore”); else printf("Il secondo è maggiore"); return 0 ; for ( i=1; i<=100; i=i+1) somma = somma+i; printf (“La somma vale: %d \n”, somma); return 0; } } Il linguaggio C 11 Il linguaggio C 12 2 Strutture di controllo Operatori di incremento e decremento Ciclo while n while (< condizione> ) n < istruzioni> A esempio: calcolo radice quadrata intera ( cioè la parte intera) di un numero intero n #include <stdio.h> int main(){ int n, radice = 1; radice=radice−1 printf (“Inserire il numero:”); può essere scritto scanf (“%d” , &n); radice− − while (radice*radice <= n) oppure − −radice radice++; radice−−; printf (“La radice vale %d\ n”, radice); n ++ e -Esempi q y=x++ il contenuto della variabile x viene inizialmente usata per l’assegnazione y, e solo dopo incrementata q y=--x il contenuto della variabile x viene inizialmente incrementato di uno e solo dopo viene effettuata l’assegnazione di x a y return 0;} Il linguaggio C 13 Strutture di controllo n Il linguaggio C Strutture di controllo n Ciclo do do < istruzioni> while (< condizione> ) Esempio trovare un programma che legge e addiziona dei numeri , terminaquando la somma supera il valore 1000 #include < stdio.h> int main(){ int i, somma = 0, cont = 0; do{ printf ( “Inserire nuovo numero :” ); scanf (“ %d ”, &i); somma = somma + i; cont++; }while (somma < = 1000); printf ( “I numeri letti sono % d\ n” ,cont); return 0; } Il linguaggio C Selezione switch < istr. switch>::=switch(<espr.> )‘{‘<istr. case> |< istr. default> ’}’ < istr.case >::=case< valore intero> :{case < valore intero> :} < istr.> [break] < istr. default>::= default < istr.> 2 A L egg e due numeri ed un simbolo di operazione (+,−,∗ ,/); visualizza il risultato dell’operazione richiesta #include < stdio.h> int main(){ int m,n; char operazione,invio; printf (“ Inserire i due numeri: ”) ; scanf ( “%d%d” , &m,&n); printf ( “Inserire l’ operazione :” ); scanf ( “%c%c” , &invio , &operazione) ; 15 Strutture di controllo switch ( operazione ) { case ‘+ ’: printf(“ Risultato %d \n ”, break; case ‘− ’: printf(“ Risultato %d \n ”, break; case ‘∗ ’: printf(“ Risultato %d \n ”, break; case ‘/ ’: printf(“ Risultato %d \n ”, break; default: printf(“ operazione 14 Il linguaggio C 16 Esempio /* Legge la data d i nascita di una persona nel formato giorno/mese/anno e la data attuale nello stesso formato; calcola poi l'et à della persona in anni */ #include < stdio.h> int main(){ int g_att,m_att,a_att,g_nas,m_nas,a_nas; m+ n); m− n); printf("immetti la data di nascità : "); scanf("%d%d%d",&g_nas,&m_nas,&a_nas) ; printf("immetti la data attuale: "); scanf("%d%d%d",&g_att,&m_att,&a_att) ; if ( m_att> m_nas || m_att= =m_nas && g_att> =g_nas ) printf("l'et à (in anni ) è : %d",a_att- a_nas) ; else printf("l'et à (in anni ) è : %d",a_att- a_nas- 1); return 0; m∗ n); m/ n); non consentita\ n” ); } } return 0;} Il linguaggio C 17 Il linguaggio C 18 3 Strutture di dati Una struttura di dati ha le seguenti propriet à: n è un insieme di dati Strutture dati q n Es. una struttura contenente il totale delle vendite un’azienda in ognuno dei dodici mesi di un anno effettuate da ogni dato dell’insieme può essere singolarmente identificato rispetto agli altri q Es. si deve poter conoscere il totalevenduto in un certo mese n la modalità d i identificazione dei singoli dati, consente che una stessa istruzione, eseguita in momenti diversi, possa operare su diversi dati della struttura n possono esistere operazioni che agiscono a livello dell’ intera struttura Vettori e matrici q Es. deve essere possibile leggere, con un ciclo, tutte le fatture (emesse da un’ azienda, contenute in un archivio) Il linguaggio C Vettori Vettori n n n n 20 un vettore (array unidimensionale ) è un insieme di elementi dello stesso tipo ha un nome che lo identifica gli elementi del vettore vengono identificati , oltre che con il nome del vettore di appartenenza, con il valore di un indice numerico giorni_mese 1 31 28 2 31 0 indice n nome vettore per identificare un elemento si utilizza il nome del vettore seguito dal valore dell’indice racchiuso tra parentesi. es. giorni_mese [3] il valore dell’indice può essere una qualsiasi espressione; ad esempio es. giorni_mese [n+3] n occorre dichiarare il tipo degli elementi e la dimensione del vettore (in C i vettori hanno dimensione prefissata) <tipo> <nome > ‘[‘ <dimensione> ‘]’ n il valore dell’indice parte da zero un vettore occupa locazioni contigue di memoria n n il C non effettua alcun controllo (n é in fase di compilazione, né in fase di esecuzione) sul superamento dei limiti di un vettore contenuto Il linguaggio C 21 Vettori Il linguaggio C 22 Array Multidimensionale /* Programma che legge n numeri in un vettore e li visualizza in ordine inverso */ #include < stdio.h> #define MAX 100 int main (){ int n, i, numeri[MAX ] ; /* Lettura dimensione vettore */ printf ( “Inserire il numero di elementi: ”) ; scanf (“ %d ”, &n); if (n> MAX) printf ( “Valore troppo elevato \n ”) ; else{ /* lettura dei numeri */ for (i= 0; i< n; i++){ printf ( “Inserire un numero: ”) ; scanf (“ %d ”, & numeri[i ]); } /* visualizzazione dei numeri in ordine inverso */ for(i= n− 1; i> = 0; i− − ) printf (“ %d \n ”, numeri[i]); } return 0;} Il linguaggio C n hanno due o più indici (o dimensioni) n in C, occorre dichiarare la dimensione di ogni indice <tipo> <nome> ‘[‘<dimensione>‘]’ { ‘[‘<dimensione>‘]’ } n 23 i vettori bidimensionali sono denominati matrici Il linguaggio C 24 4 Esempio /*legge, per righe, gli elementi di una matrice 2× 3 e stampa la somma d i ogni riga*/ #include < stdio.h> #define N_RIGHE 2 #define N_COLONNE 3 int main(){ int i, j, somma , numeri[N_RIGHE][N_COLONNE] ; for (i= 0; i< N_RIGHE; i+ + ) { printf (“ Inserisci riga n.%d\ n” , i+ 1); for (j= 0; j< N_COLONNE; j+ + ) { printf (“ Inserisci elemento n.%d: ”, j+ 1); scanf (“ %d ”, & numeri[i][j]); } } for (i= 0; i< N_RIGHE; i+ + ) { somma= 0; for (j= 0; j< N_COLONNE; j+ + ) somma+ = numeri[i][j ]; printf (“ La somma della riga n.%d vale %d \n ”, i+ 1, somma ); } Caratteri e stringhe <string.h> return 0;} Il linguaggio C 25 Caratteri e Stringhe Caratteri e stringhe Lettura di un carattere da tastiera (dispositivo standard di input): getchar() n accetta caratteri fino alla pressione del tasto invio; solo allora restituisce il primo carattere inserito; gli altri restano in memoria. n Esempi char c; c=getchar(); putchar(c) Scrittura di un carattere sullo schermo (dispositivo standard di output) n putchar (<espressione carattere>) Il linguaggio C 27 Stringa Il linguaggio C 28 Lettura di una stringa da tastiera n È una sequenza di caratteri n In C non esiste il dato di tipo stringa; una stringa viene memorizzata in un array di caratteri gets (<array>) char nome[30] n Il C usa la tecnica di contrassegnare la fine effettiva di una stringa con il carattere avente codice 0 ( ‘\0’) n Inizializzazione di una stringa: char nome[30]=”Luca ” (inserisce automaticamente il carattere ‘\0’) Il linguaggio C 29 //termina l ’immissione con il tasto “invio” scanf (“%s”, <array>) //termina l ’immissione con il tasto “invio ” (il codice del tasto invio non viene letto) n in entrambi i casi, l’inserimento di un numero di caratteri maggiore della lunghezza dell’array, ha effetti imprevedibili Il linguaggio C 30 5 Esempio Scrittura di una stringa su schermo //legge una stringa e conta le eventuali cifre presenti al suo interno #include < stdio.h> #define MAX_CAR 128 int main() { int i, n_cifre= 0; char stringa [MAX_CAR]; puts (“Inserire una stringa: ”); gets (stringa); for (i= 0; i< MAX_CAR; i+ + ) { if (stringa[i]= = ’\0’) break; if (stringa[i]> = ’0’ && stringa[i]< = ’9’) n_cifre+ + ; } printf (“Il numero di cifre è %d\n”, n_cifre); return 0; } puts (<espressione stringa>) //aggiunge ‘\n’ printf (“%s ”, <espressione stringa>) Es. put s (stringa ); printf (“%s %s\n”, stri1, stri2); Il linguaggio C 31 n Per il loro utilizzo occorre includere il file string.h strcpy (s1, s2) copia la stringa s2 in s1 strcat (s1, s2) concatena s2 alla fine di s1 strlen (s) restituisce la lunghezza della stringa s strcmp (s1, s2) 32 Funzioni di manipolazione delle stringhe Funzioni di manipolazione delle stringhe n Il linguaggio C Copia due nomi in due stringhe , ne fa la comparazione , stampa a video la più grande (in ordine alfabetico) e unisce i due nomi in una terza stringa e restituisce il numero di caratteri del primo e del seconod numero inserito. confronta s1 con s2 Il linguaggio C 33 #include <stdio.h> #include <string.h> #define MAX_CAR 128 #define MAX_NOME 10 int main() { int l; char nome1[MAX_NOME], nome2[MAX_NOME2], mixed [MAX_CAR]; char titolo[30]; strcpy(nome1, “Topolino” ); strcpy(nome2, “Pluto”); strcpy (titolo, “Questo e’ il titolo. ”); printf (“%s \n\n”, titolo); printf(“Il primo nome e’ %s \n”, nome1); printf (“Il secondo nome e’ %s \n”, nome2); if (strcmp(nome1, nome2) >0) /*comparazione alfabetica, la piu’ grande e’ pluto* / strcpy(mixed, nome1); else Il linguaggio C 34 strcpy(mixed, nome2); printf (“Il piu’ grande nome in ordine alfabetico e’ %s \n”, mixed); /*utilizzo funzione strcat*/ strcpy ( mixed, nome1); strcat(mixed, “ “); strcat(mixed, nome2); printf (“Entrambi i nom i sono %s \n”, mixed); /*utilizzo funzione strlen* / l=strlen(nome1); printf (“Il primo nome e’ composto da %d caratteri\n”, l); l=strlen(nome2); printf (“Il secondo nome e’ composto da %d caratteri\n”, l); return 0; } 6 n n n n n n n Questo e’ il titolo Topolino Pluto Pluto (primo nome in ordine alfabetico) Entrambi i nomi sono Topolino Pluto Il primo nome e’ composto da 8 caratteri Il secondo nome e’ composto da 5 caratteri Le funzioni Funzioni Funzioni n Con il termine funzione si intende, in generale, un operatore che, applicato a certi operandi, consente di calcolare un risultato n Il linguaggio C consente la definizione di funzioni n Occorre dichiarare il cosiddetto prototipo della funzione nella sezione delle dichiarazioni globali: Esempi: n int somma (int m, int n); int somma (int, int); int fun (void); Occorre definire la funzione <tipo risultato> <nome funzione> ([<elenco par. >]){ <corpo della funzione> } <tipo risultato > <nome funzione > (<elenco parametri >); n All’interno del corpo della funzione, si utilizza un’apposita istruzione per uscire dalla funzione e restituirne il risultato: return <espressione risultato> dove: <elenco parametri> ::= < tipo parametro> [<nome parametro> ] {,< tipo parametro> [<nome parametro >]} Il linguaggio C 39 Esempio Il linguaggio C 40 Funzioni con parametri #include <stdio.h> int leggi_numero (void); int max ( int m, i n t n); int main () { int a, b,massimo; a = leggi_numero(); b = leggi_numero(); massimo = max(a,b); printf (“ Il massimo è %d\ n”,massimo); return 0; } int leggi_numero(void) { int n; printf (“ Inserire un numero:”); scanf (“% d”, &n); return n; } int max (i n t m, int n) { if (m>n) return m; else return n; } Il linguaggio C n n n 41 Possono operare su dati diversi per ogni funzione il programma che chiama la funzione deve dichiarare nella chiamata i dati su cui operare Si dice che I parametri vengono passati per valore Il linguaggio C 42 7 Passaggio parametri per valore (by value) n n ã o Esempio Parametri formali utilizzati nella funzione chiamata Parametri effettivi passati per valore dalla funzione chiamante I valori dei dati effettivi sono copiati nei parametri formali utilizzati dalla funzione chiamata Nessun effetto provocato da modifiche nel parametro formale all’interno della funzione si ripercuote sul parametro reale del programma chiamante Il linguaggio C n n Si realizzi un programma che legga da tastiera il costo di listino di un prodotto e la percentuale di sconto e visualizzi il prezzo da pagare si può realizzare una funzione che riceva come parametri i due valori e calcoli il prezzo finale 43 Esempio Il linguaggio C 44 Esempio /*Funzione con parametri*/ #include<stdio.h > /*Definizioni generali - variabili globali*/ long int costo; int percentuale; long int prezzo_scont(long int valore, int percent) {/*Definizioni interne alla funzione*/ long int val_scont; /*Corpo della funzione*/ val_scont=valore-(valore*percent/100); return (val_scont )} void main() {printf(“Introduci costo e percentuale (interi): \n”); scanf(“%ld%d”,&costo,&percentuale); printf(“Prezzo di listino: %ld, sconto: %d%%”, costo, percentuale); printf(“prezzo finale: %dld\n”, prezzo_scont(costo, percentuale));} Il linguaggio C n n 45 Funzioni : il passaggio di array n Gli array non sono passati per valore n Gli array vengono passati per indirizzo (in realtà si tratta ugualmente di un passaggio per valore, in quanto in C il nome di un array è l’indirizzo del primo elemento) n Se la funzione modifica il contenuto dell ’array, tale modifica si riflette sull ’array originario n Non occorre specificare la dimensione dell ’array nell ’elenco dei parametri formali Il linguaggio C Parametri formali: valore e percent Parametri effettivi: costo e percentuale Il linguaggio C 46 Esempio /* Restituisce il valore del minimo di un vettore di interi. vet: vettore di cui si cerca il minimo dim: numero di elementi del vettore */ #include <stdio.h > int min_ele (int vet[], int dim ); int main(){ int i,numeri[10]; for (i= 0; i< 10; i++){ printf (“Inserire un numero:” ); scanf (“%d”, &numeri[i]); } printf(“Il minore e’ : %d”,min_ele(numeri,i ); return 0;} int min_ele (int vet[], int dim ) { int i, min; min= vet[0]; for (i= 1;i< dim;i+ + ) if (vet[i]< min) min= vet[i]; return min; } 47 8 Passaggio dei parametri by reference Funzioni: passaggio per riferimento n n Cosa succede se la funzione deve restituire più di un dato alla funzione chiamante? Si passa l’indirizzo della cella di memoria in cui è contenuto il risultato La funzione swap e il passaggio di array Il linguaggio C Esempio di puntatore Esempio di funzione che deve ritornare più valori #include<stdio.h> int main(){ int dato; /* definizione di intero */ int *indirizzo_dato; /* definizione di puntatore ad un intero */ indirizzo_dato=&dato;/* assegna l’indir. di dato al puntatore */ dato=5; /* assegna un valore intero */ printf(“Il dato vale %d \n ”,dato); /*stampera’ il numero 5 */ *ind_dato=3; /* ora il dato vale 3 */ printf(“Il dato vale %d \n ”,dato); /*stampera’ il numero 3 */ return 0; } Il linguaggio C #include <stdio.h> void calcola (float valore, float *quad_val, float *cub_val) { *quad_val =valore * valore; *cub_val=*quad_val * valore; return; } int main() { float un_dato, quadrato, cubo; printf(“Introduci una dato”); scanf(“%f”, &un_dato); calcola (un_dato, &quadrato, &cubo); printf(“Il quadrato di %f e\’ : %f \n”,un_dato, quadrato); printf(“Il cubo di %f e\’ : %f \n”,un_dato, cubo); return 0; } 50 n Calcolare il quadrato e il cubo di un dato in una sola funzione 51 Il linguaggio C 52 Osservazione n n Importante la sintassi, si rischia di effettuare errori che il compilatore non trova Attenzione agli effetti collaterali: occorre valutare che le variazioni introdotte nelle procedure non abbiano ripercussioni indesiderate in altre parti del programma Il linguaggio C 54 9 #include <stdio.h> void scambia(int *x, int *y) { int z; z = *x; *x = *y; *y = z; return;} void swap (int x, int y){ int z; z=a; a=b; b=z; } int main() { int a=3, int b=5; Esempio: provare la funzione swap (funzione che commuta il valore fra a e b) void swap (int a, int b) //a e b passatiper valore {int t; t=a; a=b; b=t; } NON SI HA ALCUN EFFETTO printf ("Prima dello scambio swap: a=%d, b=%d. \n", a, b); /*a=3 e b=5*/ scambia(&a, &b); printf ("Dopo lo scambio: a=%d, b=%d. \n", a, b); /*a=3 e b=5*/ void swap (int *a, int *b)//a e b ora sono dei puntatori { in t; t=*a; *a=*b; *b=t; } chiamando swap(&x,&y) si OTTIENE lo scambio desiderato Il linguaggio C printf("Prima dello scambio scambia: a=%d, b=%d. \n", a, b); /*a=3 e b=5*/ scambia(&a, &b); printf ("Dopo lo scambio: a=%d, b=%d. \n", a, b); /*a=5 e b=3*/ return 0; } 55 #include<stdio.h > void prova(int a[], int b, int n) void prova1(int a, int *b); int main() { int c[3], d; c[0]=100; c[1]=15;c[2]=20; d=0; printf(“Prima : %d,%d,%d,%d\n”, c[0], c[1], c[2], d); prova(c,d,3); printf(“Dopo prova : %d,%d,%d,%d\n”, c[0], c[1], c[2], d); prova1(c[0], &d); printf(“Dopo prova1 : %d,%d,%d,%d \n”, c[0], c[1], c[2], d); return 0;} void prova(int a[], int b, int n) //a per riferimento b n per valore {int i; for (i=1; i<n; i++) { a[i]=b; } b =a[0]; return;} void prova1(int a, int *b){ *b=a; return;} Prima: 100, 15,20, 0 Dopo prova : 100, 0,0,0 Dopo prova1: 100, 0,0,100 Esempio di - passaggio per valore -passaggio per reference -passaggio di un array -passaggio di una casella di array Il linguaggio C 57 Strutture Le strutture n Una struttura è un raggruppamento di variabili sotto un unico nome; le singole variabili si chiamano membri della struttura: * ESEMPIO persona: cognome nome indirizzo data_nascita n indirizzo : via località provincia CAP data_nascita: giorno mese anno Una struttura può contenere al suo interno ulteriori sottostrutture Il linguaggio C 60 10 Strutture Strutture La definizione di una struttura in C avviene nel modo seguente: n n struct < nome struttura> ‘{‘ <dichiarazione di variabile> { < dichiarazione di variabile> } ‘}’; struct < nome struttura> < nome variabile> {,< nome variabile> }; * ESEMPIO * ESEMPIO struct data_nascita{ int giorno; int mese; int anno; }; equivalentemente: struct data_nascita { int giorno, mese, anno; }; Il linguaggio C equivalentemente: struct data_generica { int giorno; int mese; int anno; }data_fattura, data_bolla; struct data_generica data_fattura, data_bolla; Il linguaggio C 62 Esempio Per fare riferimento ai membri di una struttura , se ne qualifica il nome facendolo precedere dal nome della variabile di struttura di appartenenza, inserendo un punto di separazione n scanf(“%d%d%d”,&data_bolla.giorno, &data_bolla.mese, &data_bolla.anno); n struct data_generica{ int giorno; int mese; int anno; }; 61 Strutture n La definizione di una struttura non definisce alcuna variabile, ma solo un tipo di dato; per dichiarare variabili di tipo struttura: Scrivere un programma che memorizzi una agenda telefonica (massimo 10 componenti), utilizzando una struttura persona. È consentito ’l assegnamento diretto tra due variabili di struttura dello stesso tipo; ad esempio: data_fattura=data_bolla; Il linguaggio C #include <stdio.h> #include <string.h> #define MAXNOMI 10 #define MAXLUNG 20 struct persona{ char cognome[MAXLUNG]; char nome[MAXLUNG]; char telefono[MAXLUNG]; }; int main(){ struct persona agenda[MAXNOMI]; int n_tot_persone=i=0; printf(“Introdurre il numero totale delle persone da introdurre (<=10)\n”); scanf(“%d”,& n_tot_persone); if (n_tot_persone>10 || n_tot_persone<1) printf (“Si deve introdurre un numero compreso fra 1 e 10\n”); 63 Il linguaggio C 64 else { while(i< n_tot_persone) { printf (“Introdurre il cognome della persona n. %d”, i); scanf(“%s”, agenda[i].cognome); printf(“Introdurre il nome della persona n. %d”, i); scanf(“%s”, agenda[i].nome); printf(“Introdurre il telefono della persona n. %d”, i); scanf (“%s”, agenda[i].telefono); i=i+1; } /*ciclo per la visualiz. dell’agenda*/ for(i=0; i<n_tot_persone,i++) printf (“%s %s %s ”, agenda[i].cognome, agenda[i].nome, agenda[i].telefono); return 0; } } 11 I File I File n n normalmente con la parola file (o archivio) si intende un insieme di informazioni, memorizzate su disco magnetico le operazioni tipiche che si possono eseguire su di un file sono: q lettura di dati in memoria q scrittura (aggiornamento o aggiunta) di dati dalla memoria file memoria lettura scrittura Il linguaggio C I File n n n I File un file è una struttura dinamica, in quanto è possibile aggiungere dei nuovi dati al suo interno, incrementando cos ì la sua dimensione per il C, un file non è altro che una sequenza di byte esistono due tipi di file in C q q Es. tastiera, monitor, stampante , file su disco, porta seriale … q esistono in particolare tre file standard utilizzabili direttamente da parte di un qualunque programma C: n sono strutturati in linee di testo (tipicamente in codice ASCII ) stdin (standard input): è il dispositivo standard di input dei dati, normalmente rappresentato dal terminale; viene usato dalle funzioni scanf(), getchar (), gets(), … stdout (standard output): è il dispositivo standard di output dei dati, normalmente rappresentato dal monitor del terminale; viene usato dalle funzioni printf(), putchar (), puts(), … stderr (standard error ): è il dispositivo standard di visualizzazione dei messaggi di errore, normalmente rappresentato dal monitor del terminale q n il C identifica la fine di una linea, con il carattere ‘\n’ n l’effettivo contenuto del file su disco, dipende dal modo in cui il sistema operativo consente di realizzare i file di testo q file binari n i byte che vengono letti e scritti, corrispondono all’effettivo contenuto del file: non viene effettuata alcuna conversione n anche un file di testo p u ò essere elaborato come file binario: in tal caso si opera sull’effettivo contenuto in byte del file Il linguaggio C q 69 I File n più in generale, il C considera file, un qualunque dispositivo di I/O da cui possono essere letti o su cui possono essere scritti dei byte di informazioni n file di testo n Il linguaggio C n n 70 I File quando si desidera elaborare un file, occorre dichiarare un puntatore ad una struttura di dati apposita, di nome FILE e definita nel file stdio.h n la prima operazione che deve essere effettuata su di un file è la sua apertura FILE* fopen(char* nomefile, char* modalit à); Es. FILE* mio_file; n 68 la struttura serve per memorizzare informazioni interne indispensabili per l’elaborazione successiva del file stesso; chi scrive il programma non è tenuto a conoscerne l’effettivo contenuto il puntatore serve, all’i nterno del programma , per fare riferimento al file interessato, nelle successive operazioni tale struttura non deve essere dichiarata per i tre file standard Il linguaggio C 71 q q nomefile rappresenta il nome effettivo del file modalità specifica il modo in cui il file verrà aperto; condiziona le successive operazioni sul file stesso n la funzione fopen() crea una struttura di dati di tipo FILE, restituisce come risultato il puntatore a tale struttura; in caso di errore (file inesistente, ... ) restituisce null n i tre file standard , vengono aperti automaticamente Il linguaggio C 72 12 I File “r” “w” “a” “r+” “w+” “a+” I File apre un file di testo esistente consente operazioni di lettura si posiziona all’inizio del file crea un nuovo file di testo consente operazioni di scrittura (aggiunta di linee alla fine del file) apre un file di testo esistente si posiziona alla fine del file consente operazioni di scrittura (aggiunta di linee alla fine del file) apre un file di testo esistente consente operazioni di lettura e di scrittura (in un qualunque punto, con sovrascrittura dei byte preesistenti) si posiziona all’inizio del file crea un nuovo file di testo consente operazioni di lettura e di scrittura apre un file di testo esistente si posiziona alla fine del file consente operazioni di scrittura n Alla fine delle elaborazioni l’operazione di chiusura di un file, occorre effettuare int fclose (FILE* puntatore ) q q q q libera la struttura di dati abbinata al file in caso di scritture, garantisce che tutti i dati scritti sul file, siano effettivamente trasferiti su disco ritorna 0 se conclusa correttamente comunque, alla terminazione di un programma C, il programma stesso provvede a chiudere tutti gli eventuali file ancora aperti (ma non ne garantisce la corretta scrittura) Inserendo la lettera “ b” si ottengono le analoghe modalità per i file binari Il linguaggio C 73 File di Testo n Il linguaggio C Esempio per leggere un carattere da un file di testo, si utilizza la funzione: /* legge i caratteri presenti in un file di testo e li invia al monitor */ #include < stdio.h> int main(){ char c,nome[100]; FILE* f; printf ( “Specificare i l nome del file: ”) ; equivale a: scanf (“ %s ”, & nome ); f=fopen(nome, “r”); if ((f= fopen(nome , “r ”)) = = NULL) if(f == NULL) printf (“ Errore apertura file \n ”) ; … else{ while((c= fgetc(f ))!= EOF) putchar (c); equivale a: fclose(f ); c=fgetc (f); } while(c!= NULL) { return 0; putchar (c); c=fgetc (f); } int fgetc (FILE* puntatore) q q q q 74 legge un carattere dal file ed avanza sul carattere successivo restituisce il carattere letto sotto forma di numero int (con i bit oltre il primo byte, tutti uguali a zero) restituisce il carattere ‘\n’ quando viene incontrata la fine di una riga; restituisce ‘\n’ quando è effettivamente incontrato nel file restituisce un valore apposito, rappresentato dalla costante E O F (definita in stdio.h, solitamente con il valore -1), per indicare che si è raggiunta la fine del file } Il linguaggio C 75 File di Testo n Il linguaggio C Esempio per scrivere un carattere in un file (di testo o binario), si utilizza la funzione: /*aggiunge u n a r i g a alla fine di un file di testo, leggendo i caratteri d a tastiera*/ #include < stdio.h> int main(){ char c,nome[100]; int fputc(int carattere , FILE* puntatore); q scrive un carattere nella posizione corrente del file q ritorna il carattere scritto, in caso di successo, EOF in caso di errore qualora si scriva il carattere di codice ‘\n’ in un file di testo, si ha l’effetto di chiudere la linea corrente del file q 76 FILE* f; printf (“Specificare il nome del file:”); scanf (“%s”, &nome); getchar(); /* elimina ‘\n’ dal buffer della tastiera */ if ((f=fopen(nome, “a”)) == NULL) printf (“Errore apertura file\n”); else{ do{ c=getchar(); fputc(c, f); }while (c!= ’\n’); fclose(f ); } return 0; } Il linguaggio C 77 Il linguaggio C 78 13 File di Testo n Esempio Per leggere una stringa da un file (di testo o binario), avanzando del numero di caratteri corrispondente, si utilizza la funzione: char* fgets(char* stringa,int lunghezza,FILE* puntatore); q occorre specificare la stringa destinata a contenere i caratteri letti ed il numero massimo di caratteri che possono essereletti (compresi i caratteri ‘\n’ e ‘ \0’) q alla fine della stringa letta, viene memorizzato anche il carattere ‘\n’, oltre al carattere di fine stringa‘\0’ q la funzione termina quando viene letto il carattere ‘ \n’ (effettivo o convertito) oppurequando viene esaurita la lunghezza specificata q ritorna NULL in caso di fine file o in caso di errore; ( ritorna il puntatore alla stringafornita come parametro, in caso di successo) Il linguaggio C 80 /* leggedelle stringhe e l e scrive in un file di testo nuovo; termina quando viene inserita una riga vuota */ #include < stdio.h> #include < string.h> int main() { char nome[100], r i g a[100]; FILE* f; p r i n t f (“ Specificare il nome d e l f i l e :”); int fputs(const char * stringa,FILE* puntatore); q Il linguaggio C Esempio per scrivere una stringa in un file (di testo o binario), si utilizza la funzione: q Il carattere ‘\n’ è già presente nella stringa letta 79 File di Testo n /*legge le righe di un file di testo e le visualizza*/ #include < stdio.h> int main() { char nome[100],riga[100]; FILE *f; printf ( “Specificare i l nome del file: ”) ; scanf (“ %s ”, & nome ); getchar(); /* elimina ‘\ n’ dal buffer della tastiera */ if ((f= fopen(nome , “r ”)) = = NULL) printf ( “Errore apertura file\ n” ); else{ while (fgets(riga,100,f)!= NULL) printf(“ %s ”,riga ); fclose(f) ; } return 0;} non aggiunge automaticamente il carattere ‘\n’ alla fine della linea ritorna EOF in caso di errore scanf (“% s”, &nome ); getchar(); /* elimina ‘\n’ d a lbuffer della tastiera * / i f ( ( f= fopen(nome, “w” )) = = NULL) printf (“ Errore apertura f i l e\n ”); else { do { gets(riga) ; if (riga[0]!= ’\0’ ) { strcat(riga, “\ n”) ; fputs(riga,f ); } }while (riga[0]!=’ \0’ ); fclose(f); } return 0;} Il linguaggio C 81 n Sono le analoghe di printf e scanf solo che va specificato il file su cui scrivere o leggere Esempi q q 82 /* Legge due temperature in gradi Celsius da un file, li converte in gradi Fahrenheit e li salva sul secondo file*/ fscanf e fprintf n Il linguaggio C fscanf(miofile, “%d”,&intero); fprintf(miofile, “%d\n”,intero); Il linguaggio C #include < stdio.h > int main() { float c1, c2, f1, f2; char nomein [20], nomeout [20]; FILE* filein, fileout ; printf (“Specificare il nome del file di input:”); scanf (“%s”, &nome); getchar(); /* elimina ‘\n’ dal buffer della tastiera */ if (( filein= fopen(nomein, “r”)) = = NULL) printf (“Errore apertura file di input\n”); else { printf (“Specificare il nome del file di output:”); scanf (“%s”, &nomeout); getchar (); /* elimina ‘\n’ dal buffer della tastiera */ if ((fileout= fopen(nomeout, “w”)) == NULL) printf (“Errore apertura file di output\n”); else { fscanf(filein , "%d", &c1); fscanf(filein, "%d", &c2); fprintf(fileout, "%d ", f1); /*mettiamo esplicitamente lo spazio di separazione */ f1=32+c1*9/5; f2=32+c2*9/5; fprintf(fileout, "%d", f2); /* fra il 1 e 2 numero con uno spazio dopo il %d */ fclose(fileout ); } fclose(filein); } return 0;} 83 14 Ordinamento bubble sort L’Ordinamento di vettori Ordinare il vettore 5, 3, 7, 4, 10 Ciclo di scambi (1- ciclo ) (2 - ciclo) (3 - ciclo) n n l’algoritmo bubble sort 5, 3, 7, 4, 10 3, 5, 7, 4, 10 J 3, 5, 7, 4, 10 3, 5, 4, 7, 10 3, 5, 4, 7, 10 3, 4, 5, 7, 10 J 3, 4, 5, 7, 10 3, 4, 5, 7, 10 3, 4, 5, 7, 10 3, 5, 4, 7, 10 J 3, 4, 5, 7, 10 3, 4, 5, 7, 10 3, 5, 4, 7, 10 3, 4, 5, 7, 10 3, 4, 5, 7, 10 2 scambi 1 scambi 3e4 4e5 86 void leggi(int v[]) {int i; printf(“fornire la lunghezza del vettore < %d\n”,MAX); scanf(“%d”,&size); for (i=0;i<size;i=i+1) {printf(“elemento di posto %d valore?\n”, i); scanf(“%f”,&v[i]); printf(“valore %f\n”, v[i]);} } void scrivi(int v[]) {int i; for (i=0;i<size;i=i+1) printf(“elemento di posto %d e valore\n”, i, v[i]); } 87 Ordinamento bubble sort Il linguaggio C 88 Puntatori n void bubblesort(int v[], int iniz, int fine) {int nonscambio, i; float temp; do{ nonscambio=true; for (i=iniz; i<fine;i=i+1) {if (v[i]>v[i+1] {nonscambio=false; temp=v[i]; v[i]=v[i+1]; v[i+1]=temp; } } } while(!nonscambio) } Il linguaggio C 2e3 Ordinamento bubble sort #define MAX 5 #define true 1 #define false 0 int size; //dimensione corrente del vettore void bubblesort(int v[], int inz, int fine); void leggi(int v[]); void scrivi(int v[]); main() {float vett[MAX]; printf (“ ordinamento di un vettore”); leggi(vett); bubblesort(vett,0, size -1); scrivi(vett);} Il linguaggio C 1e2 0 scambi Il linguaggio C Ordinamento bubble sort partenza n n n n 89 L’indirizzo di un dato presente in memoria prende anche il nome di puntatore a quel dato è possibile memorizzare i puntatori all’interno di opportune variabili (variabili puntatore ) quando si dichiara una variabile puntatore, si deve specificare il tipo del dato a cui essa punta; ad esempio: int *p l’operatore & applicato al nome di un dato, restituisce l’indiri zzo di quel dato p = &i; l’operatore * applicato ad un puntatore, consente di fare riferimento al dato puntato, il valore che si assegna ad un puntatore per indicare che esso non punta a nessun dato è rappresentato dalla costante NULL (definita in stdio.h) Il linguaggio C 90 15 Allocazione Dinamica della Memoria Esempio Legge due numeri e visualizza il maggiore dei due #include <stdio.h> main () { int m,n,*maggiore; printf (“Inserire due numeri: “); scanf (“%d %d”,&m, &n); if (m>n) maggiore = &m; else maggiore = &n; printf (“Il maggiore vale %d \n”, *maggiore ); } n Il linguaggio C n q q n 91 q n n malloc: alloca un blocco di memoria contigua; richiede la dimensione in byte calloc: alloca un blocco di memoria contigua; richiede il n numero di elementi e la loro dimensione q q q q n Il linguaggio C 94 Esempio la dimensione dei singoli elementi dipende in genere dalla macchina; per rendere i programmi portabili, il C mette a disposizione la funzione: size_t sizeof ( <variabile >| <tipo >) essa restituisce come risultato la dimensione in byte della variabile o del tipo di dato specificato printf (“%d%d”,sizeof(x),sizeof(double)); Il linguaggio C num è il numero di elementi da allocare dim è la dimensione in byte di ciascun elemento size_t è un tipo definito in stdlib.h, per motivi di portabilità dei programmi; può assumere valori interi ed è solitamente dichiarato 93 Allocazione dinamica della Memoria n 92 la funzione dello standard ANSI solitamente richiamata per allocare memoria destinata ad un array, è: void *calloc(size_t num, size_t dim); essa restituisce come risultato un puntatore a void (per cui può essere assegnata ad un puntatore di qualsiasi tipo); in caso di errore ritorna NULL q realloc: modifica la dimensione di un blocco di memoria allocato in precedenza free: libera la memoria di un blocco precedentemente allocato Il linguaggio C Il linguaggio C Allocazione dinamica della Memoria la zona di memoria destinata all’allocazione dinamica è denominata memoria heap le funzioni standard per la gestione della memoria dinamica sono dichiarate nel file stdlib.h q la dimensione della memoria necessaria è nota solamente al momento dell’esecuzione si vuole riutilizzare la stessa memoria per scopi diversi la memoria allocata dinamicamente può essere rilasciata, rendendola disponibile per eventuali ulteriori allocazioni dinamiche durante l’esecuzione del programma; alla terminazione del programma la memoria dinamica viene comunque rilasciata n Allocazione dinamica della Memoria n un programma C può richiedere memoria direttamente durante la sua esecuzione (allocazione dinamica), nei punti in cui ciò si rende necessario l’allocazione dinamica è particolarmente utile quando: n /* Legge n numeri interi e li visualizza in ordine inverso; la quantità n viene richiesta al momento dell’esecuzione */ #include <stdio.h> #include <stdlib.h> main(){ int *p,n,i; printf(“Inserire il numero di elementi:”); scanf(“ %d”, &n) ; p = calloc(n, sizeof(int)); if (p == NULL) printf(“memoria insufficiente\n”); else{ for(i=0; i<n; i++) { printf (“Inserire un numero:”); scanf (“%d”, &p[i]); } for(i=n- 1; i>=0; i--) printf (“%d\n”, p[i]); } } 95 Il linguaggio C 96 16 Programmazione Ricorsiva n Programmazione Ricorsiva Molti linguaggi di programmazione consentono ad un programma di chiamare direttamente o indirettamente se stesso (chiamata ricorsiva) Chiamata diretta Chiamata indiretta Programma P …. Esegui P ….. Programma P …. Esegui Q ….. Programma Q … Esegui P …. Il linguaggio C n Esempio: funzione per il calcolo del fattoriale di un numero int fattoriale (int n) { i f (n <= 1) return 1; else return n fattoriale(n-1); } n 97 la ricorsione è resa possibile dal fatto che ogni qualvolta una funzione viene richiamata, viene creato nello stack, un nuovo ambiente locale alla particolare attivazione della funzione stessa Il linguaggio C 98 Stack n lo stack (pila) è una regione di memoria : q q q q q in cui è possibile aggiungere o eliminare dei dati (memoria dinamica) presenta una dimensione massima prefissata l’ultimo dato inserito è il primo ad essere eliminato (LIFO) viene gestita automaticamente dal programma, ed in particolare al suo interno vengono memorizzati: n n n l’indirizzo di ritorno per le funzioni, al momento della loro chiamata (vengono estratti al momento del ritorno al chiamante) le variabili locali, in corrispondenza della loro dichiarazione (vengono eliminate all’uscita dal loro ambiente di visibilità) i parametri delle funzioni, al momento della loro chiamata (vengono eliminati quando si ritorna al chiamante) Il linguaggio C 99 17