Your SlideShare is downloading. ×
0
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
6   Vettori E Matrici
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

6 Vettori E Matrici

1,336

Published on

Published in: Technology, Business
1 Comment
0 Likes
Statistics
Notes
  • Be the first to like this

No Downloads
Views
Total Views
1,336
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
78
Comments
1
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. INFORMATICA Tipi strutturati
  • 2. Tipi strutturati <ul><li>I tipi considerati finora hanno la caratteristica comune di non essere strutturati: ogni elemento è una singola entità. </li></ul><ul><li>Se il programma deve trattare collezioni di dati, anche se sono dello stesso tipo, a ognuno deve essere associato un identificatore. </li></ul><ul><li>Supponendo di dover gestire le paghe in una ditta di 3000 dipendenti sarebbe necessario definire 3000 variabili diverse, del tipo: operaio1 , operaio2 , ...., impiegato1 , impiegato2 , ....., ecc. </li></ul>
  • 3. Tipi strutturati <ul><li>I linguaggi ad alto livello permettono di ovviare a questo inconveniente con i tipi strutturati, caratterizzati sia dal tipo dei loro componenti che dai legami strutturali tra i componenti stessi, cioè dal metodo di strutturazione. </li></ul><ul><li>Il linguaggio C, anche in questo caso, si presenta ambivalente: permette di creare dati aggregati, senza peraltro che questi costituiscano dei tipi nell'accezione classica. </li></ul><ul><li>Infatti l'organizzazione strutturale dei dati e le modalità di accesso ai singoli elementi che costituiscono la struttura non vengono nascoste all'utente, che invece può interagire con esse in piena libertà. </li></ul>
  • 4. Vettori <ul><li>Il vettore è una collezione di variabili tutte dello stesso tipo (detto appunto tipo base ) di lunghezza prefissata . </li></ul><ul><li>Questa collezione di variabili è individuata da un unico nome , il nome appunto del vettore. </li></ul><ul><li>Ogni elemento del vettore è detto componente ed è individuato dal nome del vettore seguito da un indice posto tra parentesi quadre, così: </li></ul><ul><li>nome[indice] </li></ul><ul><li>L' indice può essere solo di tipo intero o enumerato e determina la posizione dell'elemento nel vettore. </li></ul>
  • 5. Vettori <ul><li>L'intervallo dei valori assunti dall' indice determina la dimensione del vettore, che deve essere limitata . </li></ul><ul><li>Definizione generale di vettore : </li></ul><ul><li>tipo_componente nome_vettore [numero_componenti]; </li></ul><ul><li>tipo_componente può essere un qualunque tipo semplice, </li></ul><ul><li>nome_vettore è il nome da attribuire al vettore, </li></ul><ul><li>numero_componenti , racchiuso tra parentesi quadre , è il numero di elementi che costituiscono il vettore e pertanto deve essere un intero o un'espressione costante di tipo intero. </li></ul>
  • 6. Vettori <ul><li>L' indice del vettore può assumere valori compresi tra 0 e numero_componenti – 1 . </li></ul><ul><li>L' indice corrisponde pertanto alla posizione nel vettore dell’elemento a cui è associato, rispetto al primo. </li></ul><ul><li>Gli elementi del vettore sono memorizzati in celle di memoria contigue (successive)! </li></ul>Vettore a (di 5 elementi): a[0] a[1] a[2] a[3] a[4]
  • 7. Vettori <ul><li>Esempi di definizioni di vettore: </li></ul><ul><li>#define NUM_MATERIE 20 </li></ul><ul><li>char s[8]; </li></ul><ul><li>double giornate[167]; </li></ul><ul><li>int voti_ottenuti[NUM_MATERIE]; </li></ul><ul><li>La variabile s è un vettore di 8 elementi: equivale alle 8 variabili di tipo char: s[0] , s[1] , s[2] , s[3] , s[4] , s[5] , s[6] , s[7] . </li></ul><ul><li>La variabile giornate è un vettore di 167 elementi di tipo double il cui indice può variare tra 0 e 166 . </li></ul><ul><li>La variabile voti_ottenuti è un vettore di 20 elementi di tipo intero il cui indice può variare tra 0 e 19 . </li></ul>
  • 8. Inizializzazione di un vettore <ul><li>E’ possibile assegnare un valore iniziale ad un vettore al momento della sua definizione. </li></ul><ul><li>L’operazione consiste nell’indicare i valori degli elementi del vettore separati tra loro da virgola. </li></ul><ul><li>Sintassi (per un vettore di N elementi): </li></ul><ul><li>= {<valore_0>, <valore_1>, ..., ,<valore_N-1>}; </li></ul><ul><li>Esempio: </li></ul><ul><ul><li>int lista[4] = { 2, 0, -1, 5 }; </li></ul></ul>
  • 9. Inizializzazione di un vettore <ul><li>NOTA: se vengono specificati meno di N elementi, l’inizializzazione comincia comunque a partire dal primo valore e lascia non assegnati i rimanenti. </li></ul><ul><li>Esempi: </li></ul><ul><li>int s[4] = {2, 0, -1}; /* s[0]=2, s[1]=0, s[2]=-1, s[3]=? */ </li></ul><ul><li>char p[5] = {‘a’, ‘b’, ‘c’}; </li></ul><ul><li>/* p[0]=‘a’, p[1]=‘b’, p[2]=‘c’, p[3]=? , p[4]=? */ </li></ul><ul><li>double d[2] = {2.56}; /* d[0]=2.56, d[1]=? */ </li></ul>
  • 10. Vettori e indici <ul><li>L’indice, che definisce la posizione di un elemento di un vettore, DEVE essere rigorosamente un intero! </li></ul><ul><li>Può ovviamente anche essere un’espressione, più o meno complessa, purché con risultato intero. </li></ul><ul><li>Esempio: </li></ul><ul><ul><li>double x, a[30]; /* a vettore di double */ </li></ul></ul><ul><ul><li>int i, j, k; </li></ul></ul><ul><ul><li>............. </li></ul></ul><ul><ul><li>x = a[2*i+j-k]; /* espressione aritmetica per l’indice */ </li></ul></ul>
  • 11. Vettori e cicli <ul><li>I cicli sono particolarmente utili per “scandire” un vettore. </li></ul><ul><li>Utilizzo tipico: applicazione iterativa di un’operazione sugli elementi di un vettore. </li></ul><ul><li>Schema: </li></ul><ul><ul><li>int data[10], ind; </li></ul></ul><ul><ul><li>............. </li></ul></ul><ul><ul><li>for (ind=0; ind<10; ind++) </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>elaborazione dell’elemento data[ind] </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>Ad ogni ciclo è interessato l’elemento individuato dall’indice ind . </li></ul>
  • 12. <ul><li>Se invece si deve ricercare un particolare elemento di un vettore è il while che si presta più opportunamente alla necessità: </li></ul><ul><ul><li>#define FALSO 0 /* “creazione” del tipo logico mancante in C */ </li></ul></ul><ul><ul><li>#define VERO 1 </li></ul></ul><ul><ul><li>………… .. </li></ul></ul><ul><ul><li>int vett[1000], ind, numero; </li></ul></ul><ul><ul><li>short int trovato; </li></ul></ul><ul><ul><li>............. </li></ul></ul><ul><ul><li>ind = 0; /* devo gestire io l’indice! */ </li></ul></ul><ul><ul><li>trovato = FALSO; /* flag associato al ritrovamento dell’elemento */ </li></ul></ul><ul><ul><li>while ( !trovato && (ind < 1000)) </li></ul></ul><ul><ul><li>/* condizione di fine ciclo: o l’ho trovato o sono giunto a fine vettore */ </li></ul></ul><ul><ul><li>{ </li></ul></ul><ul><ul><ul><li>if (vett[ind] == numero) </li></ul></ul></ul><ul><ul><ul><li>trovato = VERO; </li></ul></ul></ul><ul><ul><ul><li>…………… /* trovato l’elemento: elaborazioni del caso */ </li></ul></ul></ul><ul><ul><ul><li>else </li></ul></ul></ul><ul><ul><ul><li>ind++; /* non è questo elemento: aggiorna l’indice */ </li></ul></ul></ul><ul><ul><li>} </li></ul></ul>Vettori e cicli
  • 13. Vettori <ul><li>Non ci sono operatori che agiscono sul vettore nel suo complesso: non è lecito pertanto l'assegnamento di un vettore ad un altro vettore. </li></ul><ul><li>Se vett_x e vett_y sono vettori, l'istruzione: </li></ul><ul><li>vett_x = vett_y; </li></ul><ul><li>è errata anche se vett_x e vett_y sono dello stesso tipo. </li></ul><ul><li>  </li></ul><ul><li>Per trasferire un vettore in un altro occorre copiare un elemento per volta. </li></ul>
  • 14. Vettori <ul><li>Esempio: copia il vettore vett_iniz nel vettore vett_fin </li></ul><ul><li>#include <stdio.h> </li></ul><ul><li>#define NUMDATI 5 </li></ul><ul><li>int vett_iniz[NUMDATI] = {11, -2, -63, 4, 15}; </li></ul><ul><li>int vett_fin[NUMDATI], indice; </li></ul><ul><li>  </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>for (indice = 0; indice < NUMDATI; indice++) </li></ul><ul><li>vett_fin[indice] = vett_iniz[indice]; </li></ul><ul><li>} </li></ul>
  • 15. Vettori <ul><li>Sugli elementi del vettore agiscono gli operatori previsti per il tipo_componente . Pertanto è lecito scrivere: </li></ul><ul><li>valor_fin = vett_x[m1] + vett_y[m2]; </li></ul><ul><li>purché, naturalmente, valor_fin , il vettore vett_x e il vettore vett_y siano tutti dello stesso tipo. </li></ul><ul><li>Il tempo necessario per accedere a un elemento di un vettore è indipendente dal valore dell'indice: il vettore è pertanto una </li></ul><ul><li>struttura ad accesso casuale </li></ul>
  • 16. Esempio <ul><li>Leggere 10 valori da tastiera e memorizzarli in un vettore; quindi calcolarne il minimo ed il massimo. </li></ul><ul><li>Pseudocodice: </li></ul><ul><ul><li>Con un indice ind che varia tra 0 e 9: </li></ul></ul><ul><ul><ul><li>legge un dato e lo salva in vettdati[ind] ; </li></ul></ul></ul><ul><ul><li>Inizializzo la variabile massimo e la variabile minimo col primo elemento del vettore vettdati[0] ; </li></ul></ul><ul><ul><li>Con un indice ind che varia tra 1 e 9: </li></ul></ul><ul><ul><ul><li>se vettdati[ind] è più grande di massimo : </li></ul></ul></ul><ul><ul><ul><li>massimo vettdati[ind] ; </li></ul></ul></ul><ul><ul><ul><li>altrimenti se vettdati[ind] è più piccolo di minimo : </li></ul></ul></ul><ul><ul><li>minimo vettdati[ind] ; </li></ul></ul><ul><ul><li>Visualizza massimo e minimo </li></ul></ul>
  • 17. Esempio <ul><li>#include <stdio.h> </li></ul><ul><li>#define NUMDATI 10 </li></ul><ul><li>  </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>int minimo, massimo, ind; </li></ul><ul><li>int vettdati[NUMDATI]; </li></ul><ul><li>/* lettura dei dati */ </li></ul><ul><li>for (ind = 0; ind < NUMDATI; ind++) </li></ul><ul><li>{ </li></ul><ul><li>printf (&quot; Introduci vettdati[%d]: &quot;, ind); </li></ul><ul><li>scanf (&quot;%d&quot;, &vettdati[ind]); </li></ul><ul><li>} </li></ul>
  • 18. Esempio <ul><li>/* cerca il massimo e il minimo */ </li></ul><ul><li>massimo = vettdati[0]; </li></ul><ul><li>minimo = vettdati[0]; </li></ul><ul><li>for (ind = 1; ind < NUMDATI; ind++) </li></ul><ul><li>{ </li></ul><ul><li>if (vettdati[ind] > massimo) </li></ul><ul><li>massimo = vettdati[ind]; </li></ul><ul><li>else </li></ul><ul><li>{ </li></ul><ul><li>if (vettdati[ind] < minimo) </li></ul><ul><li>minimo = vettdati[ind]; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>printf (“ Il massimo è %d e il minimo è %d &quot;, massimo, minimo); </li></ul><ul><li>} </li></ul>
  • 19. Esempio <ul><li>Scrivere un programma che legga un numero decimale positivo minore di 1024 e lo converta nella corrispondente codifica binaria. </li></ul><ul><li>Analisi </li></ul><ul><ul><li>Per convertire in binario puro un numero decimale occorre eseguire una sequenza di divisioni per 2 prendendo i resti (0 oppure 1): occorre dunque un vettore per memorizzare questi resti. </li></ul></ul><ul><ul><li>Poiché i numeri devono essere compresi tra 0 e 1023 sono sufficienti 10 bit: il nostro vettore sarà pertanto lungo 10 elementi e in ogni elemento memorizzeremo una cifra. </li></ul></ul>
  • 20. Esempio <ul><ul><li>Analisi (continua): </li></ul></ul><ul><ul><li>I resti ottenuti dalle divisioni per 2 vanno però letti al contrario, conviene pertanto riempire il vettore a partire dall’ultimo elemento. </li></ul></ul><ul><ul><li>Per eseguire le divisioni per due è intuitivo che conviene servirsi di un ciclo il quale, ad ogni iterazione, calcola un nuovo bit (resto della divisione per 2). </li></ul></ul><ul><ul><li>for o while ? È pressochè indifferente usare un ciclo for o un ciclo while : occorre però che le inizializzazioni delle variabili siano adattate al ciclo prescelto. </li></ul></ul><ul><ul><li>Se usiamo il for avremo come “dato-guida” del ciclo l’indice del vettore; </li></ul></ul><ul><ul><li>Se usiamo il while il “dato-guida” sarà il resto delle divisioni per 2. </li></ul></ul>
  • 21. Esempio (con while) <ul><li>#include <stdio.h> </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>int ind, numero, num; </li></ul><ul><li>int binario[10]; </li></ul><ul><li>  /* inizializza il vettore risultato con tutti zeri */ </li></ul><ul><li>for (ind = 0; ind < 10; binario[ind++]=0); </li></ul><ul><li>/* equivale a : for (ind=0; ind<10; ind++) </li></ul><ul><li>binario[ind] = 0; */ </li></ul><ul><li>printf (“ Introduci un numero intero positivo minore di 1024: &quot;); </li></ul><ul><li>scanf (&quot;%d&quot;, &numero); </li></ul>
  • 22. Esempio (con while) <ul><li>if ((numero >= 0) && (numero < 1024)) </li></ul><ul><li>{ </li></ul><ul><li> num = numero; /* num è il “dato-guida” del ciclo */ </li></ul><ul><li>ind = 9; </li></ul><ul><li>while (num != 0) /* finché num è diverso da 0! */ </li></ul><ul><li>{ </li></ul><ul><li> binario[ind] = num % 2; /* calcola un nuovo bit */ </li></ul><ul><li> num /= 2; /* aggiorna num per il prossimo ciclo */ </li></ul><ul><li> ind--; /* aggiorna l’indice del vettore */ </li></ul><ul><li>} </li></ul><ul><li>printf (&quot; Conversione del numero %d: &quot;, numero); </li></ul><ul><li>for (ind=0; ind<10; ind++) /* Visualizza il vettore: */ </li></ul><ul><li>printf (&quot;%1d&quot;,binario[ind]); /* un bit per volta */ </li></ul><ul><li>} </li></ul><ul><li>else </li></ul><ul><li>printf (“ Numero non lecito!”); </li></ul><ul><li>} </li></ul>
  • 23. Esempio (con for) <ul><li>#include <stdio.h> </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>int ind, numero, num; </li></ul><ul><li>int binario[10]; </li></ul><ul><li>/* non è necessario inizializzare il vettore in quanto il ciclo for deve */ </li></ul><ul><li>/* scrivere comunque tutti gli elementi del vettore */ </li></ul><ul><li>printf (“ Introduci un numero intero positivo minore di 1024: &quot;); </li></ul><ul><li>scanf (&quot;%d&quot;, &numero); </li></ul>
  • 24. Esempio (con for) <ul><li>if ((numero >= 0) && (numero < 1024)) </li></ul><ul><li>{ </li></ul><ul><li>num = numero; </li></ul><ul><li>for (ind = 9; ind >= 0; ind--) /* con un indice che va da 9 a 0 */ </li></ul><ul><li>{ </li></ul><ul><li> binario[ind] = num % 2; /* calcola un nuovo bit */ </li></ul><ul><li> num /= 2; /* aggiorna num per il prossimo ciclo */ </li></ul><ul><li>} </li></ul><ul><li>printf (&quot; Conversione del numero %d: &quot;, numero); </li></ul><ul><li>for (ind = 0; ind < 10; ind++) /* Visualizza il vettore: */ </li></ul><ul><li>printf (&quot;%1d&quot;,binario[ind]); /* un bit per volta! */ </li></ul><ul><li>} </li></ul><ul><li>else </li></ul><ul><li>printf (“ Numero non lecito!”); </li></ul><ul><li>} </li></ul>
  • 25. Vettori <ul><li>Quando si definisce un vettore il compilatore riserva un’area di memoria sufficiente per contenerlo e associa l'indirizzo iniziale di quell'area al nome simbolico (identificatore) da noi scelto per il vettore. </li></ul><ul><li>  </li></ul><ul><li>Pertanto il nome vett_dati non è una vera e propria variabile, ma piuttosto un puntatore : in pratica vett_dati è l' indirizzo di memoria del primo elemento del vettore cioè l'indirizzo di vett_dati[0] . </li></ul><ul><li>  </li></ul><ul><li>Ecco perché è errata l'istruzione: </li></ul><ul><li>voti_ottenuti = voti_semestre; </li></ul>
  • 26. Vettori multidimensionali <ul><li>Il concetto di vettore come collezione di elementi consecutivi, può essere esteso immaginando che gli elementi siano a loro volta dei vettori: si ottiene così un vettore multidimensionale o matrice (cioè un “vettore di vettori” ). </li></ul><ul><li>La definizione di matrice ricalca pienamente quella del vettore: </li></ul><ul><li>tipo_comp nome [dim1] [dim2].........; </li></ul><ul><li>tipo_comp può essere un qualunque tipo semplice, </li></ul><ul><li>dim1 , dim2 , ecc.; racchiusi tra parentesi quadre, definiscono il numero di elementi di ogni dimensione. </li></ul>
  • 27. Vettori multidimensionali a int a[3][5]; a[0] a[1] a[2] <ul><li>Esempio: </li></ul><ul><ul><li>matrice bidimensionale di numeri interi formata da tre righe e 5 colonne: </li></ul></ul>a[0][0] a[1][0] a[2][0] a[3][0] a[4][0] a[0][1] a[1][1] a[2][1] a[3][1] a[4][1] a[0][2] a[1][2] a[2][2] a[3][2] a[4][2]
  • 28. Vettori multidimensionali <ul><li>Accesso ad un elemento: </li></ul><ul><ul><li><nome vettore> [ <posizione1> ] [ <posizione2> ]............. </li></ul></ul><ul><li>Per esempio </li></ul><ul><li>matrix [10][20][15] </li></ul><ul><li>individua l'elemento di coordinate rispettivamente 10 , 20 e 15 nella matrice a 3 dimensioni matrix . </li></ul><ul><li>Inizializzazione di un vettore multidimensionale: </li></ul><ul><ul><li>deve essere effettuata per righe! </li></ul></ul><ul><ul><ul><li>int vett[3][2] = { {8,1}, /* vett[0] */ </li></ul></ul></ul><ul><ul><ul><li> {1,9}, /* vett[1] */ </li></ul></ul></ul><ul><ul><ul><li>{0,3} /* vett[2] */ </li></ul></ul></ul><ul><ul><ul><li>}; </li></ul></ul></ul>
  • 29. Vettori multidimensionali e cicli <ul><li>Per un vettore a più dimensioni, la scansione va applicata a tutte le dimensioni: in questo caso si devono in genere utilizzare “ cicli annidati ”. </li></ul><ul><li>Esempio: elaborazione degli elementi di un vettore bidimensionale. </li></ul><ul><ul><li>int vett [3][5]; </li></ul></ul><ul><ul><li>… </li></ul></ul><ul><ul><li>for (i = 0; i < 3; i++) { /* per ogni riga */ </li></ul></ul><ul><ul><li>for (j = 0; j < 5; j++) { /* per ogni colonna */ </li></ul></ul><ul><ul><li>... elaborazione su vett[i][j] </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>} </li></ul></ul>
  • 30. Stringhe
  • 31. Vettori di caratteri: le stringhe <ul><li>Le variabili di tipo char possono contenere un solo carattere: per trattare sequenze di caratteri come nomi o, più in generale, testi il C prevede le stringhe . </li></ul><ul><li>Differentemente dagli altri tipi di dato (intero, reale, ecc.) per le stringhe non è sempre possibile fissare a priori le dimensioni: spesso si tratta di parole e la loro caratteristica peculiare è proprio la lunghezza variabile. </li></ul><ul><li>Per gestire dati di questo tipo occorrerebbe l'allocazione dinamica della memoria, in modo da riservare tutta e solo la memoria che serve. </li></ul>
  • 32. Vettori di caratteri: le stringhe <ul><li>Il C prevede per le stringhe un vettore di caratteri, il quale deve quindi avere una lunghezza massima prefissata . </li></ul><ul><li>All'interno di questo vettore, la lunghezza reale della stringa è determinata dalla presenza di un carattere delimitatore particolare, ' ', detto anche NULL . </li></ul><ul><li>Come per i tipi base, anche per le stringhe è prevista una notazione particolare per indicarne i valori: la sequenza di caratteri deve essere delimitata da una coppia di doppi apici (&quot;). </li></ul>
  • 33. Stringhe <ul><li>Esempio: </li></ul><ul><li>const char s[6] = “Ciao!”; </li></ul><ul><li>Il messaggio è lungo solo 5 caratteri, ma deve essere riservato un carattere in più per il terminatore di stringa, che deve essere sempre presente e viene forzato automaticamente dal linguaggio C. </li></ul><ul><li>  </li></ul><ul><li>Il vettore può essere definito più lungo, con gli ultimi elementi indefiniti, ma non più corto. </li></ul>s[0] s[1] s[2] s[3] s[4] s[5] ‘ C’ ‘ i’ ‘ a’ ‘ o’ ‘ !’ ‘ ’
  • 34. Stringhe <ul><li>Per la definizione di una stringa si può anche utilizzare la direttiva define : </li></ul><ul><li>#define MESSAGGIO “Ciao!”; </li></ul><ul><li>  </li></ul><ul><li>Attenzione infine a non confondere variabili di tipo carattere con stringhe: per esempio, </li></ul><ul><li>'C' rappresenta un unico carattere che è memorizzato in un'unica cella. </li></ul><ul><li>&quot;C&quot; rappresenta invece una stringa che è memorizzata in due celle consecutive che contengono i caratteri ' C ' e ' '. </li></ul>
  • 35. Stringhe <ul><li>Un vettore di nomi si realizza mediante una matrice di tipo carattere dove ogni riga (vettore) contiene un nome. Ad esempio, per memorizzare i nomi dei giorni della settimana, si può procedere così: </li></ul><ul><li>const char giorni[7][10] = {&quot;lunedì&quot;, &quot;martedì&quot;, </li></ul><ul><li>&quot;mercoledì&quot;, &quot;giovedì&quot;, &quot;venerdì&quot;, &quot;sabato&quot;, &quot;domenica&quot;}; </li></ul><ul><li>dove la dimensione dei singoli vettori (tutti i vettori!), cioè 10, è determinata sommando 1 alla lunghezza del nome più lungo ( mercoledì ). </li></ul><ul><li>Pertanto un vettore di stringhe è in realtà una matrice di caratteri! </li></ul>
  • 36. Stringhe m a r t e d ì … ? … ? l u n e d ì … ? … ? … ? m e r c o l e d ì g i o v e d ì … ? … ? v e n e r d ì … ? … ? s a b a t o … ? … ? … ? d o m e n i c a … ? giorni[0] giorni[1] giorni[2] giorni[3] giorni[4] giorni[6] giorni[5]
  • 37. I/O di stringhe <ul><li>Le stringhe possono comparire come argomento di printf e scanf : per esse si utilizza lo specificatore di formato %s . </li></ul><ul><li>In particolare la printf , quando trova nel format lo specificatore %s , interpreta i valori contenuti nella variabile corrispondente (che dev’essere un vettore di caratteri!) come caratteri e li visualizza finché non trova un carattere ' '. </li></ul><ul><li>Se non è presente il carattere terminatore la printf continua l’output oltre i confini del vettore fino a che non incontra un ' ‘ (ovvero una cella di memoria che contiene 0!). </li></ul><ul><li>Come per gli altri specificatori, anche in %s si può specificare la lunghezza del campo e gli altri attributi di allineamento. </li></ul>
  • 38. Esempio <ul><li>Programma per visualizzare i giorni della settimana, uno per riga, allineati a sinistra (flag - ) in un campo di 15 caratteri. </li></ul><ul><li>#include <stdio.h> </li></ul><ul><li>const char giorni[7][10] = { &quot;lunedì&quot;, &quot;martedì&quot;, &quot;mercoledì&quot;, </li></ul><ul><li>&quot;giovedì&quot;, &quot;venerdì&quot;, &quot;sabato&quot;, &quot;domenica&quot;}; </li></ul><ul><li>  </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>int indice; </li></ul><ul><li>printf (&quot; I giorni della settimana sono: &quot;); </li></ul><ul><li>for (indice = 0; indice < 7; indice++) </li></ul><ul><li>printf (&quot;%-15s &quot;, giorni[indice]); </li></ul><ul><li>} </li></ul>
  • 39. Lettura di stringhe <ul><li>La scanf , quando trova nel format lo specificatore %s , attua un meccanismo di lettura simile a quello usato per i numeri: scarta tutti gli “ spazi neutri ” iniziali ( spazio , <TAB> , <CR> , ecc.), “legge” i caratteri successivi scrivendoli in locazioni consecutive del vettore indicato e si ferma non appena incontra un altro carattere appartenente alla categoria degli “ spazi neutri ”, chiudendo la stringa appena generata nel vettore con il carattere NULL . </li></ul><ul><li>E’ importante quindi che nella stringa non siano presenti spazi e che il vettore destinazione sia dimensionato opportunamente poiché, come sempre in C, non ci sono controlli sugli indici. </li></ul>
  • 40. Lettura di stringhe <ul><li>Il fatto che non ci siano controlli sul numero di caratteri introdotti, ad esempio da tastiera, può provocare danni collaterali non trascurabili: infatti la lettura prosegue fino al primo “ spazio neutro ” in ogni caso e i caratteri letti vengono memorizzati consecutivamente come se la stringa fosse stata dimensionata in modo corretto anche quando è più corta di quanto sarebbe necessario. </li></ul><ul><li>I caratteri “in eccesso” e il NULL vengono comunque memorizzati e possono pertanto andare a ricoprire aree di memoria riservate ad altri dati sporcandoli irrimediabilmente. </li></ul><ul><li>Poiché il nome della stringa è proprio l’idirizzo del vettore di caratteri associato nella scanf non si deve usare il carattere & prima del nome. </li></ul>
  • 41. Esempio <ul><li>Esempio: programma per leggere i nomi (lunghi al massimo 20 caratteri) e le altezze (in cm) di 10 persone e successivamente visualizzarli incolonnati. </li></ul><ul><li>#include <stdio.h> </li></ul><ul><li>#define NUM_NOMI 10 </li></ul><ul><li>#define L_STRING 21 </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>/* Definizioni */ </li></ul><ul><li>char nome[NUM_NOMI][L_STRING]; </li></ul><ul><li>int altezza[NUM_NOMI]; </li></ul><ul><li>int ind; </li></ul>
  • 42. Esempio <ul><li>printf (“ Introduci il nome e l'altezza di 10 persone: &quot;); </li></ul><ul><li>for (ind = 0; ind < NUM_NOMI; ind++) </li></ul><ul><li>{ </li></ul><ul><li>printf (“ Persona N. %2d: &quot;, (ind + 1)); /* indice a partire da 1 */ </li></ul><ul><li>scanf (&quot;%s%d&quot;, nome[ind], &altezza[ind]); </li></ul><ul><li>} </li></ul><ul><li>printf (&quot; Nome Altezza&quot;); </li></ul><ul><li>for (ind = 0; ind < NUM_NOMI; ind++) </li></ul><ul><li>{ </li></ul><ul><li>printf (“ Persona N. %4d: %-20s %3d&quot;, (ind + 1), nome[ind], </li></ul><ul><li>altezza[ind]); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  • 43. Confronto tra stringhe <ul><li>Poiché le stringhe sono vettori, non è lecito assegnare una stringa ad un'altra. Pertanto il frammento di programma che segue è errato: </li></ul><ul><li>char messag[16]; </li></ul><ul><li>..................... </li></ul><ul><li>messag = &quot;Errore nei dati&quot;; </li></ul><ul><li>..................... </li></ul><ul><li>  </li></ul><ul><li>Anche il confronto tra stringhe non può essere effettuato mediante un'unica istruzione, come invece avviene per i singoli caratteri, ma occorre confrontare col criterio opportuno i singoli elementi delle due stringhe. </li></ul>
  • 44. Confronto tra stringhe: esempio <ul><li>Programma che legge da tastiera due parole (lunghe al più 20 caratteri) e verifica se sono uguali o diverse. </li></ul><ul><li>#include <stdio.h> </li></ul><ul><li>#define VERO 1 </li></ul><ul><li>#define FALSO 0 </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>char parola1[21], parola2[21]; </li></ul><ul><li>int ind; </li></ul><ul><li>short int uguali; </li></ul><ul><li>printf (“ Introduci la prima parola: “); </li></ul><ul><li>scanf (“%s”, parola1); </li></ul><ul><li>printf (“ Introduci la seconda parola: “); </li></ul><ul><li>scanf (“%s”, parola2); </li></ul>
  • 45. Confronto tra stringhe: esempio <ul><li>/* verifica se sono uguali */ </li></ul><ul><li>uguali = VERO; /* ipotizza che siano uguali */ </li></ul><ul><li>ind = 0; </li></ul><ul><li>while (uguali && (ind < 20)) </li></ul><ul><li>{ </li></ul><ul><li>if (parola1[ind] != parola2[ind]) </li></ul><ul><li>uguali = FALSO; </li></ul><ul><li>ind++; </li></ul><ul><li>} </li></ul><ul><li>if (uguali) </li></ul><ul><li>printf (“ Le parole introdotte sono uguali”); </li></ul><ul><li>else </li></ul><ul><li>printf (“ Le parole introdotte sono diverse”); </li></ul><ul><li>} </li></ul>
  • 46. Confronto tra stringhe <ul><li>Essendo i caratteri interpretati come numeri interi, è lecito confrontarli tra loro per stabilire la precedenza alfabetica mediante una espressione relazionale. </li></ul><ul><li>0 < 1 < 2 <.... < A < B < C <.....< Z ..... < a < b < c <....< z </li></ul><ul><li>Poiché le stringhe sono vettori di caratteri, e quindi composte da elementi di tipo char, è lecito stabilire l’ordine alfabetico di due stringhe confrontandole fra loro carattere per carattere. </li></ul><ul><li>Esempio: programma che legge da tastiera due parole e stabilisce l’ordine alfabetico. </li></ul>
  • 47. Confronto tra stringhe: esempio <ul><li>#include <stdio.h> </li></ul><ul><li>#define VERO 1 </li></ul><ul><li>#define FALSO 0 </li></ul><ul><li>main() </li></ul><ul><li>{ </li></ul><ul><li>char parola1[21], parola2[21]; </li></ul><ul><li>int ind; </li></ul><ul><li>short int finito, prima1; </li></ul><ul><li>printf (&quot; Introduci la prima parola: &quot;); </li></ul><ul><li>scanf (&quot;%s&quot;, parola1); </li></ul><ul><li>printf (&quot; Introduci la seconda parola: &quot;); </li></ul><ul><li>scanf (&quot;%s&quot;, parola2); </li></ul><ul><li>finito = FALSO; /* segnala fine dei confronti! */ </li></ul><ul><li>ind = 0; </li></ul>
  • 48. Confronto tra stringhe: esempio <ul><li>while (!finito && (ind < 20)) </li></ul><ul><li>{ </li></ul><ul><li>if (parola1[ind] == parola2[ind]) /* caratteri uguali: nessuna decisione */ </li></ul><ul><li> ind++; </li></ul><ul><li>else </li></ul><ul><li> { </li></ul><ul><li> if(parola1[ind] < parola2[ind]) </li></ul><ul><li> prima1 = VERO; /* parola1 precede parola2 */ </li></ul><ul><li> else </li></ul><ul><li> prima1 = FALSO; /* parola2 precede parola1 */ </li></ul><ul><li> finito = VERO; /* caratteri diversi: fine dei confronti */ </li></ul><ul><li> } </li></ul><ul><li>} </li></ul><ul><li>if (prima1) </li></ul><ul><li>printf (&quot; %s precede %s&quot;, parola1, parola2); </li></ul><ul><li>else </li></ul><ul><li>printf (&quot; %s precede %s&quot;, parola2, parola1); </li></ul><ul><li>} </li></ul>

×