Compound types (CAP 4)

Transcript

Compound types (CAP 4)
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Strings
Strutture
Puntatori
Strutture
Puntatori
Outline
Compound types (CAP 4)
Gli Array
Alberto Garfagnini
Le Stringhe
Università degli studi di Padova
24 Novembre 2010
Le Strutture
I puntatori
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Gli Array
• Tipo composito che può contenere diversi valori dello stesso tipo
• Ogni valore è immagazzinato in un elemento separato dell’array
• Il calcolatore mantiene tutti i valori in zone contigue di memoria
Strings
La creazione di Array
• Creo un array con 4 elementi:
• primo elemento seasons[0]
• ...
• ultimo elemento seasons[3]
int seasons[4];
[0]
[1]
[2]
[3]
Sintassi di dichiarazione di un array
Tipo di dato
numero di elementi
TypeName arrayName[arraySize];
nome dell’array
Esempio
short months[12];
float loans[20];
// crea un array con 12
// elementi di tipo short
// 20 elementi di tipo float
TypeName arrayName[arraySize]
• arraySize può essere:
una costante intera
una espressione variabile
const int size = 4;
wine[size];
double wine[8*sizeof(int)];
ma NON è lecita una variabile il cui valore cambia run-time
int dim = 3;
double boxes[dim];
Outline
Arrays
Strings
Strutture
Puntatori
// arrayone.cpp - Lavora con piccoli arrays di interi
#include <iostream>
int main( )
Output del programma:
{
Total yams: 8
using namespace std;
Il pacchetto 2 costa 20
int yams[3];
Costo totale: 500
yams[0] = yams[1] = 2;
Dimensione array: 12 bytes
yams[2] = 4;
Un elemento: 4 bytes
int yamcost[3] = {20, 30, 100};
cout << "Total yams: " << yams[0]+yams[1]+yams[2] << endl;
cout << "Il pacchetto " << yams[0] << " costa "
<< yamcost[0] << endl;
int total_exp = yams[0]*yamcost[0] +
yams[1]*yamcost[1] + yams[2]*yamcost[2];
cout << "Costo totale: " << total_exp << endl;
Outline
Arrays
Strings
Strutture
Array: regole di inizializzazione
• Si può inizializzare un array soltanto in fase di definizione.
• Esistono varie regole:
int cards[4] = {3,6,8,10};
Standard: tutti gli elementi
specificati
int Tips[4] = {3, 1};
Lista parziale: gli elementi
non specificati sono posti
uguale a zero
char cards[] = {’H’,’u’,’u’};
ArraySize non specificata: il
compilatore determina le
dimensioni at compile-time
cout << "Dimensione array: " << sizeof yams << " bytes" << endl;
Inizializzazioni non permesse
cout << "Un elemento: " << sizeof yams[0] << " bytes" << endl;
return 0;
Tips[4] = {1, 2, 3, 4};
Tips = cards;
}
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Stringhe C-style
• Sono array di char
• L’ultimo carattere della stringa è il NULL byte ’\0’ (ASCII code: 0)
char cat[] = {’a’,’b’,’c’,’\0’}; // a string.
char dog[] = {’a’,’b’,’c’};
// not a string!
• Il NULL byte serve per capire dove terminare la stringa
// manca il tipo
// No!
Strings
Strutture
Produce
cout << " cat[] : " << cat
<< endl;
cat[] : abc
Il codice
Produce
cout << " dog[] : " << dog
<< endl;
dog[] : abc@úÿÿÿ
• cout continua a interpretare i byte in memoria come char fino al
primo NULL byte che incontra
Puntatori
Stringhe: utilizzo della memoria
• Modo più conveniente per inizializzare una stringa:
char bird[10] = "Robin";
char fish[]
= "Salmon";
• Le stringhe costanti includono automaticamente un NULL byte per
terminare la stringa
bird[0]
Il codice
Puntatori
R
bird[9]
o
b
i
n
\0
\0
\0
\0
\0
aggiunto auto- aggiunti in fase
maticamente di inizializzazione
S
fish[0]
a
l
m
o
n
\0
fish[6]
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Inizializzazione di Stringhe
Strings
Strutture
Puntatori
Es: utilizzo di stringhe come array di char
// strings.cpp - C-strings
#include <iostream>
#include <cstring>
Una stringa costante non è equivalente ad un carattere costante
Come ti chiami? Luca
Ciao Luca
Il tuo nome ha 4 caratteri
int main( )
{
using namespace std;
const int Size = 15;
char nome[Size];
char bird = ’R’; // corretto
• Assegna correttamente alla variabile bird, il carattere
costante ’R’
Come ti chiami? Luca Corti
Ciao Luca
Il tuo nome ha 4 caratteri
char fish = "R"; // illegale
• cin può essere utilizzato per
• "R" rappresenta una stringa costante:
cout
cin
cout
cout
<< "Come ti chiami
>> nome;
<< "Ciao " << nome
<< "Il tuo nome ha
<< strlen( nome )
<< " caratteri."<<
return 0;
è composta da due caratteri: ’R’ e ’\0’
char insect[] = "R"; // corretto
// array di 2 caratteri
• "R" indica l’indirizzo di memoria dove è immagazzinata la
stringa
? ";
<< endl;
"
endl;
}
acquisire stringhe, ma
ignora tutti i caratteri
whitespace che precedono
il testo (spazi, tabs o caratteri
newline)
ferma la lettura al primo
carattere whitespace
successivo
• strlen( ) ritorna la dimensione della stringa immagazzinata nell’array
(esclude nel computo il NULL character)
Outline
Arrays
Strings
Strutture
Puntatori
Es: lettura di più stringhe
#include <iostream>
int main( )
{
using namespace std;
const int Size = 25;
char nome[Size], nick[Size];
cout << "Come ti chiami ? ";
cin >> nome;
cout << "Nickname ? ";
cin >> nick;
cout << "Ciao " << nome << endl;
<< "Il tuo nickname e’: "
<< nick << endl;
return 0;
}
Luca\0
nome
Corti
input
buffer
Corti\0
Strings
Strutture
Puntatori
• il C++ fornisce un metodo per cin, cin.getline( )
• permette di acquisire una linea intera inclusi i caratteri di whitespace
all’inzio e in mezzo al testo, fino al carattere di terminazione new-line
const int SIZE = 80;
char name[SIZE], city[SIZE];
cout << "Inserire un nome: ";
cin.getline( name, SIZE );
cout << "Inserire una citta’: ";
cin.getline( city, SIZE );
cout << "Ciao: " << name << endl;
cout << "Abiti a: " << city << endl;
nick
• cin utilizza whitespace (space | tab | newline) per delimitare una stringa:
• legge la prima stringa e la inserisce nella variabile nome
• la seconda stringa rimane nell’input buffer e viene incamerata dalla
successiva chiamata a cin
Arrays
Line-Oriented input with getline( )
Come ti chiami? Luca Corti
Nickname ?
Ciao Luca
Il tuo nickname e’ Corti
Luca
Outline
Inserire un nome: John Doe
Inserire una citta’: New York
Ciao: John Doe
Abiti a : New York
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Line-Oriented input with get()
Arrays
Strings
Strutture
Puntatori
Line-Oriented input with get( ): example
• La classe istream definisce il metodo, get( ), con diverse forme.
Eccone alcune (dal file header istream)
• int get( );
Extracts a character from the stream and returns its value (casted to an
integer).
• istream & get( char * c, streamsize n);
Extracts characters from the stream and stores them as a C-string into
the array beginning at s. Characters are extracted until either (n - 1)
characters have been extracted or the delimiting character ’\n’ is
found.
If the ’\n’ character is found, it is not extracted from the input
sequence and remains as the next character to be extracted.
#include <iostream>
int main()
{
const int SIZE = 80;
char name[SIZE];
cout << "Inserire un nome: ";
cin.get( name, SIZE );
cin.get( );
Inserire un nome: John Doe
Inserire una citta’: New York
Ciao: John Doe
Abiti a : New York
char city[SIZE];
cout << "Inserire una citta’: ";
cin.get( city, SIZE ).get( );
• istream & get( char * c, streamsize n, char delim);
Same as above, except that the delimiting character is the one specified
in delim instead of ’\n’.
cout << "Ciao: " << name << endl;
cout << "Abiti a: " << city << endl;
}
• una possibilità è chiamare cin.get(char *, streamsize) e
successivamente cin.get( ) per rimuovere il carattere di fine linea.
• È possibile concatenare due member functions:
cin.get( city, SIZE ) ritorna l’oggetto cin
che a sua volta invoca get( )
Outline
Arrays
Strings
Strutture
Puntatori
La funzione cin.get( char )
• A volte è comodo leggere un solo carattere dalla tastiera
• Utilizzando
char ch;
cin >> ch
non è possibile inserire uno <spazio> o il solo carattere
ENTER.
• Il metodo cin.get( char c ) legge un qualsiasi carattere,
inclusi i caratteri di whitespace
char ch;
cout << "Press ANY KEY to continue";
cin.get( ch );
cout << "Process restored" << endl;
Press ANY KEY to continue [ENTER]
Process restored
Outline
Arrays
Strings
Strutture
Puntatori
Input tra tipi diversi
cout << "Quanti anni hai ? ";
int eta;
cin >> eta;
cin >> eta;
cin.get( );
cout << "Dove abiti ? ";
char indirizzo[80];
cin.getline( indirizzo );
cout << "Riepilogo dati:" « endl;
cout << "Eta’: " « eta « endl;
cout << "Citta’: " « indirizzo « endl;
Quanti anni hai? 18
Dove abiti ? Padova
Riepilogo dati:
Eta’ : 18
Citta’ : Padova
Quanti anni hai? 18
Dove abiti ? Riepilogo
dati:
Eta’ : 18
Citta’ :
• Non si riesce ad inserire l’indirizzo!
• cin >> eta lascia il carattere \n nella input queue
Outline
Arrays
Strings
Strutture
Puntatori
Outline
La classe string
#include <string>
• Inizializzazione:
string str = "Chimica";
char c_string[] = "Fisica";
string str1 = c_string; // copio C-string
• Si può usare cin per l’input:
cin >> str;
• E visualizzare contenuto con cout:
" << str1;
• È possibile accedere ai singoli caratteri della stringa con la
notazione ad array:
cout << "Carattere iniziale:
Outline
Arrays
Strings
Puntatori
Operazione su stringhe: std::string vs char[]
const int N = 132;
char cstr1[N], cstr2[N];
string str1, str2, str3;
• Copiamo una stringa
C++ strings:
• Semplice assegnazione:
str2 = str1;
C strings:
• Funzione di libreria:
Outline
Arrays
strcpy( cstr1,
str3 = str1 + str2; //join
str1 = str1 + str2; //append
Strings
Strutture
Puntatori
str1 += " bianca";
strcat( cs1, " nera" );
• Concateniamo due stringhe
• Usiamo l’operatore +:
Puntatori
// strtype3.cpp - operazioni su stringhe
#include <iostream>
#include <string> // classe string
#include <string> // definizioni per C-style strings
int main( )
{
using namespace std;
char cs1[30], cs2[30] = "pantera";
string str1, str2 = "tigre";
str1 = str2;
strcpy( cs1, cs2 );
cstr2 );
C++ strings:
Strutture
Dammi due animali feroci ? leone pantera
Ecco le belve: giaguaro leone pantera
Prima lettera di leone : l
Prima lettera di pantera : p
" << str[0];
Strutture
Strings
// string.cpp - Utilizzo classe string
#include <iostream>
#include <string>
int main( )
{
using namespace std;
char ani_1[30] = "giaguaro", ani_2[30];
string str;
cout << "Dammi due animali feroci ? ";
cin >> ani_2 >> str
cout << "Ecco le belve: ";
cout << ani_1 << " " << ani_2 << " " str << endl;
cout << "Prima lettera di "<< ani_1 << " : " ani_1[0] << endl;
cout << "Prima lettera di "<< str << " : " str[0] « endl;
return 0;
}
• È parte delle librerie standard del C++ (namespace std)
• Le definizioni della classe sono nel file header string
cout << "La mia materia preferita:
Arrays
int len_s = str1.size( );
int len_c = strlen( cs1 );
C strings:
cout << "La stringa ¨
" << cs1 << "¨ ha "
<< len_c << " caratteri " << endl;
• Funzione di libreria:
La stringa "pantera nera" ha 12 caratteri
strcat( cstr1,
cstr2 );
cout << "La stringa ¨
" << str1 << "¨ ha "
<< len_s << " caratteri " << endl;
return 0;
}
La stringa "tigre bianca" ha 12 caratteri
Outline
Arrays
Strings
Strutture
Puntatori
Outline
string : la funzione getline( )
Arrays
spazio sufficiente per contenere l’informazione
char site[10] = "casa";
strcat( site, "di Aldo" ); // memory problem!
string name, city;
cout << "Inserire un nome: ";
getline( cin, name );
cout << "Inserire una citta’: ";
getline( cin, city );
cout << "Ciao: " << name << endl;
cout << "Abiti a: " << city << endl;
site[0]
c
a
site[9]
s
a
Inserire un nome: John Doe
Inserire una citta’: New York
Ciao: John Doe
Abiti a : New York
Strings
Strutture
Puntatori
• Con le stringhe std::string non c’e’ bisogno di controllare che
ci sia spazio a disposizione per lo storage
• Utilizzando gli array di char bisogna controllare sempre che ci sia
spazio sufficiente per contenere l’informazione
char site[10] = "casa";
strncat( site, "di Aldo", 10 ); // + sicuro
Outline
a
s
a
Arrays
a
d
i
c
a
s
a
\0
\0
d
i
A
l
d
o
\0
Strings
A
Strutture
• Le strutture sono dei tipi composti, definibili dall’utente
• possono contenere tipi di dati diversi tra loro
• It’s a two-process step:
1. create the structure description
define and label the different data types
2. instantiate a structure data object
tag = name for the new type
struct wine_bootle
{
char name[40];
int anno;
double prezzo;
};
l
• Se la stringa da copiare è più lunga, aggiungere il NULL byte:
site[9] = ’\0’;
site[0]
\0
Il tipo structure
site[9]
s
\0
site[9]
keyword
a
\0
• La stringa sconfina intaccando zone contigue di memoria
Possibili errori con C-style strings (2)
c
\0
site[0]
c
site[0]
Puntatori
• Utilizzando gli array di char bisogna sempre controllare che ci sia
whitespace all’inzio e in mezzo al testo:
Arrays
Strutture
Possibili errori con C-style strings (1)
• funzione analoga per le stringhe del C
• permette di acquisire una linea intera inclusi i caratteri di
Outline
Strings
struct
members
site[9]
d
i
A
\0
• wine_bottle a; crea un oggetto di tipo wine_bottle
• tramite il l’operatore di appartenenza . si acccede agli elementi della
struttura:
• a.name, a.anno e a.prezzo
Puntatori
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Strings
Strutture
Puntatori
Structure properties
#include <iostream>
#include <cmath>
Structures = User Defined Types
struct complex {
double re;
double im;
};
// A complex number
// type definition
complex x = {1.0, 2.0}, y;
y = x;
It is possible to
1. use the assignement operator (memberwise assignment)
Program output
int main( )
{
using namespace std;
z = 3 + 4.6i
complex vec[2] = { {1.,2.}, {0.,2.} };
cout << vec[1].re;
|z| = 5.49181
complex x = { 2.0, 1.1 };
complex y = { 1.0, 3.5 };
2. define arrays of structures
double real_part( complex x) {
return x.re;
}
complex z;
z.re = x.re + y.re;
z.im = x.im + y.im;
3. pass structures to functions
cout << " z = " << z.re << " + " << z.im << "i" << endl;
cout << "|z| = " << sqrt(x.re*x.re + y.re*y.re) << endl;
4. define a function that returns a structure
return 0;
}
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
complex unity( ) {
complex a = {1.0, 1.0};
return a;
}
Strings
L’operatore &
Strutture
I puntatori
• Determina la locazione di memoria di una variabile che identifica
un tipo semplice o composto
• Sono un tipo speciale: contengono una locazione di
memoria
Esempio di programma:
int donuts = 6;
cout << "donuts: " << donuts;
cout << "indirizzo: " << &donuts;
double cups = 4.5;
cout << "cups: " << cups;
cout << "indirizzo: " << &cups;
Output del programma:
donuts: 6 indirizzo: 0xbf9afaa4;
cups: 4.5 indirizzo: 0xbf9afa98;
Sintassi
tipo al quale punta
typeName * nomePuntatore;
nome del puntatore
Esempi di puntatori (1)
short * pin;
double * misure;
string * name;
// punta a uno short
// punta a un double
// punta a una stringa
Puntatori
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Esempio di utilizzo di puntatori (1)
// punt.cpp - Utilizzo dei puntatori
#include <iostream>
int main( )
{
using namespace std;
double cup = 5.3;
double * pd = & cup;
cup:
*pd:
&pd:
cup:
Strings
Strutture
Puntatori
Esempio di utilizzo di puntatori (2)
// punt.cpp - Utilizzo dei puntatori
#include <iostream>
int main( )
size
{
size
double cup = 5.3;
size
double * pd = & cup;
size
...
5.3 &cup: 0xbf8f9160
5.3 pd:
0xbf8f9160
pd:
0xbf8f9160
0xbf8f915c
12.3 &cup: 0xbf8f9160
of
of
of
of
size of
// creo un puntatore e lo inizializzo
cup: 8
pd: 4
mug: 2
pi: 4
(long long *): 4
cout << "size of cup: " << sizeof cup << endl;
cout << "size of pd: " << sizeof pd << endl;
cout << "cup: " << cup << " &cup: " << &cup << endl;
cout << "*pd: " << *pd << "
pd:
" << pd;
cout << " &pd: " << &pd << endl;
short mug = 7;
cout << "size of mug: " << sizeof mug << endl;
*pd = 12.3;
cout << " cup: " << cup << " &cup: " << &cup << endl;
short * pi = & mug;
cout << "size of pi:
return 0;
" << sizeof pi << endl;
cout << "size of (long long *):
return 0;
}
" << sizeof (long long *) << endl;
}
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Dichiarazione e inizializzazione di puntatori
• Un puntatore contiene sempre una locazione di memoria:
⇒ occupa la stessa dimensione per tutti i tipi
• Con l’operatore * davanti a un puntatore si accede al
contenuto della zona di memoria a cui punta
Strings
Strutture
Gli operatori new e delete
• L’operatore new permette di allocare memoria all’interno di un
programma durante l’esecuzione (run-time)
• Sintassi:
typeName * nomePuntatore = new typeName;
Inizializzate sempre un puntatore prima di usarlo!
• L’operatore delete libera la memoria allocata (da new)
• Sintassi:
Esempio
long * d;
cout << " d: " <<
*d = 7; // BOOM!
int * pi = new int; // spazio per un intero
double * pd = new double; // e per un double
delete nomePuntatore;
d; // random memory
d : 0x8048819
Segmentation fault
delete pi; // libera spazio dell’ intero
delete pd; // e del double
Puntatori
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Gli operatori new e delete per gli arrays
Strings
Strutture
Puntatori
Esempio : utilizzo di new con arrays
• Con l’operatore new possiamo creare nuovi array con dimensioni
// dynarr.cpp - New con arrays
#include <iostream>
int main( )
{
using namespace std;
cout << "Dimensione array: " << endl;
int n;
cin >> n;
conosciute soltanto durante l’esecuzione
• Sintassi:
typeName * nomePuntatore = new typeName[size];
int * pi = new int[500]; // array di 500 int
double * pd = new double[7]; // e di 7 double
Dimensione array: 3
3.2
10.75
-23.2
la media è: -9.25
// Creo un array per contenere le n misure
double * data = new double[n];
• L’operatore delete libera la memoria allocata (da new)
double mean = 0.0;
for (int i=0; i<n; i++) {
cin >> data[i];
mean = (data[i] + i * mean) / (i + 1);
}
• Sintassi:
delete [] nomePuntatore;
delete [] pi; // libera spazio degli interi
delete [] pd; // e dei double
cout <<
"la media è: " << mean << endl;
return 0;
}
Outline
Arrays
Strings
Strutture
Puntatori
Outline
Arrays
Aritmetica dei puntatori
Strings
Strutture
Differenza array/puntatori
• Aggiungere una unità ad un puntatore significa incrementare di una unità la
locazione di memoria alla quale punta
• L’incremento tiene conto del numero di bytes occupati dal tipo del puntatore
Puntatori a double
-1.5 | -1.5 3.0
long double a[3] = {-1.5L, 3.0L, 5.5L};
3.0 | -1.5 3.0
long double *pld = &a[0];
cout << *pld << " | " << a[0] << a[1] << endl;
pld++;
cout << *pld << " | " << a[0] << a[1] << endl;
• ∃ una sottile differenza:
1. una variabile puntatore può assumere indirizzi differenti;
2. il nome di un array è un puntatore fissato (costante)
• Le seguenti espressioni non sono valide
const int N = 10;
int a[N], *p;
Puntatori a char
char c[3] = {’A’,’B’,’C’};
char *pch = c;
cout << *pch << c[0] << c[1] << endl;
pch++;
cout << *pch << c[0] << c[1] << endl;
AAB
BAB
• Nome array ≡ locazione di memoria primo elemento ⇒
& a[0] ≡ a
a = p;
// ILLEGALE
++a;
// ILLEGALE
a += 2;
// ILLEGALE
Puntatori