Sei sulla pagina 1di 5

I VETTORI IN C (Capitolo 6)

I vettori (array) sono delle strutture dati che consistono in un gruppo di locazioni di memoria correlate dal
fatto che tutte hanno lo stesso nome e tipo di dato; per questo è possibile lavorare sui dati in essi contenuti
anche in maniera automatica e non per forza singolarmente.
I vettori (e anche le strutture), sono statici, difatti manterranno le proprie dimensioni durante l’esecuzione del
programma e non si potranno ne aggiungere ne cancellare elementi.
Per far riferimento a una particolare posizione o elemento all’interno del vettore, specificheremo il nome
dello stesso e il numero di posizione di quel particolare elemento nel vettore.

Possiamo definire un array di dati in questo modo: tipo_di_dato nome_array [DIM]; (*)

Ognuno degli elementi dell’array potrà essere puntato con il nome del vettore, seguito dal numero di
posizione per quel particolare elemento racchiuso tra parentesi quadre ([ ]). Il primo elemento di ogni vettore
è si troverà in posizione zero, mentre l’ultimo in posizione DIM – 1.
Il numero di posizione contenuto all’interno delle parentesi quadre è più formalmente noto come indice (è
sempre un intero o un’espressione intera).

Usando la dicitura (*), dovremmo poi dichiarare il contenuto di ogni cella di memoria:
nome_array [indice] = carattere_contenuto;
C’è anche un secondo modo per definire un array, molto utile se si vuole definire fin da subito il contenuto
delle celle:
tipo_di_dato nome_array [ ] = {a,b,c,d,e}; ← lista di inizializzatori

(in questo caso la dimensione dell’array verrà ricavata direttamente dal numero di elementi tra le graffe)

Una notazione importante:


I nomi dei vettori, come i nomi delle altre variabili, possono contenere soltanto lettere, cifre (non possono
essere il primo carattere) e caratteri di sottolineatura;

ESERCIZIO: Dichiariamo un array di 3 elementi e riportiamone l’utilizzo complessivo di memoria.


#include <stdio.h>

