570 likes | 686 Views
LA LIBRERIA STANDARD DEL C. La libreria standard del C è in realtà un insieme di librerie Per usare una libreria, non occorre inse-rirla esplicitamente nel progetto : ogni ambiente di sviluppo sa già dove cercarle Rhide: C:DJGPPLIB Turbo C: vedi Options/Project/Directories
E N D
LA LIBRERIA STANDARD DEL C • La libreria standard del C è in realtà un insieme di librerie • Per usare una libreria, non occorre inse-rirla esplicitamente nel progetto: ogni ambiente di sviluppo sa già dove cercarle • Rhide: C:\DJGPP\LIB • Turbo C: vedi Options/Project/Directories • Ogni file sorgente che ne faccia uso deve però includere lo header opportuno, che contiene le dichiarazioni necessarie.
LA LIBRERIA STANDARD DEL C Le librerie standard • input/output stdio.h • funzioni matematiche math.h • gestione di stringhe string.h • operazioni su caratteri ctype.h • gestione dinamica della memoria stdlib.h • ricerca ed ordinamento stdlib.h • … • ... e molte altre.
IL MODELLO DI COORDINAZIONE DEL C • Libreria standard stdio • l’input avviene di norma dal canale standard di input(stdin) • l’output avviene di norma sul canale standard di output (stdout) • input e output avvengono sotto forma di una sequenza di caratteri • tale sequenza è terminatadallo speciale carattere EOF(End-Of-File), che varia da una piattaforma all’altra.
I CANALI STANDARD Di norma: • il canale standard di input, stdin, coincide con la tastiera • il canale standard di output, stdout, coin-cide con il video Esiste inoltre un altro canale di output, riservato ai messaggi di errore: stderr. • anch’esso di norma coincide con il video Avere un canale separato per i messaggi di errore è utile se stdout viene ridiretto su un altro dispositivo fisico (stampante, modem, etc): così i messaggi d’errore rimangono sul video.
IL MODELLO DI COORDINAZIONE DI BASE • Poiché sui canali di I/O fluiscono sequen-ze di caratteri, il modello di coordinazio-ne prevede due operazioni base: • scrivere un carattere sul canale di output putchar(ch); • leggere un carattere dal canale di input ch = getchar(); • Ogni altro tipo di I/O può essere costruito a partire da queste operazioni primitive.
I/O A CARATTERI • int putchar(int ch); • scrive un carattere sul canale di output • restituisce il carattere scritto, o EOF in caso di errore. • int getchar(void); • legge un carattere dal canale di input • restituisce in carattere letto, o EOF in caso la sequenza di input sia finita, o in caso di errore. Entrambe le funzioni leggono/scrivono un carattere convertito in int (senza estensione di segno): ciò assicura che il valore numerico del carattere non sia mai negativo (escluso, eventualmente, il solo carattere speciale EOF).
ESEMPIO Ricopiare l’input standard sull’output standard, carattere per carattere. #include <stdio.h> main(){ int c; while(( c=getchar() ) != EOF) putchar(c);} Per chiudere l’input producendo un EOF da tastiera, CTRL+Z in sistemi Windows, CTRL+D in Unix. Attenzione: getchar() inizia a produrre caratteri solo dopo aver premuto INVIO.
I/O DI TIPI PRIMITIVI Ogni altro tipo di I/O può essere costruito sulle due primitive putchar() e getchar(). Esempi • scrivere o leggere stringhe di caratteri • scrivere o leggere la rappresentazione di un numero (naturale, intero, reale) sotto forma di stringa, in una base data. Come vedremo, queste funzionalità sono fornite giàpronte nella libreria di I/O standard: è però molto istruttivo capire come costruircele da soli.
I/O DI STRINGHE DI CARATTERI Scopo: • data una stringa di caratteri (correttamen-te terminata da ‘\0’), scriverla sull’output standard (andando a capo a fine stringa) void printString(char s[]); • dato un array di caratteri vuoto, leggere una stringa da input standard (considerando la stringa finita a fine riga) void readString(char s[]);
SCRITTURA DI STRINGHE SU stdout Data una stringa di caratteri (terminata da ‘\0’), scriverla sull’output standard, andando a capo a fine stringa. #include <stdio.h> void printString(char s[]){ while(*s) putchar(*s++); putchar('\n'); }
LETTURA DI STRINGHE DA stdin Dato un array di caratteri vuoto e lungo a suffi-cienza, leggere una stringa da input standard, considerando la stringa finita a fine riga. #include <stdio.h> void readString(char s[]){ int c; while((c=getchar())!=EOF && c!='\n') *s++ = c; *s = '\0'; }
I/O A STRINGHE La libreria standard offre le seguenti funzioni: • int puts(char s[]); • scrive la stringa sul canale di output, omettendo il terminatore ‘\0’, e aggiungendo un newline in fondo • restituisce EOF in caso di errore, o un valore non negativo altrimenti. • char* gets(char s[]); • legge dal canale di input una stringa terminata dal carattere newline (‘\n’), che però viene omesso; al suo posto introduce in fondo il terminatore ‘\0’ • restituisce l’indirizzo della stringa letta, o NULL (un valore zero) in caso di fine sequenza o di errore.
ESEMPIO Ricopiare l’input standard sull’output standard, riga per riga. #include <stdio.h> main(){ char s[81]; /* lung. max riga */ while(gets(s)) != NULL) puts(s);} Per chiudere l’input, premere CTRL+Z in sistemi Win- dows (CTRL+D in Unix) su una riga vuota, poi INVIO. Attenzione: gets() fornisce la stringa solo dopo aver premuto INVIO.
ESERCIZIO Costruire puts() e gets() da putchar() e getchar() int puts(char s[]) {int j; for (j = 0; s[j] != '\0'; j++) if ( putchar(s[j]) == EOF) return EOF; if ( putchar('\n') == EOF) return EOF; return 0; } int puts(char s[]) { int j = 0; do if(putchar(s[j] ? s[j] : '\n') == EOF) return EOF; while (s[j++]); return 0; }
I/O DI VALORI NUMERICI Scopo: • dato un numero calcolare la stringa di caratteri che lo rappresentain una data base, e scrivere tale stringa sull’output void printInteger(int n);void printDouble(double f); • leggere da input una stringa di caratteri che rappresenta un numeroin una data base, e calcolare il valore del numero int readInteger(void);double readDouble(void);
SCRITTURA DI NUMERI SU stdout Dato un numero intero, calcolare la stringa di caratteri che lo rappresenta in una data base, e scrivere tale stringa sull’output standard. #include <stdio.h>#include "myNumbers.h" void printInteger(int x){ char s[20]; intToS(10,x,s); puts(s); } In alternativa si può usare la funzione (non standard) itoa(int x, char* s, int base) che si trova in stdlib.h.
SCRITTURA DI NUMERI SU stdout Dato un numero reale, calcolare la stringa che lo rappresenta e scriverla sull’output standard. #include <stdio.h>#include <stdlib.h> void printDouble(double x){ char *p; int i=0, point, sign; p = fcvt(x,14,&point, &sign); if (sign!=0) putchar('-'); while(point>i) putchar(p[i++]); putchar('.'); puts(p+i); } Funzione di libreria (non standard)
FUNZIONI DI CONVERSIONE STANDARD La libreria standardstdlib fornisce quasi tutte le funzioni di conversione già pronte • da stringa a numero • atoi() da stringa a intero • atol() da stringa a long • atof() da stringa a double • da numero a stringa (solo Turbo C) • itoa() da intero a stringa • ltoa() da long a stringa • fcvt() da double a stringa Il C standard usa sprintf(), che vedremo più avanti.
LETTURA DI NUMERI DA stdin Leggere da input una stringa che rappresenti un numero intero in base dieci, e calcolarne il valore corrispondente. #include <stdio.h>#include "myNumbers.h" int readInteger(void){ char s[20]; gets(s); return sToInt(10,s,strlen(s)); } Ipotesi: la stringa sta su una riga a sé stante. Si può usare la funzione di libreria int atoi(char* s)
LETTURA DI NUMERI DA stdin Leggere da input una stringa che rappresenti un numero reale in base 10, e calcolarne il valore corrispondente. #include <stdio.h>#include <math.h> double readDouble(void){ char s[20]; gets(s); return atof(s); } Ipotesi: la stringa sta su una riga a sé stante.
I/O FORMATTATO La libreria standard offre due funzioni di I/O di uso generale, che compendiano tutte le necessità precedenti: printf() e scanf() • int printf(...); • scrive sul canale di output una serie di valori, effettuando le conversioni richieste ove necessario • restituisce il numero di caratteri emessi • int scanf(...); • legge dal canale di input una serie di campi, effettuando le conversioni richieste ove necessario • restituisce il numero di campi letti.
I/O FORMATTATO Le funzioni printf() escanf(): • possono avere un numero variabile di parametri • possono scrivere/leggere • singoli caratteri • stringhe di caratteri formattate nel modo indicato dall’utente • interi, con o senza segno, in base 8, 10, 16 • reali (float o double) in vari formati
OUTPUT FORMATTATO: printf() Sintassi: int printf(char frm[], e1,…, eN) • la funzione scrive sul canale di outputi risultati delle espressioni e1, …, eNnel formato specificato dalla stringa frm[] • restituisce il numero di caratteri scritti, o EOF in caso di errore.
OUTPUT FORMATTATO: printf() La stringa di formato frm[] int printf(char frm[], e1,…, eN) è una stringa che può contenere specifiche di formato, del tipo %carattere Formati per caratteri e stringhe:
OUTPUT FORMATTATO: printf() Formati per numeri:
ESEMPIO 1 #include <stdio.h> main() { float z = 3.1415; int ret = 5; char msg[50] = "Finalmente si stampa!"; printf("Valori: ret=%d, z=%f, msg=%s\n", ret, z, msg);} int (decimale) float stringa
ESEMPIO 2 La stringa di formato può essere per comodità spezzata in più stringhe, che vengono concatenate automaticamente. #include <stdio.h> main() { int a; printf("Immettere un carattere: "); a = getchar(); printf("\n%c rappresenta %d come intero" "decimale, %o in ottale e %x in hex", a, a, a, a);} char int (ottale) int (decimale) int (esadecimale)
INPUT FORMATTATO: scanf() Sintassi: int scanf(char frm[], add1,…, addN) • la funzione legge dal canale di input tanti campi quanti ne specifica la stringa di formato frm[], e li pone in memoria agli indirizzi denotati da add1, …, addN • restituisce il numero di campi letti (0 se non ha letto nulla), o EOF in caso di errore.
INPUT FORMATTATO: scanf() La stringa di formato frm[] int scanf(char frm[], add1,…, addN) specifica esattamente ciò che ci si aspetta in input, tramite specifiche %carattere Formati per caratteri e stringhe: NB: scanf considera finita la stringa al primo spazio o se- paratore che incontra. Quindi non si può usare scanf per leggere una stringa contenente spazi.
INPUT FORMATTATO: scanf() Formati per numeri:
ESEMPIO 3 #include <stdio.h> main() { float x; int ret, i; char name[50]; printf("Inserisci un numero decimale, "); printf("un float ed una stringa con meno"); printf("di 50 caratteri e senza spazi: "); ret = scanf("%d%f%s", &i, &x, name); printf("%d valori letti: %d, %f, %s", ret, i, x, name);} int (decimale) float stringa ? ?
ESEMPIO 3 Indirizzi di variabili • per tipi semplici, occorre ricavare sempre l’indirizzo con l’operatore & • per le stringhe, il nome è già un indirizzo, quindi & non va mai usato. #include <stdio.h> main() { float x; int ret, i; char name[50]; printf("Inserisci un numero decimale, "); printf("un float ed una stringa con meno"); printf("di 50 caratteri e senza spazi: "); ret = scanf("%d%f%s", &i, &x, name); printf("%d valori letti: %d, %f, %s", ret, i, x, name);} indirizzo di una variabile int indirizzo di una variabile float nome di una stringa (è già un indirizzo)
ESEMPIO 3 (variante) #include <stdio.h> main() { float x; int ret, i; char name[50]; int *pi = &i; float *px = &x; printf("Inserisci un numero decimale, "); printf("un float ed una stringa con meno"); printf("di 50 caratteri e senza spazi: "); ret = scanf("%d%f%s", pi, px, name); printf("%d valori letti: %d, %f, %s", ret, i, x, name);} Gli indirizzi possono essere passati a scanf() anche attraverso idonei puntatori.
scanf(): PRECISAZIONI • In scanf(), la stringa di formato frm[] è tipicamente una sequenza di specifiche %caratteresenza spazi o altri caratteri intermedi. Ad esempio: scanf("%d%d%f", ...) • non deve contenere messaggi! scanf("inserire un int: d%", …) Infatti, la stringa di formato descrive esattamente quello che ci deve essere in input, non ha nulla a che fare con i messaggi che si vogliono in output!!
scanf(): PRECISAZIONI • Inserire spazi o altri caratteri nella stringa di formato di scanf() è quindi possibile, ma ha il significato di richiedere che tali caratteri siano obbligatoriamente presenti in input:se mancano, scanf() dà errore. • Ad esempio: Nella prima forma, i caratteri devono essere separati da uno spazio, altrimenti...
scanf(): PRECISAZIONI • Questa caratteristica può essere sfruttata per leggere dati formattati in modo partico-lare, come ad esempio una data (gg/mm/aa) scanf("%d/%d/%d", &g, &m, &a); • In questo modo, scanf() filtra automatica-mente i dati, eliminando le barre e “cattu-rando al volo” gli interi che interessano.Se anche solo una barra manca errore • Dulcis in fundo, scanf() elimina automatica-mente gli spazi di separazione fra i campi.
ESEMPIO 4 Leggere (e poi riscrivere) nome, cognome, e data di nascita di una persona. #include <stdio.h> main() { struct { char cognome[20], nome[20]; int g, m, a; } p; printf("Cognome, nome e data di nascita: "); scanf("%s%s%d/%d/%d", p.cognome, p.nome, &p.g, &p.m, &p.a); printf("%s %s è nato il %d/%d/%d\n", p.cognome, p.nome, p.g, p.m, p.a);} Gli spazi di separazione sono eliminati automaticamente
DUE VARIANTI: sprintf() e sscanf() • printf() e scanf() operano su console • sprintf() e sscanf() operano su una stringa char os[DIM], is[DIM];sprintf(os, ...);sscanf(is, ...); • sprintf() scrive il risultato sulla stringa os invece che sull’output standard • sscanf() legge i campi dalla stringa is invece che dall’input standard
DUE VARIANTI: sprintf() e sscanf() • printf() e scanf() operano su console • sprintf() e sscanf() operano su una stringa char os[DIM], is[DIM];sprintf(os, ...);sscanf(is, ...); • sprintf() scrive il risultato sulla stringa os invece che sull’output standard • sscanf() legge i campi dalla stringa is invece che dall’input standard Adattissime per fare conversioni numero / stringa (sprintf) e stringa / numero (sscanf)
DUE VARIANTI: sprintf() e sscanf() Conversione stringa (s) / numero (n) sscanf(s,"%d", &n); • sscanf() legge un intero decimale dalla stringa s, lo converte, e lo pone in n Conversione numero (n) / stringa (s) sprintf(s,"%d", n); • sprintf() converte l’intero n in stringa (rappr. decimale) e lo scrive sulla stringa s
DUE VARIANTI: sprintf() e sscanf() Conversione stringa (s) / numero (n) sscanf(s,"%d", &n); • sscanf() legge un intero decimale dalla stringa s, lo converte, e lo pone in n Conversione numero (n) / stringa (s) sprintf(s,"%d", n); • sprintf() converte l’intero n in stringa (rappr. decimale) e lo scrive sulla stringa s Equivale a scriveren = atoi(s);ma è più flessibile
ALTRE LIBRERIE STANDARD Le seguenti librerie forniscono funzioni utili: Elenchiamo ora le funzioni più importanti che esse mettono a disposizione.
ALTRE LIBRERIE STANDARD ctype.h (funzioni sui caratteri) conio.h (funzioni di I/O diretto da console) string.h (funzioni sulle stringhe)
ALTRE LIBRERIE STANDARD math.h (funzioni matematiche) stdlib.h (funzioni varie)
ESEMPIO 5 Lettura diretta da tastiera con getch() e ungetch(). #include <stdio.h> #include <ctype.h> #include <conio.h> main() { int val=0; char ch; puts("Inserire un intero e un char: "); while((ch = getche()) != EOF && isdigit(ch)) val = 10 * val + ch - '0'; if (ch != EOF) ungetch(ch); printf("\nValore = %d, prossimo = %c\n", val, getch()); } getch() preleva il carattere e non lo mostra a videogetche() invece lo mostra Se il carattere letto non è una cifra, lo “rimanda indietro”
ESERCIZIO: CODICE FISCALE Problema (non banale!): Scrivere un programma che, a partire dai dati anagrafici, calcoli il codice fiscale di una persona. Il C.F. è composto di 5 parti: • tre lettere identificative del cognome; • tre lettere identificative del nome; • due cifre, una lettera e altre due cifre,indicanti sesso e data di nascita; • una lettera e tre cifre, indicanti il Comune di nascita; • una lettera di controllo, calcolata sulla base delle lettere e delle cifre precedenti.
ESERCIZIO: CODICE FISCALE Le prime tre consonanti (se non bastano,le vocali; se non bastano ancora, una X) Problema:Scrivere un programma che, a partire dai dati anagrafici, calcoli il codice fiscale di una persona. Il C.F. è composto di 5 parti: • tre lettere identificative del cognome; • tre lettere identificative del nome; • due cifre, una lettera e altre due cifre, indicanti sesso e data di nascita; • una lettera e tre cifre, indicanti il Comune di nascita; • una lettera di controllo, calcolata sulla base delle lettere e delle cifre precedenti. Esempi:ROSSI MARIO RSS MRAROSSI GASTONE RSS GTN La prima, la terza e la quarta consonante(se non ci sono quattro consonanti, si usanole prime tre; se non bastano, si usano levocali; se non bastano ancora, una X)
ESERCIZIO: CODICE FISCALE Anno, mese e giorno di nascitaPer le donne, giorno aumentato di 40Mese = A, B, C, D, E, H, L, M, P, R, S, T Problema:Scrivere un programma che, a partire dai dati anagrafici, calcoli il codice fiscale di una persona. Il C.F. è composto di 5 parti: • tre lettere identificative del cognome; • tre lettere identificative del nome; • due cifre, una lettera e altre due cifre, indicanti sesso e data di nascita; • una lettera e tre cifre, indicanti il Comune di nascita; • una lettera di controllo, calcolata sulla base delle lettere e delle cifre precedenti. Esempi:01/02/1978 (maschio) 78B0125/12/1969 (femmina) 69T65 Sigla che si trova su apposite tabelleBologna = A944,Reggio Emilia = H223, etc
ESERCIZIO: CODICE FISCALE Cifre 0 9 Lettere A JLettere di posto pari (2,4,..) 0-25Lettere di posto dispari (1,3,…) vedi tabella:B A K P L C Q D R E V O S F T G U0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16H M I N J W Z Y X 17 18 19 20 21 22 23 24 25 Alla fine, si somma tutto e si prende il risul-tato modulo 26. Problema:Scrivere un programma che, a partire dai dati anagrafici, calcoli il codice fiscale di una persona. Il C.F. è composto di 5 parti: • tre lettere identificative del cognome; • tre lettere identificative del nome; • due cifre, una lettera e altre due cifre, indicanti sesso e data di nascita; • una lettera e tre cifre, indicanti il Comune di nascita; • una lettera di controllo, calcolata sulla base delle lettere e delle cifre precedenti.
ESERCIZIO: CODICE FISCALE Esempio: Rossi Mario, 12/6/76, Bologna R S S M R A 7 6 H 1 2 A 9 4 4 ? R S S M R A H G H B C A J E E ? 18 12 0 6 1 0 4 (pari) 8 12 8 17 17 5 21(dispari) Totale: 129 mod 26 = 25 Z R S S M R A H G H B C A J E E Z Problema:Scrivere un programma che, a partire dai dati anagrafici, calcoli il codice fiscale di una persona. Il C.F. è composto di 5 parti: • tre lettere identificative del cognome; • tre lettere identificative del nome; • due cifre, una lettera e altre due cifre, indicanti sesso e data di nascita; • una lettera e tre cifre, indicanti il Comune di nascita; • una lettera di controllo, calcolata sulla base delle lettere e delle cifre precedenti.