C librerie standard
Il C è un linguaggio ricco di librerie che possono essere opportunamente caricate con la direttiva <include> del compilatore.
La libreria standard C (RunTIme Library) contiene centinaia di funzioni ed è suddivisa in sezioni
Il linker accede, in genere, automaticamente ai codici binari della libreria
Il compilatore, invece,
richiede che tutte le funzioni usate nel programma siano espressamente dichiarate tramite inclusione dei
corrispondenti header-files
Header file Descrizione
ctype.h Funzioni che verificano proprietà dei caratteri
string.h Funzioni di elaborazione di stringhe
stdio.h Funzioni per operazioni di input/output
stdlib.h Funzioni di conversione numeri in stringhe e viceversa, generatori causali, altre utilità
time.h Funzioni manipolazione date e valori temporali
... ...
C libreria ctype.h
La libreria ctype (ctype.h) contiene funzioni che verificano proprietà dei caratteri.
Ritornano un intero e non un booleano (anche se resta inteso che un valore nullo sta per false ed un valore diverso da zero sta per true).
Prototipo Descrizione
int isalnum (int c); Controlla se c è una cifra o una lettera int isalpha (int c); Controlla se c è una cifra o una lettera int isdigit (int c); Controlla se c è una cifra
int iscntrl (int c); Controlla se c è un carattere di controllo int isspace (int c); Controlla se c è un separatore
int isxdigit (int c); Controlla se c è una cifra esadecimale
int tolower (int c); Se c è una lettera, restituisce la sua versione minuscola, altrimenti restituisce c inalterato
int toupper (int c); Se c è una lettera, restituisce la sua versione maiuscola, altrimenti restituisce c inalterato
... …
C libreria ctype.h
Manipolazione di caratteri
int isdigit(int c) {
return ((c>=‘0’)&&(c<=‘9’));
}
int isalpha(int c) {
return (((c>=‘a’)&&(c<=‘z’)) || ((c>=‘A’)&&(c<=‘Z’)));
}
int tolower(int c) {
if isupper( c )
c=c-’A’+’a’;
return c;
}
C libreria stdlib.h
La libreria stdlib (stdlib.h) contiene funzioni di conversione di numeri in stringhe e viceversa, generatori causali, altre utilità
Prototipo Descrizione
int atoi(const char s[]); Converte la stringa C contenuta nell’array s in un intero void itoa(int n, char sn[], int b); Converte il numero intero n in una stringa C, copiata
nell’array sn
double atof(const char s []); Converte la stringa C contenuta nell’array s in un
double. La funzione restituisce 0 se la C non contiene un numero reale valido
int rand (); Genera un numero pseudocasuale
void srand(unsigned int seme); Genera un punto di partenza per la funzione rand().
void exit(int CodiceDiUscita); Provoca l’immediata terminazione del programma e fornisce il CodiceDiUscita al sistema operativo.
int system (const char cmd []); Invia la stringa cmd all’interprete dei comandi del sistema operativo
... …
C libreria stdlib.h
La funzione rand() genera in maniera casuale un numero intero compreso tra 0 e 32767
32767 è il massimo intero rappresentabile con 2 byte
Casuale significa che valore tra 0 e 32767 ha la stessa probabiltà di essere generato
Esempio: simulare il lancio di un dado
n = rand() % 6 + 1;
C libreria stdlib.h
Problema dell’estrazione del lotto: simulare una sequenza casuale di n numeri senza ripetizioni nell’intervallo [0 nr] (n≤nr)
• La sequenza ordinata di valori [0, 1, 2, …, nr] viene “mischiata”:
scorrendo dal primo all’ultimo valore, il valore i-esimo viene scambiato con un altro valore (anche sé stesso) selezionato casualmente
for i from 0 to nr-1:
numeri[i] ß i for i from 0 to nr-1:
indice ß random(0,nr);
temp ß numeri[indice];
numeri[indice] ß numeri[i];
numeri[i] ß temp;
for i from 0 to n-1:
randnumeri[i] ß numeri[i];
Algoritmo
2
numeri
...
indice (casuale) i
1
0
scambia3 4 5 6 89
4 27
33 43 0
randnumeri
75 12 ... 65
C libreria stdlib.h
Se eseguiamo più volte un programma contenente l’istruzione rand() si vede che i valori generati sono sempre gli stessi.
La procedura srand(seme) ha lo scopo di cambiare il valore iniziale e quindi tutta la serie secondo il valore introdotto nella variabile seme.
all’inizio di ogni programma invocando la funzione:
srand(time(0))
si fa sì che le successive invocazioni della funzione rand() generino
unasuccessione diversa di valori casuali ad ogni esecuzione del programma
C libreria time.h
La libreria time (time.h) contiene funzioni di manipolazione date e valori temporali
Prototipo Descrizione
double time(); Restituisce il tempo assoluto in secondi double
localtime(); Converte il tempo assoluto nella rappresentazione suddivisa double asctime(); Converte in stringa il tempo memorizzato in una struttura tm double ciftime(); Calcola intervalli di tempo
double clock(); Restituisce il tempo trascorso dall’inizio dell’esecuzione del programma (in ticks)
... …
struct tm
{int tm_sec; //secondi 0..59 int tm_min; //minuti 0..59 int tm_hour; //ora 0..23 int tm_mday; //giorno 1..31 int tm_mon; //mese 0..11
int tm_year; //anno 0..anno-1900 int tm_wday; //secondi 0..6
int tm_yday; //secondi 0..365 ...
C libreria string.h
La libreria string (string.h) contiene funzioni di manipolazione di stringhe
Prototipo Descrizione
char *strcpy(char *s, char *cs); copia cs in s e ritorna s char *strcat(char *s, char *cs); concatena cs ad s e ritorna s
int strcmp(char *cs1, char *cs2); confronta cs1 e cs2; se cs1 < cs2 il valore di ritorno è < 0; se cs1 > cs2 il valore di ritorno è > 0;
se le due stringhe sono uguali il valore di ritorno è 0 char *strstr(char *cs1, char *cs2); restituisce un puntatore alla prima occorrenza in
cs1 della stringa cs2
size_t strlen(char *cs); restituisce la lunghezza di cs
... …
C librerie personali
Nella scrittura di programmi accade spesso di dover utilizzare le stesse operazioni: un tipico esempio è dato dalle istruzioni di input/output. A questo scopo conviene progettare una sola volta le funzioni che ci
servono per poi tenerle pronte per un possibile riutilizzo.
Costruiamo una funzione per l’inserimento dei numeri interi.
Il file, che chiameremo InsertNumero.h potrà essere richiamato da qualsiasi programma.
C librerie personali
Per costruire una funzione che restituisca solo numeri interi osserviamo che:
1. conviene accettare l’input sotto forma di stringa per poi trasformarlo in numero intero con la funzione di sistema atoi(stringa) contenuta nell’header
<stdlib>;
2. la funzione atoi(stringa) si comporta in questo modo:
a- se il primo carattere non è né una cifra, né il segno + o – allora restituisce il valore 0;
per esempio se digitiamo aa321 restituisce zero; per evitare che ogni digitazione errata corrisponda al valore zero dobbiamo controllare se il primo carattere inserito è 0;
b- se il primo carattere è una cifra oppure è un segno + o – allora restituisce solo il numero corrispondente alle prime cifre digitate; per esempio:
atoi("aa321") à 0 atoi("124-33") à 124
3. considerare la possibilità che il numero inserito sia incluso tra due valori assegnati (per default supporremo che questi valori siano compresi tra –2 miliardi e +2 miliardi).
C libreria inserimento dati
Scriviamo una libreria per l’inserimento di numeri interi
supponiamo l’input come stringa per poi trasformarlo in numero intero con la funzione di sistema atoi(stringa) (includi il file stdlib.h)
il numero inserito è nell’intervallo consentito [-2miliardi, +2miliardi]
function NumeroIntero(limiteinf, limitesup) ok ß ‘falso’
do:
leggi(stringaint)
Numero ß atoi(stringaint)
if ((Numero ≥ limiteinf) and (Numero £ limitesup)):
ok ß ‘vero’
if (Numero=0 and primocarattere(stringaint) ¹ ‘0’) ok ß ‘falso’
while (ok = ‘falso’):
return Numero:
C libreria inserimento dati
Se includiamo il codice nelle nostre librerie per richiamarlo basterà scrivere
#include “InsertNumero.h”
Se il nome del file header viene posto tra “ ” allora il
compilatore si aspetta di trovarlo nella stessa directory del file chiamante, mentre se viene posto tra parentesi angolari
<> lo cerca nella libreria include (in genere settabile come parametro di variabile d’ambiente nel compilatore).
C libreria inserimento dati
Se il file viene richiamato più volte nel corso di un programma, per evitare problemi è possibile utilizzare la direttiva condizionale del compilatore #ifndef.
Scrivere ad esempio
#ifndef INSERT_NUMERO_H
#define INSERT_NUMERO_H
……istruzioni
#endif
significa segnalare al compilatore che in questo programma, con l’istruzione
#define INSERT_NUMERO_H
viene definita la costante INSERT_NUMERO_H; la direttiva
#ifndef
avverte il preprocessore di controllare se è già stata definita la costante INSERT_NUMERO_H
se tale costante non è stata ancora definita, allora devono essere compilate tutte le istruzioni comprese tra #ifndef e #endif, altrimenti quella stessa parte di codice non deve essere presa in considerazione.
#ifdef INSERT_NUMERO_H
#define INSERT_NUMERO_H
#include <stdio.h>
#include <stdlib>
using namespace std;
// PROTOTIPO
int NumeroIntero(const char[], float=-2e9, float=2e9);
// DEFINIZIONE
int NumeroIntero(const char INTEST[],float inf, float sup) {
char INT1[12];
int i,m;
bool OKint=false;
do {
printf(INTEST);
scanf("%d", &INT1);
m=atoi(INT1);
if (m>=inf && m<=sup) OKint=true;
if (INT1[0]!='0' && m==0) OKint=false;
} while(!(OKint));
return m;
}
#endif
C libreria inserimento dati
#include <stdio.h>
#include "InsertNumero.h"
using namespace std;
int main () { int n;
n=NumeroIntero ("Inserire un numero intero:");
printf("%d\n",n);
}
C libreria utilità vettori
Scriviamo una libreria di funzioni di utilità per vettori:
LeggeVettore() - legge un vettore generico di dimensione n Parametri:
• int [] Vet è Vet è il vettore restituito (per un vettore non è necessario introdurre l’operatore & )
• const int n è n rappresenta la lunghezza del vettore assegnato come parametro in input
• char nome è nome è un carattere che rappresenta il nome del vettore
• bool Acaso èAcaso è un valore booleano che, se vale true, assegna a caso i valori del vettore, se false aspetta che siano immessi da tastiera; notiamo che esso è un parametro di default, bool=true nel prototipo
(dichiarazione), per cui se non viene inserito si sottintende true.
• int nr è tutti i valori generati dal computer sono compresi nell’intervallo (- nr; nr) estremi esclusi
C libreria utilità vettori
Scriviamo una libreria di funzioni di utilità per vettori:
StampaVettore() stampa il vettore sul monitor;
i parametri formali sono:
• const int[] a è a è il vettore da stampare (che può anche essere un vettore costante)
• const int n è rappresenta la lunghezza del vettore assegnato come parametro in input
• char nome è un carattere che rappresenta il nome del vettore
C libreria utilità vettori
Scriviamo una libreria di funzioni di utilità per vettori:
La libreria la organizziamo in un unico (header) file // InsertArray.h
#ifndef INSERT_ARRAY_H
#define INSERT_ARRAY_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;
//PROTOTIPI
void LeggeVettore (int [],const int, char, bool=true, int=100);
void StampaVettore (const int [], const int, char);
//DEFINIZIONI ...
C libreria utilità vettori
Scriviamo una libreria di funzioni di utilità per vettori:
...
void LeggeVettore (int vet[],const int n, char nome, bool Acaso, int nr) {
int i;
if (Acaso){
srand(time(0));
for (i=0; i<n; i++) {
vet[i]=rand() % nr - nr/2;
printf("%c[%d]=%d", nome, i, vet[i]);
} }
else {
for (i=0; i<n; i++) {
printf("%c[%d]=%d", nome, i);
scanf("%d", &vet[i]);
} } }
...
C libreria utilità vettori
Scriviamo una libreria di funzioni di utilità per vettori:
...
void StampaVettore (const int a[], const int n, char nome) { int i;
for (i=0; i<n; i++) {
printf("%c[%d]=%d\n", nome, i, vet[i]);
} }
#endif
C libreria utilità stringhe
Scriviamo una libreria di funzioni di utilità per stringhe:
Confronta se due stringhe sono uguali (paragona)
Confronta due stringhe e ritorna un valore booleano, true se le stringhe sono uguali, false altrimenti.
Calcola la lunghezza di una stringa
Restituisce la lunghezza della stringa.
Concatena due stringhe
Restituisce il risultato nella terza.
#ifndef stringhe_array_h
#define stringhe_array_h
#include <stdio.h>
using namespace std;
// PROTOTIPI
bool paragona (const char[], const char[]);
int lung(const char[]);
void concat(const char[], const char[], char[]);
// DEFINIZIONI
//qui vanno inserite le implementazioni delle funzioni
#endif
C libreria utilità stringhe
Utilizziamo la parola chiave const per tutte le variabili di input nella lista dei parametri formali: in questo modo anche una stringa costante può essere passata come parametro.
La prima funzione paragona confronta due stringhe; per verificarne l’uguaglianza è necessario confrontarle carattere per carattere: se due caratteri sono distinti allora le stringhe non sono uguali e la funzione deve restituire false, true altrimenti.
22
22
Finché i due caratteri i-esimi sono uguali
Se la stringa è terminata restituisci TRUE Incrementa l’indice i
Se esce dal ciclo allora i due caratteri sono diversi e quindi
restituisci FALSE
bool paragona (const char s1[], const char s2[]) { int i=0;
while (s1[i]==s2[i]) { if (s1[i]=='\0')
return true;
i++;
}
return false;
}
C libreria utilità stringhe
La seconda funzione lung calcola il numero di caratteri racchiusi in una stringa: è sufficiente scandire la stringa inserendo un contatore nel ciclo (per eliminare il tipico errore off by one viene restituito un valore
decrementato di una unità).
int lung(const char s1[]) { int i=0;
while (s1[++i]!='\0');
return i--;
}
C libreria utilità stringhe
L’ultima funzione concat concatena due stringhe S1 ed S2 in S3.
A questo scopo, si copiano in S3 prima tutti i caratteri di S1, successivamente tutti quelli di S2 ed, infine, si aggiunge il carattere di fine stringa ‘\0’.
void concat(const char s1[], const char s2[], char s3[]) { int i=0,j=0;
while (s1[i]!='\0') { s3[i]=s1[i];
i++;
}
while (s2[j]!='\0') { s3[i++]=s2[j++];
}
s3[i]='\0'; // inserisce il simbolo di fine stringa }
C libreria utilità stringhe
Scriviamo un programma che usa la libreria di funzioni di utilità per stringhe
#include <stdio.h>
#include <stdlib.h>
#include "stringhearray.h"
using namespace std;
int main () {
char t[10],s[10],z[20];
printf("stringa s =");
scanf("%s", s);
printf("stringa t =");
scanf("%s", t);
printf("Lunghezze\ns = %d\nt = %d\n", lung(s), lung(t));
concat(s,t,z);
printf("stringa s concatenata a t = %s\n", z);
if (paragona(s,t))
printf("Le due stringhe sono uguali\n");
else
printf("Le due stringhe NON sono uguali\n");
return 0;
}
C libreria utilità stringhe
Problema: Data una stringa qualsiasi verificare se è palindroma
Una stringa è palindroma quando ha uguali i caratteri che hanno la stessa distanza dal centro della stringa. Per esempio
Palindromi NON palindromi
ANNA AMARA
ADA AROMA
DEOED ODE
baccdccab abcab
detta n la lunghezza della stringa, se è palindroma sarà:
s[i]=s[n-1-i] per ogni i=0,…,n-1
Esercizi su funzioni e array
Esercizi: usare le funzioni di utilità per vettori e per stringhe
1. Generato in modo random un vettore contenente N interi relativi compresi tra –M ed M mediante una procedura, risolvere i seguenti problemi :
scrivere un programma che stampi tutti i numeri positivi e la loro posizione scrivere un programma che stampi tutti i numeri minori o uguali a zero scrivere un programma che stampi il più grande ed il più piccolo e le loro
posizioni
scrivere un programma che stampi tutti i numeri maggiori di un valore dato e le posizioni
scrivere una procedura che restituisca tutte le posizioni dei numeri negativi 2. Definire una funzione Uguali2 che prenda in input un vettore V di interi di
lunghezza n, e restituisca:
true se il vettore contiene almeno due numeri uguali, false altrimenti Esempi: Se V=[1,22,13,24,5] allora Uguali2(V) à false
Se invece V=[1,2,6,24,2] è Uguali2(V) à true
Esercizi su funzioni e array
3. Definire una procedura PrecSegueX che abbia in input un vettore V di interi di lunghezza n, ed un numero X, e:
inserisca all’inizio di V i valori di V minori o uguali ad X (preservandone l’ordine);
inserisca in seguito tutti i valori di V maggiori di X (preservandone l’ordine).
Esempio: Sia V= [56,35,4,2,22]. L’output di PrecSegueX(V,40) deve essere: V=[35,4,2,22,56]
4. Definire una funzione ContaCifre che prenda in input un vettore V di interi di lunghezza n, ed un numero X e conti quante volte tutte le cifre di X siano contenute negli elementi che compongono il vettore
Esempio: Siano V=[484,325,12,8489,48,12487,1284] e X=48;
ContaCifre(V,7,48) à 4
(sono evidenziati i numeri che contengono al loro “interno” il numero 48).
5. Definire una procedura GoDestra, che, assegnato un vettore V di n elementi ed un intero m, 0£ m £ n, sposti verso destra di m passi tutti gli elementi del vettore V
Esempio: Sia V=[7,8,9,0] ed n=4 otteniamo GoDestra(V,3) fa diventare V=[8,9,0,7]
Esercizi su funzioni e array
6. Scrivere una procedura Comuni, che assegnati due vettori V1, V2 di
dimensioni rispettivamente n1 ed n2, ponga in un altro vettore V3 tutti e soli gli elementi di V1 che compaiono anche in V2, conservando l’ordine con cui compaiono in V1
Esempio: Siano V1=[1,2,3,4,5], V2=[5,0,3,0,1], V3 qualunque.
Eseguiamo Comuni(V1, V2,V3). Allora V3 diventa [1,3,5]
7. Definire una procedura PariDispari che dato un vettore V di interi di lunghezza n:
ponga all’inizio di V i valori di V pari, nello stesso ordine in cui si trovavano in V;
li faccia seguire dai valori di V dispari, di nuovo nello stesso ordine in cui si trovano in V.
Esempio: Sia V= [5,3,4,2,1]. Eseguiamo PariDispari si deve avere: V = [4,2,5,3,1]
8. Scrivere una funzione che dato un array V di interi di dimensione n
restituisce true se nell’array V c’è un valore che è uguale alla somma di tutti i valori che lo precedono, false altrimenti
Esempio. V=[1, 4, 4, 9, 3] la funzione restituisce true perché V[3]=9=1+4+4
V=[1,3,5,8,3] la funzione restituisce false
Esercizi su funzioni e array
9. Scrivere una procedura che dati 2 array di interi V1 e V2 di dimensione n restituisce nell’array V3 gli elementi che appartengono a V1 ma non a V2 non ripetuti e in N3 il numero di tali elementi
Esempio: V1= [2, 4, 4, 5, 3] e V2= [7, 3 ,10 ,6 ,7] si deve ottenere V3= [ 2, 4, 5] con N3 =3
10. Scrivere una funzione che data una stringa s ed un carattere car restituisce il numero massimo di caratteri car consecutivi presenti nell’array
Esempio: s = ‘abcaacaaabaa', car=’a’ la funzione deve restituire 3 11. Scrivere una procedura che dato un array a ordinato di dimensione N
inserisce nell’array il valore x in modo tale che l’array dopo l’inserimento sia ancora ordinato
Esempio: Siano a = [2, 3, 7, 11, 24] e x =5 si deve ottenere a = [2, 3, 5, 7, 11,24 ]
Esercizi su funzioni e array
12. Scrivere un programma che, dati due vettori di interi di dimensione N, ne costruisca un terzo di dimensione 2N i cui elementi di posizione pari siano gli elementi del primo vettore e gli elementi di posizione dispari siano gli
elementi del secondo vettore. Strutturare il programma in procedure e funzioni
13. Scrivere un programma che, dato un vettore V1 di reali di dimensione N, ne generi un altro V2 così definito: il primo elemento di V2 è dato dal prodotto degli elementi 1 e 2 di V1, il secondo elemento di V2 è dato dal prodotto degli elementi 3 e 4 di V1, e così via
Esercizi su funzioni e array
14.Scrivere una procedura che genera un vettore V di numeri reali di dimensioni N (N£100). Con tale procedura scrivere un programma che
stampi prima tutti gli elementi di posto dispari e poi quelli di posto pari,
letto un indice h stampi l’indice ed il valore del più piccolo fra i numeri maggiori di V[h];
stampi l’indice ed il valore dei numeri di valore dispari massimo e minimo;
si costruisca e quindi si stampi un secondo array di N elementi tali che il primo
elemento contenga la somma di tutti gli N numeri, il secondo la somma dei numeri dal secondo in poi, il terzo la somma dal terzo in poi e così via;
si stampi l’indice ed il valore dell’elemento massimo fra gli elementi di posto dispari, quindi l’indice ed il valore del minimo fra gli elementi di posto pari;
letto un indice h, si costruisca e quindi si stampi un array di N elementi tali che il
primo sia quello specificato dall’indice, il secondo sia quello precedente e così fino al primo, poi proseguendo dall’ultimo retrocedendo fino a completare l’array.
15.Scrivere un programma che prenda in input un vettore già ordinato di interi e stampi in output l’istogramma delle occorrenze di ogni elemento del vettore.
Esempio. dato il vettore V=[1,1,1,3,5,5,7,7,7,7,10,10], deve stampare:
1 ***
3 *5 **
7 ****
10 **