Sei sulla pagina 1di 38

Array

1
Gli array dichiarazione
int v[12];
nome array
• Gruppo di celle consecutive v[0] -45
v[1] 6
– Stesso nome e tipo v[2] 0

• Per riferirsi a un elemento, si v[3] 72


v[4] 1543
specificano: v[5] -89
v[6] 0
– Il nome dell’array
v[7] 62
– La posizione dell’elemento (indice) v[8] -3
v[9] 1
• Formato: nomearray[posizione] v[10] 6453

– Il primo elemento ha indice 0 v[11] 78

– L’n° elemento dell’array v è v[n-1] posizione elemento

2
Gli array
• Array: vettori di elementi indicizzati, omogenei,
memorizzati in celle di memoria consecutive

char parola[12];
È un array di 12 elementi di tipo char, vale a
dire un vettore di 12 caratteri
• La lunghezza dell’array è comunque decisa
durante la compilazione del programma
• Non si usano variabili per specificare, nella
dichiarazione, la dimensione degli array

3
Per la precisione
• Slide per NERD
• C99 introduce la possibilità di usare
variabili per dimensionare un array
• C11 (2011) la toglie
• Quindi farlo non è detto che funzioni,
perché il compilatore può non
implementare questa feature
• Quindi per scrivere un codice portabile
non dovreste usarli senza le guardie
#ifndef _STDC_NO_VLA_
4
Lo spazio allocato per gli array
• int Pippo[20];

Le dimensioni devono
essere note prima della
compilazione per
definire quanto spazio
lasciare in memoria per
l’array
Lo spazio allocato per gli array
•int Pippo[20];

Pippo[0] Pippo[2] è a tutti gli effetti


Pippo[1]
Pippo[2] una variabile intera. Una volta
Pippo[3] specificato l’indice accedo ad
Pippo[4] una cella specifica dell’array e
Pippo[5]
Pippo[6] non c’è differenza con le
: variabili viste in precedenza
Pippo[19]
Gli array
• Sequenza di elementi consecutivi dello stesso
tipo in numero predeterminato e costante
• Ogni elemento della sequenza è individuato
mediante un indice con valore da 0 a N-1 (dove
N è la dimensione dell’array)
Esempio
int v[100];
...
v[3]=0;
n.b. se i >= 100, v[i] è un errore!
(e il comportamento è indefinito)

7
Come opera il calcolatore?
• int a[100];
– alloca memoria per 100 elementi interi, a
partire da un certo indirizzo di memoria
• la dimensione deve essere nota al compilatore
• deve essere una espressione costante
• Per accedere all' i-esimo elemento di a
– calcola l'indice i (può essere un'espressione)
– all’indirizzo della prima cella di a somma il
numero di celle pari allo spazio occupato da
i elementi
• ottiene così l'indirizzo dell'elemento cercato

8
Array, cosa da non fare
Errore
int dim; /* il valore a dim è associato solo durante
l’esecuzione */
scanf("%d", &dim);
float resti[dim]; /* quindi il compilatore non sa quanto
spazio riservare in memoria per resti */

Anche se il gcc lo permette, questo NON è da


fare perché espone il codice a vulnerabilità
#define
• Spesso si ricorre alla direttiva di precompilazione
define per dichiarare un array
#define NOME_DEFINE valoreNumerico
• Prima della compilazione, ogni istanza di NOME_DEFINE
(riferibile all’uso di variabile) verrà sostituita da
valoreNumerico
• Se dichiaro int vet[NOME_DEFINE]; le dimensioni
di vet sono note prima di iniziare la compilazione
• L’utilizzo di define rende il codice più leggibile, e
facilmente modificabile quando occorre cambiare la
dimensione dell’array (richiede comunque la
ricompilazione del codice sorgente)
• NB non si deve mettere il ; dopo valoreNumerico
Inizializzazione di un array
• Sintassi compatta:
int n[5]  {1, 2, 3, 4, 5};
– Inizializzazione parziale: gli elementi più a destra sono posti a 0
int n[5]  {13}; tutti gli altri elementi sono posti a 0
– Specificare troppi elementi tra le graffe è un errore di sintassi
• Se la lunghezza dell’array è omessa, gli
inizializzatori la determinano:
int n[]  {5, 47, 2, 0, 24};
è equivalente a:
int n[5]  {5, 47,  2, 0, 24};
– In tal caso la dimensione è inferita automaticamente, e si
avranno 5 elementi nell’array (con indici che variano tra 0 e 4)

