Sei sulla pagina 1di 28

4/10/2013

1
Vettori, stringhe e matrici
Lezione frontale #4
Argomenti:
-vettori e stringhe
-allocazione dinamica di memoria
-libreria di funzioni sulle stringhe
-Strutturazione di un progetto con librerie e CUnit
Lab di Informatica - Prof. F. Calefato
Tipi di dato in C
Lab di Informatica - Prof. F. Calefato
4/10/2013
2
VETTORI & STRINGHE
Parte 1
Lab di Informatica - Prof. F. Calefato
Vettori (Array)
I vettori (array) sono uno dei tipi di dato
strutturati:
Sequenza finita di elementi omogenei (tutti dello
stesso tipo)
Ogni elemento identificato allinterno dellarray da
un numero dordine detto indice dellelemento
Il numero di elementi del vettore detto lunghezza
(o dimensione fisica) del vettore
Lab di Informatica - Prof. F. Calefato
4/10/2013
3
Vettori (in teoria)
Esempio
Vettore di n elementi
n detto lunghezza o dimensione fisica del vettore
Ogni elemento identificato da un indice intero
compreso tra 1 e n
1 2 N
X Y Z
indici
elementi
Lab di Informatica - Prof. F. Calefato
Vettori in C
In C il vettore un tipo di dato primitivo e si usa il costruttore
di tipo [ ]
Sintassi
<id-tipo> <id-variabile>[ <dimensione> ];
dove:
<id-tipo>: identificatore di tipo degli elementi componenti
<dimensione>: costante intera che rappresenta il numero
degli elementi componenti
<id-variabile>: identificatore della variabile strutturata (il
vettore)
Es.
int studenti [35];
N.B. lindice in C compreso tra 0 e n-1
Lab di Informatica - Prof. F. Calefato
4/10/2013
4
Esempi di dichiarazioni
#define MAX 10
int vet[MAX];
Alloca un vettore di MAX elementi, ovvero 10 locazioni di memoria
consecutive, ciascuna contenente un intero
MAX la lunghezza del vettore.
In C lindice degli elementi va sempre da 0 a lunghezza 1
vet[i] denota lelemento del vettore vet di indice i
Ogni elemento del vettore una variabile di tipo intero
vet lindirizzo del primo elemento vet[0]
ATTENZIONE:
La lunghezza del vettore deve essere una espressione costante, cio nota
a tempo di compilazione
int N;
float vet[N];
Lab di Informatica - Prof. F. Calefato
ERRORE Non standard ANSI C
Il compilatore non sa quanta
memoria allocare per larray
Uso di typedef per dichiarare il tipo
non primitivo vettore
In C possibile utilizzare typedef [ ] per dichiarare tipi di dato
non primitivi rappresentati da vettori
Sintassi
typedef <tipo-componente> <tipo-vettore>[<dim>];
<tipo-componente>: identificatore di tipo di ogni singola
componente
<tipo-vettore>: identificatore che si attribuisce al nuovo tipo
<dim>: numero di elementi che costituiscono il vettore (deve
essere una costante)
Esempio:
typedef int persone[30];
persone v1, v2; /* v1 e v2 sono variabili di tipo vettore ed ognuna
rappresenta un vettore di 30 elementi interi */
Lab di Informatica - Prof. F. Calefato
4/10/2013
5
Inizializzazione di un vettore (1/2)
Possibilit 1: inizializzazione in fase di
definizione
Esempio:
int v[10] ={1,2,3,4,5,6,7,8,9,10};
/* v[0] =1; v[1] =2; ... v[9] =10; */
NB la dimensione determinata sulla base
dellinizializzazione
Lab di Informatica - Prof. F. Calefato
Inizializzazione di un vettore (2/2)
Possibilit 2: mediante un ciclo
Per attribuire un valore iniziale agli elementi di un
vettore si pu attuare una sequenza di assegnamenti
alle N componenti del vettore
Esempio:
#define N 30
int vettore[N];
int i;
...
for (i =0; i <N; i++)
vettore [i] =i;
Lab di Informatica - Prof. F. Calefato
4/10/2013
6
Esempi di inizializzazione di vettori
Elementi del vettore inizializzati con valori costanti contestualmente alla
dichiarazione del vettore
Esempio: int n[4] ={11, 22, 33, 44};
Linizializzazione deve essere contestuale alla dichiarazione
Esempio: int n[4];
n ={11, 22, 33, 44}; errore!
Se ci sono meno inizializzatori di elementi, quelli rimanenti vengono posti
a 0
Esempio: int n[10] ={3}; azzera i rimanenti 9 elementi del vettore
float af[5] ={0.0}pone i 5 elementi pari a 0,0
int x[5] ={}; errore!
Se ci sono pi inizializzatori di elementi, si ottiene un errore di sintassi
Esempio: int v[2] ={1, 2, 3}; errore!
Se si mette una lista di inizializzatori, si pu evitare di specificare la
lunghezza (viene presa la lunghezza della lista)
Esempio: int n[] ={1,2,3}; equivale a int n[3] ={1,2,3};
ERRORE
ERRORE
ERRORE
Lab di Informatica - Prof. F. Calefato
Dimensione fisica vs. dimensione logica
Un array una collezione finita di N celle dello stesso
tipo
Non significa che si debbano per forza usare sempre tutte.
La dimensione logica di un array pu essere inferiore
alla sua dimensione fisica
la porzione di array realmente utilizzata dipende dai dati
dingresso
Esempio
#define DIM 10
main() {
int v[DIM] ={273,340,467,10};

Dimesione
fisica 10
Dimesione
logica 4
Lab di Informatica - Prof. F. Calefato
4/10/2013
7
Operatori di vettori in C
Non esistono operatori specifici per i vettori
E necessario operare singolarmente sugli elementi componenti
Non possibile lassegnamento diretto tra vettori
int V[10], W[10];

V =W; /* non corretto! */


Non possibile leggere (o scrivere) un intero vettore
fanno eccezione le stringhe (lo vedremo pi avanti!)
Occorre leggere/scrivere le sue componenti
Esempio: lettura di un vettore
int V[100];
int i;
for(i =0; i <100; i++) {
printf(valore %d-simo? , i);
scanf(%d, &V[i]);
}
Lab di Informatica - Prof. F. Calefato
Esercizio 1
Si realizzi un programma che, dati in input gli
elementi di due vettori A e B, entrambi di 10
interi, calcoli e stampi gli elementi del vettore C
(ancora di 10 interi), ottenuto come somma di A
e B
Realizzate il codice nel main senza invocare
altre procedure o funzioni
Lab di Informatica - Prof. F. Calefato
4/10/2013
8
Soluzione
#include <stdio.h>
#define N 10
int A[N], B[N], C[N];
main() {
int i;
/* lettura del vettore A */
for (i =0; i <10; i++) {
printf(valore di A[%d] ? , i);
scanf(%d, &A[i]);
}
/* lettura del vettore B */
for (i =0; i <10; i++) {
printf(valore di B[%d] ? , i);
scanf(%d, &B[i]);
}
/* calcolo del risultato */
for (i =0; i <10; i++)
C[i] =A[i] +B[i];
/* stampa del risultato C */
for (i =0; i <10; i++)
printf(C[%d]=%d\n,i, C[i]);
}
Lab di Informatica - Prof. F. Calefato
Esercizio 2
Usare la typedef per creare un tipo vettore di
interi di dimensione MAX (es MAX 10)
Creare un array di tipo vettore e avvalorarlo
con interi letti da tastiera
Dopodich stampare a video il contenuto del
vettore e la somma totale degli elementi
Realizzate il codice nel main senza invocare
altre procedure o funzioni
Lab di Informatica - Prof. F. Calefato
4/10/2013
9
Esercizio 3
Scrivere un programma che:
definisca il tipo vettore di lunghezza massima 10
interi con una typedef
definisca due vettori A e B di 5 interi, avvalorati da
tastiera, ancora con una typedef
definisca un vettore C di 10 interi che conterr gli
elementi di A seguiti da quelli di B;
e stampi a video gli elementi del vettore C
Realizzate il codice nel main senza invocare
altre procedure o funzioni
Lab di Informatica - Prof. F. Calefato
Vettori di caratteri = stringhe
Una stringa di caratteri in C un array di caratteri terminato dal
carattere '\0
Un vettore di N caratteri pu ospitare stringhe lunghe al pi N-1
caratteri perch una cella destinata al terminatore '\0
Un array di N caratteri pu essere usato per memorizzare anche
stringhe pi corte di N-1
Per es, se la stringa s lunga k-1 caratteri, k<N, le celle oltre la k-esima sono
sono inutilizzate e contengono un valore casuale (a meno di non azzerarle
esplicitamente con memset)
Come per gli array compito del programmatore non superare il
numero di caratteri consentiti dalla dimensione
Esempio
#include <string.h>
memset(s, \0, strlen(s)*sizeof(char));
i s a \0 s
Lab di Informatica - Prof. F. Calefato
4/10/2013
10
Operazioni e inizializzazioni con le stringhe
Essendo dei vettori, vale tutto quello che stato
riportato su di essi
Es.
char s[MAX] ={i, s, a, '\0'};
char s[MAX] =isa; // \0 automaticamente incluso
Nota
a !=a
a una costante carattere e occupa 1 byte
a una stringa costante che occupa due byte, uno per
il carattere a e uno per \0
Lab di Informatica - Prof. F. Calefato
Esempio di uso stringa: copia di stringhe
main() {
char s1[ ] =Ciao mondo;
char s2[MAX];
int i=0;
for (i=0; s1[i]!='\0'; i++) {
s2[i] =s1[i];
}
s2[i] = '\0';
}
Lab di Informatica - Prof. F. Calefato
4/10/2013
11
Stringhe e scanf() / printf()
char str[MAX];
int i;

scanf(%c, &str[i]);
scanf( %s , str);
char str[MAX];
int i;

printf(%c, stri[i]);
printf(%s, str);
Lab di Informatica - Prof. F. Calefato
Esercizio 4
Scrivere nel main il codice tale che
Data in input una stringa di lunghezza MAX
Restituisce una nuova stringa con ogni carattere
ripetuto tre volte
Occhio al carattere terminatore!
Es
balbuziente(abcd) restituisce aaabbbcccddd
Lab di Informatica - Prof. F. Calefato
4/10/2013
12
Asserzioni CUnit con puntatori e stringhe
Lab di Informatica - Prof. F. Calefato
Asserzione Significato
CU_ASSERT_PTR_EQUAL(actual, expected) Assert that pointers
actual ==expected
CU_ASSERT_PTR_NOT_EQUAL(actual, expected) Assert that pointers
actual !=expected
CU_ASSERT_PTR_NULL(value) Assert that pointer
value ==NULL
CU_ASSERT_PTR_NOT_NULL(value) Assert that pointer
value !=NULL
CU_ASSERT_STRING_EQUAL(actual, expected) Assert that
strings actual and expected
are equal
CU_ASSERT_STRING_NOT_EQUAL(actual, expected) Assert that
strings actual and expected
differ
malloc(), calloc() e free()
E se si volesse creare dinamicamente un vettore/stringa di
dimensione N, con N letto da tastiera?
Occorre sfruttare le funzioni di allocazione dinamica della memoria
Le variabili dinamiche sono allocate tramite malloc() e calloc()
sfruttano una porzione di memoria apposita chiamata heap
Lheap, ovviamente non infinito e quindi il programmatore deve
ricordarsi di deallocare manualmente la memoria dinamica
occupata quando non ne ha pi bisogno usando la funzione free()
Variabili statiche deallocate automaticamente dal SO
Le variabili dinamiche deallocate manualmente dal programmatore,
altrimenti si va incontro ai cosiddetti memory leak
Dunque a ogni malloc()/calloc() deve corrispondere una free()
Lab di Informatica - Prof. F. Calefato
4/10/2013
13
malloc(), calloc() e free()
Nella libreria stdlib (header stdlib.h):
void * calloc (int n, int dim_elemento)
alloca spazio in memoria per n elementi di dimensione
(ciascuno) dim_elemento, inizializza tutti i bit a zero, e
restituisce il puntatore a void
void * malloc (int dim_totale)
alloca spazio in memoria per dim_totale byte e restituisce il
puntatore a void
calloc() e malloc() resituiscono un void *
C bisogno di effettuare il cast al tipo corretto
free (ptr)
libera la zona di memoria puntata da ptr
Lab di Informatica - Prof. F. Calefato
Vettori e puntatori
Esiste una relazione molto stretta tra array e puntatori
Il nome di un array di per s un indirizzo di memoria
Sono in pratica equivalenti a parte che
un array rappresenta un indirizzo fissato (a differenza dei
puntatori che possono cambiare)
Es.
char* p =ciao;
char s[MAX] =mondo;
p 0xA01

0xB10 m
0xB11 o
0xB12 n
0xB13 d
0xB14 o
0xB15 \0
s 0xB10
Lab di Informatica - Prof. F. Calefato

0xA01 c
0xA02 i
0xA03 a
0xA04 o
0xA05 \0
4/10/2013
14
Aritmetica dei puntatori
Se p un puntatore a un dato con un certo tipo
allora:
Lespressione p+i rappresenta lindirizzo di memoria
corretto per memorizzare la successiva i-ma
variabile dello stesso tipo a partire da p
Sono corrette anche espressioni come:
p +=i; // equivale a p = p + i;
p++;
q =p +i;
Lab di Informatica - Prof. F. Calefato
Aritmetica dei puntatori
Sia a un array di interi e i un intero
int a[10];
int i;
Allora
a[i] *(a + i)
Perch?
Lab di Informatica - Prof. F. Calefato
4/10/2013
15
Array e puntatori: perch equivalenti
Lab di Informatica - Prof. F. Calefato
Esempio 1/2
Due funzioni:
input_array()
print_array ()
Input della dimensione
Allocazione:
cast a (int *)
dim interi
Chiamata di inputarray
scanf sul puntatore p
incremento di p
void input_array (int *, int);
void print_array (const int *,
int);
void main(void) {
int *a;
int dim;
printf (Che dimensione?);
scanf (%d,&dim);
a =(int *) calloc ( dim, sizeof(int) );
input_array (a, dim);
print_array (a, dim);
free (a);
}
void input_array(int *p, int size) {
int i;
for (i=0; i <size; i++) {
printf (a[%d]=, i);
scanf (%d, p +i);
}
}
Lab di Informatica - Prof. F. Calefato
Base +
spostamento con
il puntatore (p+i)
cast a int*
4/10/2013
16
Esempio 2/2
Chiamata di
print_array()
La stampa di ogni
elemento
stampa lintero puntato
da p e poi incrementa il
puntatore
La memoria allocata
liberata
free(a);
main() {
int *a;
int dim;
printf (Che dimensione?);
scanf (%d,&dim);
a =(int *) calloc (dim, sizeof(int));
input_array (a, dim);
print_array (a, dim);
free (a);
}

void print_array (const int *p, int size) {


int i;
for (i=0; i <size; i++)
printf ( a[%d]=%d\n, i, *(p+i) );
}
Lab di Informatica - Prof. F. Calefato
Quindi
E corretto scrivere?
int* p;
int b[10];
p =b;
p[0] =100;
Lab di Informatica - Prof. F. Calefato
4/10/2013
17
Vettori con procedure e funzioni
Un vettore pu essere passato come parametro o restituito come valore di
ritorno
In C un array non pu essere passato per valore ma solo per indirizzo
Es.
char s[MAX] =ciao\n;
stampa(s);
void stampa(const char* str)
Se si restituisce un array con una funzione, esso deve essere stato
allocato dinamicamente con malloc()/calloc()
Es.
char* crea_stringa(char a, char b, char c) {
char* s =(char*) calloc(4, sizeof(char));

return s;
}
Lab di Informatica - Prof. F. Calefato
Esercizio 5
Completare lesempio precedente della
funzione
char* crea_stringa(char a, char b, char c)
Dimostrarne la correttezza attraverso un
opportuno caso di test CUnit
Lab di Informatica - Prof. F. Calefato
4/10/2013
18
Esercizio 6 per casa
Scrivere una funzione int conta_parole(const
char* str) che conta le parole separate dagli
spazi in una stringa
Come distinguere lo spazio dagli altri caratteri???
Suggerimento: cercate nelle librerie standard del C
Dimostrarne la correttezza con un opportuno
caso di test CUnit
Lab di Informatica - Prof. F. Calefato
string.h
Libreria di funzioni da includere per le
operazioni pi comuni tra stringhe
Contiene funzioni per:
Copiare una stringa
Concatenare due stringhe in una
Misurare la lunghezza di una stringa
etc.
Lab di Informatica - Prof. F. Calefato
4/10/2013
19
Alcune funzioni di string.h
char *strcat ( char *s1, const char*s2)
concatena s2 a s1 e restituisce s1.
Lo spazio in s1 deve essere sufficiente a contenere la stringa
concatenata
int strcmp (const char *s1, const char *s2)
confronta le stringhe e restituisce un intero =0 se sono uguali
<0 se s1 precede s2, >0 se s1 segue s2
char *strcpy (char *s1, const char *s2)
copia s2 in s1 e restituisce s1 (dopo la copia)
Lo spazio in s1 deve essere sufficiente
int strlen(const char *s1)
restituisce la lunghezza di s1
Lab di Informatica - Prof. F. Calefato
Esercizio 7
Create dei programmi a scelta che facciano
uso di
strcat
strcpy
strcmp
strlen
Dimostrarne la correttezza attraverso opportuni
casi di test CUnit
Lab di Informatica - Prof. F. Calefato
4/10/2013
20
Strutturazione di un progetto in CDT
In C un progetto non pu avere pi
di una definizione di funzione main ()
Occorre creare due progetti distinti,
uno con il main CUnit per il test, uno
con il main "classico"
Struttura corretta a 3 progetti
1. Progetto libreria (statica) di funzioni
2. Progetto main CUnit
3. Progetto main classico
Lab di Informatica - Prof. F. Calefato
1. Creazione progetto libreria
Lab di Informatica - Prof. F. Calefato
4/10/2013
21
2. Creazione progetto CUnit (1/3)
Creare normalmente
un progetto
Utilizzare il file
main_cunit_template.c
fornito con le dispense
Aggiungere il progetto
di libreria tra le
references del
progetto Cunit
(necessario per
Eclipse)
Lab di Informatica - Prof. F. Calefato
2. Creazione progetto CUnit (2/3)
Aggiungere il progetto di libreria tra le
references del progetto CUnit (GCC)
Lab di Informatica - Prof. F. Calefato
4/10/2013
22
2. Creazione progetto CUnit (3/3)
Lab di Informatica - Prof. F. Calefato
3. Creazione del progetto Main classico
Rieseguire i medesimi passi compiuti per
configurare il progetto CUnit
Lab di Informatica - Prof. F. Calefato
4/10/2013
23
Esercizio 8 per casa
Scrivere un insieme di funzioni su array
dinamici di interi che effettuino:
linput e loutput
la ricerca del minimo e del massimo
la somma degli elementi
Le funzioni devono essere modularizzate in un
modulo con rispettivi file .h e .c
Dimostrarne la correttezza attraverso opportuni
casi di test CUnit
Lab di Informatica - Prof. F. Calefato
puts & gets in <stdio.h>
scanf non adatta a leggere intere linee (che possono contenere
spazi bianchi, caratteri di tabulazione, etc.)
scanf (con formato %s) prevede come separatore anche il blank
(spazio bianco)
possibile soltanto leggere stringhe che non contengono spazi bianchi;
Per esempio
Nel mezzo del cammin di nostra vita, mi ritrovai per una selva oscura
Leggendo con:
char s1[80], s2[80];
scanf("%s", &s1); /* s1 vale "Nel" */
scanf("%s", &s2); /* s2 vale "mezzo" */
Esistono funzioni specifiche per fare I/O di linee:
gets (legge fino a '\n')
puts (scrive e aggiunge '\n')
Lab di Informatica - Prof. F. Calefato
4/10/2013
24
gets
E una funzione standard che legge una intera riga da input,
fino al primo carattere di fine linea ('\n', newline) e lassegna
a una stringa
gets(const char* str);
Assegna alla stringa str i caratteri letti.
Il carattere '\n sostituito (nella stringa di destinazione str) da '\0
Restituisce la stringa letta str o NULL in caso di fallimento
Esempio
dato linput:
Nel mezzo del cammin di nostra vita,
mi ritrovai per una selva oscura
char s[80];
gets(s);
s vale: "Nel mezzo del cammin di nostra vita,"
Lab di Informatica - Prof. F. Calefato
puts
E una funzione standard che scrive una stringa sull'output
aggiungendo un carattere di fine linea ('\n', newline)
puts(const char* str);
puts(s) equivalentea printf("%s\n", s);
Restituisce un intero non negativo in caso di successo, EOF in caso
contrario
Esempio:
char s1[80]="Dante Alighieri";
char s2[80]="La Divina Commedia";
puts(s1);
puts(s2);
stampa sullo standard output:
Dante Alighieri
La Divina Commedia
Lab di Informatica - Prof. F. Calefato
4/10/2013
25
MATRICI
Parte 2
Lab di Informatica - Prof. F. Calefato
Matrici (vettori multidimensionali)
Gli elementi di un vettore possono essere a loro
volta di tipo vettore:
Si parla di matrici
Ci limitiamo ai vettori bidimensionali e quindi a matrici
N x M (righe x colonne)
Sintassi matrice 2D
<tipo> <identificatore> [<costante>][<costante>] ;
Esempio
float mat[4][3];
Lab di Informatica - Prof. F. Calefato
4/10/2013
26
Matrici 2D
float M [20][30];
M un vettore di 20 elementi
ognuno dei 20 elementi a
sua volta un vettore di 30 float
Accesso alle componenti:
il primo indice denota la riga
il secondo la colonna
M [0][0] =7.1 ;
M [1][29] =0.5 ;
M [19][29] =-1.99 ;
M [0] rappresenta il primo
vettore di 30 float (la prima
riga)
Lab di Informatica - Prof. F. Calefato
7.1
0.5
-1.99
Inizializzazione di matrici
Anche nel caso di vettori multi-
dimensionali linizializzazione si
pu effettuare in fase di
definizione
Esempio:
int matrix[4][4] ={ {1,0,0,0},
{0,1,0,0},
{0,0,1,0},
{0,0,0,1} };
Si pu anche omettere il numero
di righe
int matrix[][4]={{1,0,0,0},
{0,1,0,0}, {0,0,1,0}, {0,0,0,1}};
Non sono ammessibili
dichiarazioni:
int matrix[4][]=
int matrix[][]=
La memorizzazione
avviene per righe
Lab di Informatica - Prof. F. Calefato
4/10/2013
27
Matrici e typdef
Come al solito, possiamo usare typedef per
definire lalias del nuovo tipo di dati matrice
bidimensionale
Es
typedef int matrice [MAX_RIGHE] [MAX_COL]
matrice m1, m2;
Lab di Informatica - Prof. F. Calefato
Esercizio 9
Creare un tipo matrice di interi 2 x 3
Avvalorare la matrice da tastiera
Stampare la matrice
Stampare la somma totale dei numeri inseriti
nella matrice
Lab di Informatica - Prof. F. Calefato
4/10/2013
28
Riferimenti
Vittorio Scarano, Puntatori e stringhe
www.dia.unisa.it/~vitsca/LAB/lezione07l.pdf
La sezione sulle matrici contiene materiale
proveniente dalle lezioni del corso di
Programmazione di Michele Colajanni
Lab di Informatica - Prof. F. Calefato