Title: Nessun titolo diapositiva
1Array e puntatori in C
2Sommario
- Gli array ed i puntatori
- Dichiarazione e memorizzazione di array
- Linizializzazione di array
- Laritmetica dei puntatori
- Il passaggio di puntatori come argomenti di
funzione - Gli algoritmi di ordinamento
- Le stringhe
2
3Gli array ed i puntatori
3
4Gli array
- Nel linguaggio C, un array è un insieme di
variabili dello stesso tipo memorizzate
consecutivamente - Ogni variabile dellarray, detta elemento, può
essere acceduta mediante il nome dellarray ed un
indice (un espressione), con il primo elemento
individuato dallindice di valore 0 - Esempio Memorizzare la temperatura media
registrata per ogni giorno dellanno - Si dichiara un array di 365 elementi (piuttosto
che 365 variabili!), identificati con un solo
nome, e che occupano posizioni di memoria
consecutive - Nota Gli array contengono informazione correlata
(le temperature di un anno, i voti di esame di
uno studente, etc.)
4
5La dichiarazione di array ? 1
- La sintassi della dichiarazione di array è
- La dichiarazione viene effettuata inserendo una
coppia di parentesi quadre dopo il nome
dellarray - La dimensione dellarray viene specificata
inserendo il numero di elementi allinterno delle
parentesi quadre
5
6La dichiarazione di array ? 2
- Il riferimento ad un elemento dellarray è invece
loperazione di accesso al dato elemento ed
avviene utilizzando il nome dellarray seguito
dallindice dellelemento (racchiuso fra
parentesi quadre) - Le istruzioni di dichiarazione di un array e di
riferimento ad un elemento dellarray sono molto
simili nella forma, ma molto diverse nel
significato
/ I seguenti sono riferimenti a elementi
dellarray i valori 0,1,2, specificano gli
elementi cui accedere / daily_temp0 ?
2 daily_temp1 ? 5 daily_temp2 ? 3
/ La seguente è una dichiarazione il
valore 365 specifica il numero di elementi
dellarray / int daily_temp365
6
7La dichiarazione di array ? 3
- Esempio Calcolo della temperatura media annua
?include ltstdio.hgt ?include ltstdlib.hgt ?define
DAYS_IN_YEAR 365 main() int j, sum?0
int daily_tempDAYS_IN_YEAR / si
assegnano i valori a daily_temp / for
(j?0 jltDAYS_IN_YEAR j??) sum ??
daily_tempj printf(La temperatura media
dellanno è d.\n, sum/DAYS_IN_YEAR)
exit(0)
7
8La memorizzazione di array
- Esempio
- ar2 e ar4 sono indefiniti il contenuto delle
posizioni di memoria è quello rimasto da
esecuzioni precedenti (garbage)
int ar5 / dichiarazione / ar0 ? 15 ar1
? 17 ar3 ? 3
8
9Linizializzazione di array ? 1
- La presenza di valori indefiniti in alcuni
elementi dellarray può provocare errori
difficili da rilevare - ? Occorre inizializzare lintero vettore
- Dichiarare larray static (vettore a durata
fissa) gli elementi del vettore, non
inizializzati esplicitamente, vengono posti a
zero - Valori diversi possono essere specificati,
facendoli seguire alla dichiarazione dellarray,
racchiusi fra parentesi graffe tali valori
devono essere espressioni costanti che possano
essere convertite automaticamente nel tipo
dellarray
9
10Linizializzazione di array ? 2
- Esempio
- Nota il valore floating?point 3.5 viene
convertito nel valore intero 3
static int ar5 static int
br5?1,2,3.5,4,5
10
11Linizializzazione di array ? 3
- Specificare un numero maggiore di valori di
inizializzazione, rispetto agli elementi
dellarray, costituisce un errore segnalato dal
compilatore - Se vengono specificati meno valori rispetto alla
dimensione, gli elementi rimanenti vengono
inizializzati a zero - Esempio La dichiarazione
- static int cr5 ? 1,2,3
- produce linizializzazione
- cr0 ? 1
- cr1 ? 2
- cr2 ? 3
- cr3 ? 0
- cr4 ? 0
11
12Linizializzazione di array ? 4
- Se vengono specificati i valori iniziali, può
essere omessa la dimensione dellarray il
compilatore calcola automatica-mente il numero
degli elementi sulla base del numero dei valori
iniziali specificati - Esempio
- static char dr ? a,b,c,d
- comporta la creazione di un array di quattro
elementi, di tipo char, caratterizzati dai valori
iniziali - dr0 ? a
- dr1 ? b
- dr2 ? c
- dr3 ? d
12
13Crittografia ? 1
- Poiché in formato elettronico viene memorizzato e
trasmesso ogni tipo di informazione (anche
personale, quindi coperta da privacy), viene
posta attenzione alla sicurezza rispetto ad
accessi indesiderati - I file, nei sistemi multiutente, sono provvisti
di vari livelli di protezione, il primo dei quali
è costituito dallautenticazione al sistema
tramite password - Oltre ai tipi di protezione standard, il
contenuto di un file riservato può essere
codificato, utilizzando tecniche crittografiche
che producono, a partire dal testo in chiaro, il
cosiddetto crittogramma, o testo cifrato - Il legittimo proprietario del file (e chi da lui
autorizzato) è lunico depositario della chiave
di decodifica ed è lunico in grado di operare
linversione da testo cifrato a testo in chiaro
13
14Crittografia ? 2
- Inoltre, negli attuali sistemi informativi
distribuiti, e più in generale nel settore delle
telecomunicazioni, la crittografia ha assunto
rilievo ed interesse crescenti nelle
infrastrutture di sicurezza
14
15Crittografia ? 3
- Se il sistema di cifra, o cifrario, è ben
congegnato, loperazione di decifrazione o
decifratura deve risultare semplice al legittimo
proprietario (o al destinatario del messaggio),
ma di complessità proibitiva alla spia - ? possibile in quanto gli utenti legittimi
possiedono uninformazione che deve rimanere
inaccessibile alla spia, la chiave del cifrario - Occorre notare la distinzione tra decifrazione e
decrittazione, loperazione illegittima in cui
non ci si può avvalere della chiave
15
16Crittografia ? 4
/ Dato un carattere, ne fornisce un valore
codificato / ?define ILLEGAL_VAL ?1 char
encode(ch) char ch static unsigned char
encoder128 ? 127,124,121,118,115,112,
109,106,103,100,97,94,91,88,85,82,79,76,73,70,67,6
4,61, 58,55,52,49,46,43,40,37,34,31,28,25,22,
19,16,13,10,7,4, 1,126,123,120,117,114,111,10
8,105,102,99,96,93,90,87,84,
81,78,75,72,69,66,63,60,57,54,51,48,45,42,39,36,33
,30, 27,24,21,18,15,12,9,6,3,0,125,122,119,11
6,113,110,107, 104,101,98,95,92,89,86,83,80,7
7,74,71,68,65,62,59,56,53,
50,47,44,41,38,35,32,29,26,23,20,17,14,11,8,5,2
/ Controlla la presenza di caratteri
illeciti / if (ch gt 127)
return ILLEGAL_VAL else return
encoderch / Fornisce il carattere codificato
/
480 ? 111o
16
17Crittografia ? 5
- Il codice Shift Cypher con K?3 era utilizzato da
Giulio Cesare - Esercizio Con K?11, si somma 11 al valore
corrispondente alla lettera e, nel caso che la
somma superi 25, si divide il numero per 26 e si
considera il resto della divisione intera - we will meet at midnight
- 22 4 22 8 11 11 12 4 4 19 0 19 12 8 3 13 8 6 7
19 - ?
- 7 15 7 19 22 22 23 15 15 4 11 4 23 19 14 24 19 17
18 4 - hphtwwxppelextoytrse
17
18Esempio ? 1
/ Dato un vettore, stabilisce se vi sono
almeno due elementi uguali tra loro / define
MAX_DIM 256 typedef intMAX_DIM VECTOR int
TwinSearch (v) / ricerca degli elementi gemelli
/ VECTOR v int c ? 0 int k ? 0
int found ? ?1 / ricerca senza successo ritorna
?1 / for(c ? 0 ((c lt (MAX_DIM?1))
(found ?? ?1)) c??) for(k ? (c?1)
((k lt MAX_DIM) (found ?? ?1)) k??)
if (vc ?? vk)
found ? 1 / ricerca con successo /
return found
18
19Esempio ? 2
/ Inverte gli elementi di un vettore
/ include ltstdio.hgt int main()
/dichiarazioni/ int a10, b10 int i,
dim?10 /input elementi/
for(i?0iltdimi??) printf(inserire
lelemento ad ,i) scanf(d, ai)
/stampa vettore/ printf(\nIl
vettore è\n\n) for(i?0iltdimi??)
printf(ad ? d\n, i, ai) printf(\n)
/inversione vettore/ for(i?0iltdimi??)
bi?adim?1?i /stampa vettore
invertito/ printf(Il vettore invertito
è\n\n) for(i?0iltdimi??)
printf(bd ? d\n, i, bi) return 0
19
20Laritmetica dei puntatori ? 1
- Il C permette lutilizzo degli operatori additivi
in concomitanza con i puntatori - Se p è un puntatore, lespressione p?3 è lecita
ed individua il terzo oggetto che segue quello
puntato da p - Poiché p contiene un indirizzo, operazioni
aritmetiche su p forniscono nuovi indirizzi - Il compilatore non opera semplicemente una somma
tra 3 e p, ma moltiplica 3 per la dimensione
delloggetto puntato da p effettua cioè uno
scaling - Esempio Se lindirizzo contenuto in p è 1000 e p
è un puntatore a long int, allora p?3 identifica
lindirizzo 1018 (8 byte per gli interi lunghi)
se p è un puntatore a char, p?3 rappresenta
lindirizzo 1003
20
21Laritmetica dei puntatori ? 2
- Nellipotesi di puntatori che si riferiscono allo
stesso tipo di dato, è lecito sottrarre il valore
di un puntatore da un altro loperazione
fornisce un valore intero che rappresenta il
numero di oggetti compresi fra i due puntatori - Se il primo puntatore è relativo a un indirizzo
inferiore al secondo, il risultato è un intero
negativo - È lecito anche sottrarre un valore intero da un
puntatore il risultato è un puntatore
21
22 Laritmetica dei puntatori ? 3
long p1, p2, k int j char p3
p1?k p2?p1? 4 / OK / j?p2?p1 / OK a j
viene assegnato 4 / j?p1?p2 / OK a j viene
assegnato ?4 / p1?p2?2 / OK tipi dei
puntatori compatibili / p3?p1?1 / NO tipi
diversi di puntatori / j?p1?p3 / NO tipi
diversi di puntatori /
22
23Laritmetica dei puntatori ? 4
- Il linguaggio C prevede la definizione di
puntatori nulli, ovvero di puntatori che non
puntano ad alcun oggetto valido - Un puntatore nullo è un qualsiasi puntatore a cui
sia assegnato il valore zero - char p
- p?0 / rende p un puntatore nullo /
- In questo caso il compilatore non effettua la
conversione esplicita dellespressione intera nel
tipo del puntatore - La definizione del puntatore nullo è utile
allinterno di istruzioni di controllo il
puntatore nullo è lunico puntatore cui è
associato il valore FALSE tutti i puntatori
validi valgono TRUE
23
24Il passaggio di puntatori come argomenti di
funzione ? 1
- Il compilatore segnala i tentativi di utilizzo
congiunto di puntatori di tipi diversi - Uneccezione alla regola è costituita dalluso di
puntatori come argomenti di funzione in mancanza
di un prototipo, il compilatore non effettua
controlli per verificare la corrispondenza di
tipo fra parametro attuale e parametro formale - ? si possono produrre risultati inconsistenti
nel caso di parametri di tipo disomogeneo - Il prototipo di una funzione è una dichiarazione
di funzione antecedente alla sua definizione
permette al compilatore di compiere il controllo
sui tipi degli argomenti che vengono passati alla
funzione
24
25Il passaggio di puntatori come argomenti di
funzione ? 2
s0?1 s1?2 s2?3
?include ltstdio.hgt ?include ltstdlib.hgt void
clr(p) int p p ? 0 / Memorizza 0 alla
locazione p / main() static short s3 ?
1,2,3 clr(s1) / Azzera lelemento 1
di s / printf(s0?d\ns1?d\ns2?d\n,
s0,s1,s2) exit(0)
p è un puntatore a int ? vengono azzerati 4 byte,
quindi sia s1 che s2
s0?1 s1?0 s2?0
25
26Laccesso agli elementi di array mediante
puntatori ? 1
- È possibile accedere agli elementi di un array
attraverso - luso del nome dellarray con il relativo indice
- luso dei puntatori
- Infatti vale la regola che
- Aggiungere un intero ad un puntatore allinizio
di un array, ed accedere allindirizzo puntato
dallespressione, equivale ad utilizzare lintero
come indice dellarray - Inoltre, un nome di array non seguito da un
indice viene interpretato come un puntatore
allelemento iniziale dellarray
Se p?ar0 ? (p?e) è equivalente a are
ar è equivalente a ar0
26
27Laccesso agli elementi di array mediante
puntatori ? 2
- Combinando le due relazioni, si ottiene la regola
generale - Un nome di array viene trasformato dal
compilatore C in un puntatore allelemento
iniziale dellarray e quindi gli indici vengono
interpretati come spostamenti dalla posizione di
indirizzo base - In considerazione del meccanismo di scaling, lo
spostamento determina il numero di elementi da
oltrepassare - Esempio
arn equivale a (ar?n)
Sono equivalenti in entrambi i casi, ar è un
puntatore allelemento iniziale dellarray e 2 è
un fattore di spostamento che richiede al
compilatore di aggiungere due al valore del
puntatore
ar2 (ar?2)
27
28Laccesso agli elementi di array mediante
puntatori ? 3
- Tuttavia
- i valori delle variabili puntatore possono
essere modificati - i nomi di array non sono variabili, ma
riferimenti a indirizzi delle variabili array e,
come tali, non possono essere modificati - Un nome di array non associato ad un indice o ad
un operatore accesso allindirizzo di () non
può apparire alla sinistra di un operatore di
assegnamento
float ar7, p p?ar / OK equivale a
p?ar0 / ar?p / NO assegnamento su un
indirizzo di array / p?ar / NO assegnamento
su un indirizzo di puntatore / ar?? / NO
non è possibile incrementare un indirizzo di
array / ar1?(p?5) / OK ar1 è una
variabile / p?? / OK è possibile
incrementare una variabile puntatore /
28
29Il passaggio di array come argomenti di funzione
? 1
- In C, un nome di array, utilizzato come argomento
di funzione, viene interpretato come indirizzo
del primo elemento dellarray - Esempio
- Nella funzione chiamata è necessario dichiarare
largomento come un puntatore allelemento
iniziale di un array
main() extern float func() float x static
float farray5 x ? func(farray) /
equivalente a func(farray0) /
29
30Il passaggio di array come argomenti di funzione
? 2
- Anche nel secondo caso, ciò che viene passato è
un puntatore al primo elemento dellarray ed il
compilatore è in grado di convertire
automaticamente ar in un puntatore a float - In termini di leggibilità, la seconda versione è
preferibile, poiché evidenzia che loggetto
passato è lindirizzo di base di un array e non
un generico puntatore a una variabile float
(scalare o composta?) - La dichiarazione della dimensione dellarray
nella definizione dellargomento è comunque
corretta il compilatore può usare linformazione
sulla dimensione per effettuare controlli sui
valori limite
30
31Il passaggio di array come argomenti di funzione
? 3
- Non è possibile ottenere la dimensione di un
array allinterno di una funzione cui viene
passato come argomento, ma solo laddove larray è
effettivamente dichiarato
?include ltstdio.hgt ?include ltstdlib.hgt void
print_size(arg) float arg printf(La
dimensione di arg è d\n,sizeof(arg)) main()
void print_size() static float
f_array10 printf(La dimensione di f_array
è d\n,sizeof(f_array)) print_size(f_array)
exit(0)
Sulla macchina di riferimento, lesecuzione del
programma fornisce
La dimensione di f_array è 40 La dimensione di
arg è 4
31
32Uscita dal limite superiore di un array
- Il compilatore, di solito, non controlla che
laccesso agli elementi di un array venga
effettuato rispettandone i limiti dimensionali - ? È possibile accedere per errore ad elementi
per i quali non è stata allocata memoria (aree
di memoria riservate ad altre variabili,
riservate ad altri processi, etc.) - Esempio
Essendo ar un array di 10 elementi, quelli cui è
possibile accedere in modo corretto hanno indice
da 0 a 9 il ciclo for contiene un errore
off?by?one Probabilmente verrebbe azzerata la
variabile j ? il ciclo diventa infinito
main() int ar10, j for(j?0 jlt?10
j??) arj ? 0
32
33Gli algoritmi di ordinamento ? 1
- Lordinamento di una sequenza di informazioni
consiste nel disporre le stesse informazioni in
modo da rispettare una qualche relazione
dordine ad esempio, una relazione dordine
minore o uguale dispone le informazioni in modo
non decrescente - Lordinamento è unoperazione molto importante
perché permette di ridurre notevolmente i tempi
di ricerca di uninformazione, nellambito di una
sequenza di informazioni - Nel caso in cui tale sequenza risulta ordinata,
secondo una qualche relazione dordine, è infatti
possibile sfruttare la stessa relazione dordine
per effettuare la ricerca
33
34Gli algoritmi di ordinamento ? 2
- Esistono due categorie di algoritmi di
ordinamento la classificazione è fatta in base
alla complessità di calcolo e alla semplicità
algoritmica - La complessità di calcolo si riferisce al numero
di operazioni necessarie allordinamento tali
operazioni sono essenzialmente confronti e scambi
tra gli elementi dellinsieme da ordinare - La semplicità algoritmica si riferisce alla
lunghezza e alla comprensibilità del codice
34
35Gli algoritmi di ordinamento ? 3
- Algoritmi semplici di ordinamento
- Algoritmi che presentano complessità O(n2), dove
n è il numero di informazioni da ordinare sono
caratterizzati da poche e semplici istruzioni,
dunque si realizzano con poche linee di codice - Algoritmi evoluti di ordinamento
- Algoritmi che presentano complessità
computazionale O(n?log2n) sono più complessi,
fanno spesso uso di ricorsione la convenienza
del loro utilizzo si rileva quando il numero n di
informazioni da ordinare è molto elevato
35
36Bubblesort ? 1
- La strategia Bubblesort (ordinamento a bolla)
prevede il confronto dei primi due elementi di un
array, e lo scambio, se il primo è maggiore del
secondo - Dopo il primo confronto, si effettua un confronto
fra il secondo ed il terzo elemento (con
eventuale scambio), fra il terzo ed il quarto,
etc. - Gli elementi pesanti (grandi) tendono a
scendere verso il fondo del vettore, mentre
quelli leggeri (più piccoli) salgono (come
bolle) in superficie
36
37Bubblesort ? 2
- Il confronto fra tutte le coppie di elementi
adiacenti viene detto passaggio - Se, durante il primo passaggio, è stato
effettuato almeno uno scambio, occorre procedere
ad un ulteriore passaggio - Ad ogni passaggio, almeno un elemento assume la
sua posizione definitiva (lelemento più grande
del sottoinsieme attualmente disordinato) - Devono essere effettuati al più n?1 passaggi
- Al k?esimo passaggio vengono effettuati n?k
confronti (con eventuali scambi) almeno k?1
elementi sono già ordinati - Complessivamente, vengono effettuati n?(n?1)/2
confronti - ? La complessità computazionale del Bubblesort è
O(n2)
37
38Bubblesort ? 3
?define FALSE 0 ?define TRUE 1 ?include
ltstdio.hgt void bubble_sort(list, list_size) int
list, list_size int j, temp,
sorted?FALSE while(!sorted)
sorted ? TRUE / assume che list sia ordinato
/ for(j?0 jltlist_size?1 j??)
if(listjgtlistj?1)
/ almeno un elemento non è in ordine /
sorted ? FALSE
temp ? listj listj ?
listj?1 listj?1 ? temp
/ fine del ciclo for
/ / fine del ciclo while /
Nota Nel caso migliore, quando il vettore è già
ordinato, si effettua un solo passaggio, con n?1
confronti e nessuno scambio ? La complessità
scende a O(n)
38
39Le stringhe
39
40Definizione
- Una stringa è un array di caratteri terminato dal
carattere nullo, corrispondente alla sequenza di
escape \0 (con valore numerico associato zero) - Una stringa costante (o letterale) è una serie di
caratteri racchiusi fra doppi apici tale stringa
è di tipo array di caratteri, con ogni carattere
che occupa un byte - Ad ogni stringa viene aggiunto automaticamente
dal compilatore un carattere nullo, ad indicarne
la fine
40
41Dichiarazione e inizializzazione ? 1
- Per memorizzare una stringa occorre dichiarare un
array di char, che può essere inizializzato con
una stringa costante - static char str?testo
- Larray ha dimensione maggiore di uno rispetto
alla lunghezza della stringa, per consentire la
memorizzazione del carattere nullo di
terminazione (str ha lunghezza 6 byte) - Il compilatore segnala un errore se si dichiara
la lunghezza della stringa n, e si inizializza
con una stringa costante di lunghezza gtn - static char str3?quattro / SCORRETTO /
- static char str13?tre / CORRETTO /
- I compilatori ANSI, generalmente, consentono di
specificare una dimensione di array che non
includa il carattere terminatore
41
42Dichiarazione e inizializzazione ? 2
- È possibile inizializzare un puntatore a char con
una stringa costante - char ptr altro testo
- si crea un array di caratteri, inizializzato ad
altro testo, ri-servando però memoria anche per
il puntatore - Nel caso dellarray, tutti i successivi accessi
utilizzano il nome dellarray come riferimento
per lindirizzo dellelemento iniziale
dellarray tale indirizzo non può essere
modificato - Il puntatore è una variabile e può essere
modificato lindirizzo relativo alla prima
inizializzazione viene perso
ptr
1006
2000
42
43Gli assegnamenti a stringhe
- Un puntatore a char può essere inizializzato con
una stringa costante, perché una stringa è un
array di char - Una stringa costante viene interpretata come un
puntatore al primo carattere della stringa
?include ltstdlib.hgt main() char
array10 char ptr1 ? 10 spazi char
ptr2 array ? not OK / non è possibile
assegnare un indirizzo / array5 ? A
/ OK / (ptr1?5) ? B / OK / ptr1
? OK ptr15 ? C / opinabile a causa
dellassegnamento precedente / ptr2 ? not
OK/ conflitto di tipi / ptr2 ? OK
/ opinabile perché non cè inizializzazione /
exit(0)
43
44Stringhe e caratteri ? 1
- Occorre notare la differenza fra stringhe
costanti e costanti di tipo carattere - È possibile assegnare una costante carattere
allindirizzo contenuto in un puntatore a char è
invece scorretto effettuare la stessa operazione
relativamente ad una stringa
char ch ? a / Per a è riservato un byte /
/ Vengono riservati due byte per a, oltre
allo spazio necessario alla memorizzazione di
ps / char ps ? a
char p2 p2 ? a / not OK / p2 ? a / OK
/
char p1 p1 ? a / OK / p1 ? a / not
OK /
Le stringhe sono interpretate come puntatori a
carattere
44
45Stringhe e caratteri ? 2
- Le inizializzazioni e gli assegnamenti non sono
simmetrici è infatti possibile scrivere - char p ? string
- ma non
- p ? string
- Nota vale per inizializzazioni ed assegnamenti
di tutti i tipi di dati - float f
- float pf ? f /OK /
- pf ? f / SCORRETTO /
Puntatore a carattere
Carattere
Puntatore a float
Float
45
46Lettura e scrittura di stringhe ? 1
- Le stringhe possono essere lette e scritte
utilizzando le funzioni scanf() e printf(), con
lo specificatore di formato s - Largomento della funzione scanf() deve essere un
puntatore ad un array di caratteri di dimensioni
sufficienti a contenere la stringa in ingresso,
che si intende terminata da un qualsiasi
carattere di spaziatura - La funzione scanf(), dopo aver letto il dato in
ingresso, aggiunge automaticamente il carattere
\0 in fondo alla stringa - Largomento della funzione printf() deve essere
un puntatore ad un array di caratteri terminato
dal carattere nullo (che non viene stampato)
46
47Lettura e scrittura di stringhe ? 2
- Esempio Scrivere un programma che legge una
stringa dalla periferica dingresso di default e
la stampa dieci volte
?include ltstdio.hgt ?include ltstdlib.hgt ?define
MAX_CHAR 80 main() char strMAX_CHAR
int i printf(Introdurre una stringa)
scanf(s, str) for (i?0 ilt10 i??)
printf(s\n, str) exit(0)
È possibile utilizzare il nome dellarray come
argomento per le funzioni di I/O, in quanto
puntatore allinizio dellarray
47
48Le funzioni di libreria per le stringhe strlen()
- La funzione strlen(), restituisce il numero di
caratteri che compongono una stringa (escluso il
carattere nullo)
- Poiché nellespressione str?? i due operatori
hanno la stessa precedenza ed associatività
de-stra, lespressione viene analiz-zata dal
compilatore nel modo seguente - Valutazione delloperatore di incre-mento
postfisso il compilatore passa str alloperatore
successivo e lo incrementa solo al termine della
valutazione dellespressione
int strlen(str) char str int i for
(i?0 str?? i??) / istruzione vuota
/ return i
- Valutazione delloperatore , applicato a str
- Completamento dellespressione, con lincremento
di str
48
49Le funzioni di libreria per le stringhe strcpy()
- La funzione strcpy() copia una stringa in unaltra
- Il risultato dellassegnamento costituisce la
condizione di test per il ciclo while - Se s2 vale zero (per il carattere di
terminazione), si ha luscita dal ciclo
void strcpy(s1, s2) char s1, s2
while(s2?? ? s1??) /istruzione vuota /
- Loperatore di incremento postfisso è
obbligatorio un incremento prefisso non
produrrebbe un risultato corretto, dato che il
primo elemento non verrebbe copiato
49
50Le funzioni di libreria per le stringhe strstr()?
1
- La funzione strstr() effettua la ricerca di una
sottostringa allinterno di una stringa,
operazione detta comunemente pattern matching - La funzione prevede come argomenti due puntatori
a stringhe di caratteri ed effettua la ricerca di
unoccorrenza della seconda stringa nella prima - se esiste unoccorrenza, viene restituita la
posizione dinizio nellarray - altrimenti, viene restituito ?1
- Nota la maggior parte delle funzioni della
libreria di run?time restituisce 0 o ?1, come
valore di errore (per strstr(), 0 corrisponde
alloccorrenza della seconda stringa allinizio
della prima)
50
51Le funzioni di libreria per le stringhe strstr()?
2
/ Restituisce la posizione di str2 in str1
restituisce ?1 se non esiste occorrenza / int
strstr(str1, str2) char str1, str2
char p, q, substr / Itera su ogni
carattere di str1 / for(substr?str1
substr substr??) p ? substr
q ? str2 / Controlla se loccorrenza
di str2 corrisponde alla posizione corrente /
while(q) if(q?? !? p??)
goto no_match / serve per
uscire dal while, ma restare nel for / /
Si giunge qui solo se si è trovata unoccorrenza
di str2 / return substr?str1 /
Si giunge qui se non è stata riscontrata
unoccorrenza di str2 (nel ciclo while) /
no_match / Si giunge qui se
non vi sono occorrenze di str2 in str1 /
return ?1
51
52Le funzioni di libreria in string.h
strcpy() Copia una stringa in un array
strncpy() Copia una parte di una stringa in un array
strcat() Concatena due stringhe
strncat() Concatena parte di una stringa ad unaltra
strcmp() Confronta due stringhe
strncmp() Confronta due stringhe per una lunghezza data
strchr() Cerca la prima occorrenza di un carattere specificato in una stringa
strcoll() Confronta due stringhe sulla base di una sequenza di confronto definita
strcspn() Calcola la lunghezza di una stringa che non contiene i caratteri specificati
strerror() Fa corrispondere ad un numero di errore un messaggio di errore testuale
strlen() Calcola la lunghezza di una stringa
strpbrk() Cerca la prima occorrenza di uno tra i caratteri specificati allinterno di una stringa
strrchr() Cerca lultima occorrenza di un carattere in una stringa
strspn() Calcola la lunghezza di una stringa che contenga caratteri specificati
strstr() Cerca la prima occorrenza di una stringa in unaltra
strtok() Divide una stringa in una sequenza di simboli
strxfrm() Trasforma una stringa in modo che sia utilizzabile come argomento per strcmp()
52
53Esempio Calcolo delletà
/ Esempio di conversione da stringa ad intero
/ ?include ltstdio.hgt ?include
ltstdlib.hgt main() char anno_nascita5,
anno_corrente5 int anni
printf(Inserire lanno di nascita )
scanf(s, anno_nascita) printf(Inserire
lanno corrente ) scanf(s,
anno_corrente) / atoi() converte una
stringa in un intero / anni ?
atoi(anno_corrente) ? atoi(anno_nascita)
printf(Età d\n, anni) exit(0)
53
54Esempio Parole nella stringa
/ Conta il numero di parole in una stringa
/ ?include ltctype.hgt int word_count(s) char
s int count?0 while(s !?\0)
while(isspace(s)) / salta
la spaziatura / ??s
if(s !?\0) / trovata una parola /
??count
while(!isspace(s) s !?\0)
??s / salta la parola /
return count
54
55Esempio Parole palindrome
/ Letta in input una stringa, verifica se è
palindroma / ?include ltstdio.hgt ?include
ltstdlib.hgt ?include ltstring.hgt main()
char parola32, i?0, n printf(Inserisci
una parola (lunga al max 31 caratteri) )
scanf(s, parola) n ? strlen(parola)
while((i ?? n/2) (parolai ? ?
parolan?1?i)) i?? if(i ? n/2)
printf(La parola s è palindroma.\n, parola)
else printf(La parola s non è
palindroma.\n, parola) exit(0)
55
56Esempio Da minuscole a maiuscole
/ Letta una stringa alfabetica, la riscrive
con solo lettere maiuscole/ ?include
ltstdlib.hgt ?include ltstdio.hgt ?include
ltstring.hgt main() char s100,
t100 int i
printf(Inserisci una stringa )
scanf(s, s) for (i?0 i?strlen(s)
i??) if (si ?? 97
si ?? 122) ti ? si ?
32 else ti ?
si printf(Stringa
maiuscola s\n, t) exit(0)
56