11
Gli array
• Gli elementi di un array sono normali variabili:
vett[0]  3;
printf ("%d", vett[0]);
> 3
scanf ("%d", &vett[1]);
> 17 vett[1] assume valore 17
• Si possono usare espressioni come indici:
se x  3, y=7 e z=4
vett[52] è uguale a vett[3]
ed è uguale a vett[x]
ed è uguale a vett[y-z]
12
Esempi sugli array
• Dichiarazione del vettore:
int a[20];

• Inizializzazione del vettore:


for (i = 0; i < 20; i++)/*int i; in qualche punto*/
a[i] = 0;

• Oppure (lettura da terminale):


for (i = 0; i < 20; i++) {
printf ("Scrivi un intero: ");
scanf ("%d", &a[i]);
}

13
Esempio

#define MAX_LEN 30 Sono certo che n è


#include <stdio.h> compatibile con le
void main() dimensioni reali di v1
{
int v1 [MAX_LEN];
int i, n; // n contiene le dimensioni effettive

do {
Da qui in poi opero solo
printf("quanti numeri vuoi inserire?");
scanf("%d" , &n); sulle prime n celle, quelle
}while(n < 0 || n > MAX_LEN); che vanno dall’indice 0 ad
n-1
for(i = 0; i < n; i++) {
printf("Inserire elemento posizione %d" , i+1);
scanf("%d" , &v1[i]);
}
}
Esempi sugli array
• Ricerca del massimo:
max = a[0];
for (i = 1; i <= 19; i++)
if (a[i] > max)
max = a[i];

• Calcolo della media:


media = 0;
for (i = 0; i <= 19; i++)
media = media + a[i];
media = media / 20;

15
Esempi sugli array
• Calcolo di massimo, minimo e media di un vettore
– È sufficiente una sola scansione del vettore (un solo ciclo)
int a[20], max, min, i;
float media;

media = a[0];
max = a[0];
min = a[0];
for ( i  1; i  19; i ) {
media  media  a[i];
if ( a[i]  max )
max  a[i];
if ( a[i]  min )
min  a[i];
}
media  media / 20;
16
Un nuovo problema
• Invertire una sequenza di 100 interi
introdotta dall’utente (stdin)
– Con un array?
– Senza array?

17
/* Programma InvertiSequenza */
#include <stdio.h>
int main() {
int i;
int a[100];
i = 0;
while (i < 100) {
printf("fornisci un valore intero");
scanf("%d", &a[i]);
i++;
} esaminare criticamente i cicli!
i--;
while (i >= 0) {
printf("%d\n", a[i]);
i--;
}
return 0;
}

18
Operazioni sugli array
• Si opera sui singoli elementi, uno per volta
• Non è possibile operare sull’intero array,
agendo su tutti gli elementi simultaneamente
/ come ricopiare array1 in array2 /
int array1[10], array2[10];
int i;
. . .
array2  array1; / ERRATO / 
. . .
for (i  0; i  10; i) 
array2[i]  array1[i]; / CORRETTO /

19
Confronto tra array
•Occorre operare su ogni singolo elemento!
#define MAX_LEN 300
#include <stdio.h>
void main(){
int v1[MAX_LEN], v2[MAX_LEN], i, uguali=1;

//… acquisizione…

for(i = 0; (i < MAX_LEN) && uguali; i++)


if(v1[i] != v2[i])
uguali = 0;

if(uguali)
printf("uguali");
else
printf("diversi");
}
Copiare alcuni elementi da un array ad
un altro senza lasciare buchi
• In molti casi è richiesto di scorrere un array v1 e di
selezionare alcuni valori secondo una data condizione.
• Tipicamente i valori selezionati in v1 vengono copiati in
un secondo array, v2, per poter essere utilizzati.
• È buona norma copiare i valori nella prima parte di v2,
eseguendo quindi una copia «senza lasciare buchi».
• È anche necessario sapere quali sono i valori significativi
in v2 e quali no.

•Esempio : copiare i numeri pari in v1 in v2


• v1 5 6 7 89 568 68 657 989 96 98
• v2 ? 6 ? ? 568 68 ? ? 96 98
• v2 6 568 68 96 98 ? ? ?
Copiare alcuni elementi da un array ad
un altro
•Per fare questo è necessario usare due indici:
– i per scorrere v1: parte da 0 e arriva a n1, la
dimensione effettiva di v1, con incrementi regolari.
– n2 parte da 0 e viene incrementata solo quando
un elemento viene copiato.
• n2 indica quindi il primo elemento libero in v2,
• al termine, n2 conterrà il numero di elementi in v2, quindi la sua
dimensione effettiva

5 6 7 89 568 68 657 989 96 98 i = 10;