int main () {
int k;
float b [ ] = {2.71,0,3.14};
for (k=0; k<3; k++){
printf("%f\n", b[k]);

printf("La dimensione di b e': %d", sizeof(b));

// Poichè un float ha una dimensione definita di 4 bit, essendoci 3 elementi la dimensione


dell'array sarà di 12 bit.

return 0;
}
ESERCIZIO: Inizializzare a zero gli elementi di un vettore.
#include <stdio.h>

int main () {
int n [10];
int i;

for (i=0;i<10;i++){
n[i] = 0;
}
printf("%s%13s\n", "Element", "Value");
// il numero tra %s (in questo caso 13) indica la distanza che deve intercorrere fra i due elementi

for(i=0;i<10;i++){
printf("%4d%14d\n",i + 1,n[i]);
}

return 0;
}

Direttiva #define

La direttiva #define, serve a definire una MACRO, ovvero un simbolo al quale verrà collegato un valore o
qualsiasi altra cosa si voglia. 
La sintassi con cui utilizzare la direttiva è la seguente:

#define  nome_macro  valore_macro 

Convenzionalmente i nomi delle macro vengono scritti con delle lettere MAIUSCOLE. Il preprocessore
legge la definizione della MACRO e, ogni volta che ne incontra il nome all'interno del file
sorgente SOSTITUISCE al simbolo il corrispondente valore, SENZA verificare la correttezza sintattica
dell'espressione risultante.

Ad esempio, nel caso fosse necessario stampare molte volte il medesimo messaggio, si può definire una
MACRO di questo tipo per rendere più immediata la scrittura e la leggibilità del programma:
#include <stdio.h> 
#define AVVISO printf("\nil programma, fino a qui, funziona in modo corretto"); 
int main() {
char c;
  c = getchar();
... // istruzioni 
AVVISO
... // altre istruzioni 
AVVISO
... // istruzioni 
}

Grazie al preprocessore, ovvero effettuando la sostituzione, questo codice si trasforma in :

int main() {
char c;
  c = getchar();
... // istruzioni 
printf("\nil programma, fino a qui, funziona in modo corretto"); 
... // altre istruzioni 
printf("\nil programma, fino a qui, funziona in modo corretto"); 
... // istruzioni 
}
Facendo ora riferimento al programma scritto a pag. 191, è stata introdotta la direttiva del preprocessore
#define SIZE 10. Questa definirà quindi una costante simbolica SIZE il cui valore sarà 10. Quando il
programma elaborato dal preprocessore, tutte le occorrenze della costante simbolica SIZE saranno sostituite
dal testo di sostituzione 10.

Pag. 192-193 Sommare gli elementi di un vettore

Quantificatore const
Come il nome stesso suggerisce, const rende l’entità cui è applicato immutabile (nel caso, ad esempio, di
una variabile), o indica che l’entità stessa non può applicare cambiamenti. Un qualsiasi tentativo di modifica
di queste variabili, provocherà un errore in fase di compilazione.

const double phi = 1.6180339887;

L’ordinamento dei vettori


L’ordinamento dei dati è una delle applicazioni più importanti nel campo dell’elaborazione elettronica. In
teoria, tutte le organizzazioni devono ordinare qualche dato e, in molti casi massicce quantità di dati. Il
problema dell’ordinamento ha attirato alcuni degli sforzi più intensi della ricerca informatica.

La tecnica che analizzeremo è detta bubble sort. Questa confronterà ogni coppia di elementi adiacenti di un
vettore. Lasceremo i valori così come li avremo trovati, qualora una coppia sia già in ordine crescente (o nel
caso che i valori siano identici). I loro valori saranno invece scambiati di posizione all’interno del vettore,
qualora una coppia sia in ordine decrescente.

#include <stdio.h>
void BubbleSort(float*, int); //Prototipo funzione BubbleSort

void main(){
float array[] = {2.71, 0, 3.14, 8.24, -9.0};
int i, n = sizeof(array)/sizeof(float); // n = # elem. array, i = indice elem. array

printf("Array non ordinato\n");


for(i = 0; i < n; i++)
printf("%10f", array[i]); // Stampa array non ordinato
printf ("\n\n\n");

BubbleSort(array, n);
printf("Array ordinato\n");
for(i = 0; i < n; i++)
printf("%10f", array[i]); // Stampa array ordinato
printf("\n");
}

void BubbleSort(float *array, int n) {


/*Il primo ciclo controlla il numero dei passaggi da svolgere ed è regolato dal contatore k; il
secondo ciclo controlla il numero di confronti per ogni passaggio*/
int k, i;
float t; // Variabile di appoggio

for(k = 0; k < n-1; k++){


for(i = 0; i < n-1-k; i++) {
if(array[i] > array[i+1]) {
t = array[i];
array[i] = array[i+1];
array[i+1] = t;
}
}
}
}
La virtù principale dell’ordinamento a bolle è la sua facilità di implementazione. Questo tuttavia risulterà
poco efficiente soprattutto quando si ordineranno vettori di dimensioni ragguardevoli, per questo sono stati
sviluppati algoritmi notevolmente più efficienti di questo.
Rappresentare graficamente i valori degli elementi di un vettore con gli istogrammi
Il seguente esercizio, leggerà alcuni numeri da un vettore e rappresenterà quelle informazioni in un grafico a
barre o istogramma: a fianco di ogni numero sarà visualizzato una barra composta di altrettanti asterischi.

#include <stdio.h>
#define SIZE 10
int main() {
int a[SIZE] = {19,3,0,7,11,9,13,5,17,1};
int i; //contatore per il for esterno per gli elementi del vettore
int j; //contatore per il for interno per il conteggio degli asterischi di ogni elemento

printf("%s%13s%17s\n","Element","Value","Histogram");
for(i=0; i < SIZE; i++) {
printf("%4d%15d ",i,a[i]); //Stampa il valore dell'elemento in posizione i dell'array

for (j=1; j<=a[i]; j++) {


printf("%c",'*'); //Stampa un asterisco in base al valore contenuto in a[i]
}
printf("\n");

return 0;

Adesso voglio stampare il diagramma a barre in verticale e non in orizzontale.

Per prima cosa dovremmo trovare il valore massimo contenuto nell’array in modo tale da conoscere l’altezza
massima dell’istogramma.

int m = a [0]; //Inizializziamo il valore massimo m al primo elemento dell’array (a[0])


for(i = 1; i < n; i++)
if( a[i] > m )
m = a[i]; //Ultimato il ciclo for avremo trovato il valore massimo contenuto nell’array

for(k = 1; k <= m; k++){ //Regola l’altezza massima dell’istogramma


for(i = 0; i < n; i++){ //Contatore per il for esterno per gli elementi del vettore
if( a[i] >= k )
printf("*"); //Fin quando è mantenuta la relazione dell’ if stampa un *
else
printf(" ");
}
printf("\n");

6.6 Ordinamento di un vettore Pag. 208 – 210


6.8 La ricerca nei vettori Pag. 216 – 222
I vettori multidimensionali
I vettori in C possono anche avere più di un indice. Un utilizzo tipico dei vettori multidimensionali è la
rappresentazione di tabelle di valori formate da informazioni organizzate in righe e colonne. Per identificare
un particolare elemento della tabella, dovremo specificare due indici: il primo identificherà per convezione la
riga dell’elemento, mentre il secondo ne identificherà a colonna. Queste tabelle o vettori che per identificare
un particolare elemento richiedono due indici sono detti vettori bidimensionali o matrici.

In generale, una matrice con m righe e n colonne sarà detta matrice m × n. Ogni elemento della matrice a è
identificato da un nome di elemento avente la forma a[i][j], dove a rappresenta il nome della matrice, mentre
i e j sono gli indici che identificano univocamente ogni elemento incluso in a.

Un vettore multidimensionale potrà essere inizializzato contestualmente alla propria dichiarazione, in un


modo molto simile a quello utilizzato per un vettore unidimensionale. Per esempio, una matrice b [2][2]
potrà essere dichiarata e inizializzata con

int b [2][2] = { { 1,2 }, { 3,4 } };

I valori saranno raggruppati per riga all’interno di parentesi graffe. I valori nel primo insieme di parentesi
inizializzeranno la riga 0 e i valori nel secondo insieme di parentesi inizializzeranno la riga 1.
Ogni elemento che non avrà un inizializzatore esplicito sarà inizializzato automaticamente a zero.

Molte manipolazioni tipiche delle matrici utilizzano il comando di ripetizione for; per esempio, la struttura
seguente azzererà tutti gli elementi della terza riga della matrice a:

for (column = 0; column <= 3; column ++)


a [2] [column] = 0;

Abbiamo specificato la terza riga, di conseguenza sappiamo che il primo indice sarà sempre 2. Il ciclo for
farà variare dunque solo il secondo indice (ovverosia quello della colonna).