n1 = 10;
6 568 68 96 98 ? ? ? n2 = 5;
Esempio
Chiedere all’utente di inserire un array di interi (di
dimensione definita precedentemente) e quindi un
numero intero t. Il programma quindi
– Salva gli elementi inseriti in un vettore v1
– Copia tutti gli elementi di v1 che sono maggiori di n
in un secondo vettore v2
– La copia deve avvenire nella parte iniziale di v2
senza lasciare buchi
Esempio
printf("\nInserire la soglia");
scanf("%d" , &t);
n2 = 0;
for(i = 0; i < n1; i++)
if(v1[i] > t){
v2[n2] = v1[i];
n2++;//n2 è la prima posizione libera in v2
}

printf("\n Maggiori di %d sono: [" , t);

for(i = 0 ; i <n2 ; i++)


printf(" %d, ", v2[i]);

printf("]");
/* Output Strutturato: Stampa di un istogramma */

#include <stdio.h>
#define SIZE 10

int main () {
int n[SIZE] = { 19, 3, 15, 7, 11, 9, 13, 5, 17, 1 };
int i, j;

printf("%s%13s%17s\n\n","Element","Value","Histogram");

for ( i = 0 ; i < SIZE ; i++ ) {


printf("%7d%13d ", i, n[i]);

for ( j = 1 ; j <= n[i] ; j++ ) /* una riga di ‘*’ */


printf("*");

printf("\n");
}

return 0;
}
25
Output del programma
Element Value Histogram

0 19 *******************
1 3 ***
2 15 ***************
3 7 *******
4 11 ***********
5 9 *********
6 13 *************
7 5 *****
8 17 *****************
9 1 *

26
Esercizio (semplice, ma apparentemente difficile)
• Si scriva un programma che visualizzi gli
istogrammi verticalmente:
*
*
* *
* *
* * *
* * *
* * * *
* * * *
* * * * *
* * * * *
* * * * * *
* * * * * *
* * * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * * *
19 3 15 7 11 9 13 5 17 1
0 1 2 3 4 5 6 7 8 9

27
#define SIZE 10
int main () {
int n[SIZE] = { 19, 3, 15, 7, 11, 9, 13, 5, 17, 1 };
int i, j, max = n[0];
for ( i = 1 ; i < SIZE ; i++ ) /* Calcola max di n[] */
if ( max < n[i] )
max = n[i];
for ( j = max ; j > 0 ; j-- ) {
for ( i = 0 ; i < SIZE ; i++ )/*stampa di ogni riga*/
if ( n[i] >= j )
printf(" * ");
else
printf(" ");
printf("\n");
}
for ( i = 0 ; i < SIZE ; i++ )
printf("%3d ", n[i]);
printf("\n");
for ( i = 0 ; i < SIZE ; i++ )
printf("%3d ", i);
printf("\n");
return 0;
}
28
Ricerca di un elemento in un array
/* Frammento di programma.
Verifica la presenza di un elemento in un vettore.
Se è presente, stampa l'indice della prima occorrenza;
se non è presente, stampa -1*/

int dato; int risultato = -1,n;


Ricerca
int array[size];
sequenziale
………..
for ( n=0; n < size; n++ ) ...
if (array[n] == dato) { Biblioteca...
risultato = n;
break;
}
printf("risultato = %d\n", risultato);
29
Ricerca binaria
int dato, risultato = -1;
int array[size];
int low=0, high=size-1, mid;
while ( low <= high ) {
mid = (low+high)/2; Termina?
if ( dato == array[mid] ) {
risultato = mid; Perché?
}
break; È corretto?
else if ( dato < array[mid] )
high = mid – 1;
else
low = mid + 1;
}

30
Ordinare un array
• Data un vettore V[n] permutare i suoi
elementi in modo che risulti ordinato in
senso crescente:
V[0] <= V[1] <= V[2] <= … <= V[n-1].  
Bubblesort
• L’idea di questo algoritmo è quella di confrontare i
primi due elementi e se non sono ordinati li si
scambia, poi si confrontano il secondo e il terzo e se
non sono ordinati li si scambia e così via sino a
confrontare penultimo e ultimo elemento.
• Dopo aver scandito una prima volta tutto il vettore si
è sicuri che l’elemento maggiore è nella cella più a
destra, quindi si comincia un nuovo ciclo che
confronta ancora a due a due le celle dalla prima
all’ultima. Se n è il numero di elementi del vettore si
itera questo processo di scansione per n-1 volte
quando il vettore risulterà completamente ordinato.
#include stdio.h
#define N 100
int main() {
int i=0, j, n, aux, V[N];
printf(“\nInserire gli elementi del vettore V:\n”);
do {
scanf(“%d”,&V[i]); i++;
} while(i<N);
for (i  0; i  N  1; i) {  
for (j  0; j  N  1 - i; j) {
if (V[j]  V[j  1]) {
aux = V[j+1];
V[j+1] = V[j];
V[j] = aux;
}
}
}
printf(“\nIl vettore ordinato e’:\n ”);
for (i = 0; i < n; i++)
printf(“%d ”,V[i]);
return 0;
}
Piccolo trucco aritmetico

• Calcolare gx in modo efficiente:


• g53
• 53=(110101)2=32+16+4+1
• g2x=gx * gx
• gg2g4g8g16g32 (5 moltiplicazioni)
• g53=g32*g16*g4*g1 (3 moltiplicazioni)
• g53 si calcola con 8 moltiplicazioni invece
che con 53

34
#include <stdio.h>
#include <stdlib.h>
#define DIM 5
main() {
int i, ind, base, esp, num, binario[DIM];
long int ris=1, prodotti[DIM];

printf("\nIntroduci base: ");


scanf ("%d", &base);
printf("\nIntroduci esponente: ");
scanf ("%d", &esp);
printf("\n");

if ((esp >= 0) && (esp < 32) && (base >= 0) && (base < 10)) {

/* calcola la conversione in binario dell’esponente */


/* visualizza il vettore binario */
/* calcola vettore prodotti */
/* visualizza il vettore prodotti */
/* calcola il risultato */
/* visualizza il risultato */
} else
printf("\nNumeri non leciti");

return 0;
}
35
/* calcola la conversione in binario dell’esponente */

num = esp;
for(ind = DIM-1; ind >= 0; ind--) { /* con un indice che va da DIM-1 a 0 */
binario[ind] = num % 2; /* calcola un nuovo bit */
num /= 2; /* aggiorna num per il prossimo ciclo */
}

/* visualizza il vettore binario */

printf ("\nConversione del numero %d: ", esp);

for (ind = 0; ind < DIM; ind++) /* Visualizza il vettore binario: */


printf ("%d",binario[ind]); /* un bit per volta */
printf ("\n\n");

36
/* calcola vettore prodotti */
prodotti[DIM-1]=base; /* calcola vettore prodotti */
for (ind = DIM-2; ind >= 0; ind--) {
prodotti[ind]=prodotti[ind+1]*prodotti[ind+1];
}

/* visualizza il vettore prodotti */


for(ind = 0; ind < DIM; ind++)
printf ("%d ",prodotti[ind]);
printf ("\n\n");

/* calcola il risultato */
for(ind = 0; ind < DIM; ind++)
if(binario[ind]==1)
ris=ris*prodotti[ind];

/* visualizza il risultato */
printf ("Risultato: %d\n",ris);

37
#include <stdio.h>
#include <stdlib.h> /* calcola vettore prodotti */
#define DIM 5 prodotti[DIM-1]=base; /* calcola vettore prodotti */
main() { for (ind = DIM-2; ind >= 0; ind--) {
int i, ind, base, esp, num, temp; prodotti[ind]=prodotti[ind+1]*prodotti[ind+1];
long int ris=1; }
int binario[DIM];
long int prodotti[DIM]; /* visualizza il vettore prodotti */
for(ind = 0; ind < DIM; ind++)
printf("\nIntroduci base: "); printf ("%d ",prodotti[ind]);
scanf ("%d", &base); printf ("\n\n");
printf("\nIntroduci esponente: ");
scanf ("%d", &esp); /* calcola il risultato */
printf("\n"); for(ind = 0; ind < DIM; ind++)
if(binario[ind]==1)
/* calcola la conversione in binario dell’esponente */ ris=ris*prodotti[ind];
if ((esp >= 0) && (esp < 32) && (base >= 0) && (base < 10)) {
num = esp; /* visualizza il risultato */
for(ind = DIM-1; ind >= 0; ind--) { printf ("Risultato: %d\n",ris);
binario[ind] = num % 2; /* calcola un nuovo bit */
num /= 2; /* aggiorna num per il prossimo ciclo */ } else
} printf("\nNumeri non leciti");

/* visualizza il vettore binario */ system("PAUSE");


return 0;
printf ("\nConversione del numero %d: ", esp); }

for (ind = 0; ind < DIM; ind++) /* Visualizza il vettore binario: */


printf ("%d",binario[ind]); /* un bit per volta! */
printf ("\n\n");

38

Potrebbero piacerti anche