In questa pagina verranno inseriti, di volta in volta, gli appunti presi a lezione al corso di Programmazione (Teoria) tenut dal prof.Paolo Boldi.
Sono appunti presi in classe e forniti, almeno all'inizio, solo riletti e corretti. Verranno poi inseriti, gradualmente, gli appunti ampliati con l'inserimento di riferimenti e note utili, nella loro forma “finale”.
Essendo, comunque, appunti presi a lezione non sono sicuramente perfetti (almeno nel rilascio iniziale) e non vogliono avere la pretesa di essere un punto di riferimento per lo studio.
Spero siano utili, pertanto, per effettuare confronti con il materiale personale e soprattutto a coloro che non hanno potuto seguire una qualunque lezione di teoria.
Chiunque, in qualunque momento, potrà ampliare gli appunti o modificarli nel caso in cui non risultassero corretti e, in uno spirito di piena collaborazione, creare materiale “guida” nello studio della programmazione Java con l'ausilio del wiki, strumento “fondamentale”, gestito dal prof. A.Trentini.
Per qualunque problema con gli appunti non esitate a contattarmi: giovanni.lombi(@)studenti.unimi.it
NB Dispongo degli appunti di tutte le lezioni, ma all'inizio sono stati presi in formato cartaceo. Spero di riuscire a renderli disponibili a breve sul wiki. -
Gli appunti verranno riportati tutti di seguito in modo da poterli stampare in una volta sola e farne una raccolta. E' possibile, comunque, scaricarli singolarmente dai link disponibili nella tabella, in formato odt (Openoffice) e/o pdf.
| .odt | ||
|---|---|---|
| Mese | Date | Date |
| Ottobre | - | - |
| Novembre | - | - |
NB Per problemi di carico ftp gli appunti verranno, all'inizio, resi disponibili solo sul wiki. A breve inserirò tutti i file per permettervi di scaricarli singolarmente.
for(int riga=1; riga <=10;riga=riga+1){
out.println(“qui ci va la tabellina del “+riga”);
}
for (int m=1; m<=10; m=m+1){
Out.print(m*riga);
out.print(“ “);
}
Out.println();
“\n” = A capo – Introduce la sequenza di escape (Dentro le virgolette del print)
“\t” = Carattere di tabulazione (tab)
“\\” = Stampa la \
“ \” ”= Stampa le virgolette
For (….) {
While {
For {
---break---
}
}
}
Break uscirà solo dal ciclo for interno (Il break esce DA UN SOLO CICLO)
Int x, somma;
somma=0;
do {
x=in.readInt();
if(x==0) break;
if(x%2==1) continue;
somma=somma+x;
} while (true);
out.println (somma);
Se x=0 interrompe l’esecuzione e stampa;
Se x è dispari il continue forza l’esecuzione del ciclo e reinizia da capo.
ESPRESSIONI
Frammento di codice Java dotato di un “tipo” e un “valore”
Tipo= decidibile staticamente (dal compilatore)
Valore= decidibile dinamicamente (solo eseguendo il programma)
X+y è un espressione fatta mettendo insieme due variabili con il segno +. Int
X+3 è un’espressione che coinvolge una sola variabile Int
3+7 è un’expr che coinvolge due costanti Int
(x+y)*x = Due sottoespressioni Int L’espressione intera è Int
x/y è un’expr omogenea Int
##
Int x, y;
double d;
(x+y)+d
L’espressione non è omogenea perché coinvolge due tipi diversi di variabili. In java questo non è accettabile e automaticamente il compilatore effettua una “promozione di tipo”, pensando il valore int come se fosse con la virgola (uniformandone il tipo alla variabile x).
(int+double)+double = double
##
La valutazione di un’espressione può modificare il contenuto di qualche variabile. (SIDE EFFECT)
Int x,y;
x+y; Tipo= Int
x=y Tipo=Int
La differenza tra ler due espressioni è che la prima non ha effetti collaterali, la seconda si.
La prima fa la somma e da il risultato. La seconda assegna ad x il valore di y (effetto collaterale che assegna il valore di destra alla variabile di sinistra)
Int x,y;
X=(y=1) L’effetto collaterale è l’assegnamento di un valore ad x.
##
Int x,y,z;
x=1;
y=2;
z=(x=y+1)*3; L’espressione ha due effetti collaterali (due assegnaz. Alle variabili)
##
Int x,y,z;
x=5;
y=3;
z= (x=x+3) – (y=y+1);
[Si riesce facendo le 3 scatoline e valutando pezzo per pezzo]
[x] 15
[y] 4
[Z] 11
##
Int x;
x=3;
x= (x=x+x)*(x=x+x) (x=6)*(x=12) x=72
X= 72
##
Operatori
Senza effetti collaterali + - * / %
Con effetti collaterali =
X+=espressione (>) x= x+espressione
Int x,y,z;
x=5;
y=7;
z= (x+=y+1)*y;
R z=91
Autoincremento /Autodecremento
X++ o ++x Incrementano x di 1 ma hanno valori diversi: Se i ++ sono dopo della variabile l’assegnamento avviene prima dell’incremento (alla variabile viene assegnato il valore “vecchio” non incrementato”).
x—o –x Decrementano x di 1
##
Int x,y;
x=5;
y= x++
R x=
## ù
In x,y,z;
x=3;
y=4;
z= x++ + ++y
R z=8
##
Exercizi
Z= ++x + ++x
Z=(x+ =x++) *(x-= - -x)
Z=(x*=x++ + ++x) * x++
##
Double d;
int x,y;
x=7;
y=2;
d= x/y;
Sx double = dx int (Divisione tra due variabili int Divisione intera)
Il valore messo in d è 3.0 ma abbiamo perso tutto quello dopo la virgola perché la divisione è intera.
Se vogliamo prendere anche le cifre decimali d=(x+0.0)/y oppure d=x/(y+0.0)
Soluzione più elegante è il “cast” = Forzatura di tipo:
d= (double)(x)/y n[Il tipo per il cast va dichiarato prima del richiamo variabile – Java può fare forzature implicite]
GLI OGGETTI
(Classe>) Oggetti Forniscono dei servizi (METODI) descritti nella documentazione.
(Ogni oggetto è istanza di un oggetto [esempio] )
Insieme al jdk si installa la documentazione (API standard) Fondamentale per costruire in java
Variabili JAVA sono
↘Tipo Primitivo es Int, double, byte, short, long, boolean, float
↘Tipo Riferimento Tutte le altre e servono a manipolare gli oggetti. Non contengono valori ma riferimenti agli oggetti.
##
ConsoleOutputManager out; >[Variabile di tipo riferimento. CosoleOuputManager è una classe di prog.io.*]
out=new ConsoleOutputManager(); >[Invocazione di costruttore – New fa nascere l’istanza della classe]
out.println (“Cia padrone”); >[Out=Oggetto Target (a cui chiediamo un servizio) . Nome del metodo (Argomento met)]
NB LE variabili di tipo riferimento non contengono direttamente il costruttore ma in qualche modo il suo “’indirizzo”.
Classe
Costruttori
Metodi
CLASSE
Nome: Frazione
Pacchetto: prog.utili
Documentazione: Descrizione della classe
Dati importanti perché ogni volta che vogliamo usare una classe la dobbiamo importare seguendo le direttive di importazione.
Import <pacchetto>.<classe>;
↘Significato: Intendo usare questa classe che si trova nel pacchetto.
Import <pacchetto>.*;
↘Significato: intendo usare una classe che si trova nel pacchetto
Alcuni pacchetti sono, però, forniti dalla SUN. Tra questi c’è java.lang che non va importato perché questa operazione avviene automaticamente (esempio: string). In questo caso all’inizio del sorgente va inserita una dorettiva di importazione.
COSTRUTTORI
Frazione (int x, int y) [x e y sono “nomi dei parametri formali”]
Questo costruttore costruisce la funzione x/y
↘Segnatura del costruttore che spiega come si invoca il costruttore stesso. Tra parentesi () elenco dei componenti per invocarlo (quanti argomenti e di che tipo).
Frazione f;
f=new Frazione (5,7);
La variabile f crea un collegamento alla classe Frazione che contiene i parametri assegnati. In questo caso il costrutto usa 2 argomenti perché le variabili sono 2.
Frazione f,g;
f=new Frazione (5,7);
g=new Frazione (3*15, 5*7+1); [Creiamo la frazione 45/36 5/4]
f=g;
↘g è un ALIAS di f perché in questo preciso istante f e g fanno riferimento alla stessa classe.
F alla fine sarà ORFANO perché f e g si riferiscono TUTTE E DUE ad un'unica classe, g. Gli oggetti orfani vengono conservati in memoria per un certo periodo ma, in assenza di memoria, Java li eliminerà attraverso il “Garbage Collector” (spazzino).
Frazione (int x)
Questo costruttore costruisce la frazione x/1
Frazione f,g;
f=new Frazione (7); [Java riconosce l’invocazione al secondo costruttore perché c’è un solo argomento]
###
Frazione f,g;
f=new Frazione (7);
g=new Frazione (4/5);
h=new Frazione (20/25);
f [ ] [ 7/1 ] g [ ] [ 4/5 ] h[ ] [ 20/25 ] [ 4/5 ]
Quando due variabili riferimenti si riferiscono allo stesso oggetto sono ALIAS, ma se due variabili di riferimento si riferiscono a due oggetti DIFFERENTI ma con lo STESSO CONTENUTO non sono ALIAS perché non si riferiscono allo stesso oggetto.
ESEMPI ED ERRORI
g=new Frazione (); ERRORE
g=new Frazione (3.7); ERRORE perché passo come argomento un double e non un int
g=new Frazione (CIAO); ERRORE perché passo una stringa al posto degli int
g=new Frazione (4,5); Posto in un punto del codice crea una nuova frazione che rimane li finchè non viene cancellata dal Garbage Collector.
###
Vogliamo un programma che legge due variabili e crea un riferimento alla classe Frazione (legge numeratore e denominatore).
[…]
Int num,den;
num=in.readInt(“Numeratore? “);
den=in.readIn(“Denominatore? “);
Frazione f;
f=new Frazione (x,y);
[…]
METODI
Int getNumeratore()
getNumeratore() = Segnatura univoca del metodo (Come si chiama il metodo + quanti e quali argomenti vuole tra parentesi)
int = Tipo restituito
Segnatura + Tipo restituito = Prototipo del metodo
↘Restituisce il numeratore della frazione su cui è invocato
In x;
x=f.getNumeratore();
Se l’utente ha inserito una frazione già semplificata la x sarà uguale al numero inserito. Se invece ha inserito una frazione non semplificata questa verrà semplificata e riproposta .
Frazione piu (Frazione f)
Restituisce una nuova frazione ottenuto sommando f al Target.
[…]
Int num,den;
num=in.readInt(“Numeratore? “);
den=in.readIn(“Denominatore? “);
Frazione f1, f2, ris;
f1=new Frazione (num,den);
num=in.readInt(“Numeratore? “);
den=in.readIn(“Denominatore? “);
f2=new Frazione (num,den);
ris=f1.piu (f2);
// ↘f1 è la frazione Target – f2 è la frazione che verrà sommata al target
out.println(f1 ” + “ +f2+ “ = “+ris);
[…]
OSSERVAZIONI
↘Se scriviamo f1.piu(f2) l’operazione somma viene eseguita ma non verrà assegnato il valore a nessuna variabile rendendo il metodo orfano.
↘Se scriviamo f1=f1.piu(f1) l’operazione verrà eseguita e il valore verrà inserito in f1. F1 ora sarà riferito al valore inserito e non più all’oggetto originario che, essendo orfano, primo o poi verrà spazzato via.
###
Creare un programma che chiede all’utente quante frazioni vuole sommare e poi somma le n frazioni richiedendole all’utente.
int n;
Frazione somma;
n=in.readInt(“Quante frazioni? “);
somma= new Frazione (0);
for(int i=0; i<n; i++) {
int num=in.readInt(“Num? “);
int num=in.readInt(“Den? “);
frazione f=new Frazione (num, den);
somma=somma.piu(f);
}
Out.println(“La somma è “+somma);
###
Se volessi fare la media scrivo:
frazione pippo=new Frazione (n);
frazione media = somma.diviso(pippo);
↘Perché l’argomento della classe Frazione deve essere una frazione.
###
Altro metodo per fare la media.
Frazione media=somma.diviso(new Frazione(n));
↘Passiamo al metodo diviso una frazione creata a volo e istantaneamente poi la buttiamo via (al termine della sua utilità).
boolean isMaggiore (Frazione f)
↘Essendo boolean restituirà true o false.
Restituisce treu se e solo se il target è maggiore di f.
boolean isMinore (Frazione f)
↘Funziona come il metodo di sopra ma con l’operatore minore al posto del maggiore.
###
Scrivere un programma che richiede una frazione (numeratore e denominatore) all’utente e dopo gli dice se è maggiore di 10.
Int a, b;
a=in.readInt(“Dammi il numeratore “);
b=in.readInt(“Dammi il denominatore “);
Frazione f=new Frazione (a, b);
Frazione dieci=new Frazione (10);
if (f.isMaggiore(dieci))
out.println(“La frazione è maggiore di 10”);
else
out.println(“La frazione non è maggiore di 10”);
SEMPLIFICHIAMO
Int a, b;
a=in.readInt(“Dammi il numeratore “);
b=in.readInt(“Dammi il denominatore “);
Frazione f=new Frazione (a, b);
if (f.isMaggiore(new Frazione(10))
out.println(“La frazione è maggiore di 10”);
else
out.println(“La frazione non è maggiore di 10”);
SEMPLIFICHIAMO ULTERIORMENTE
Int a, b;
a=in.readInt(“Dammi il numeratore “);
b=in.readInt(“Dammi il denominatore “);
if (new Frazione(a,b).isMaggiore(new Frazione (10)))
out.println(“La frazione è maggiore di 10”);
else
out.println(“La frazione non è maggiore di 10”);
###
ESERCIZI x CASA
Calcolare un programma che prende frazioni fino a quando l’utente immette 0 (codice tappo) e calcola:
Media aritmetica
Media armonica
boolean equals(Frazione f)
↘Scrivere if (f==g) sarebbe errato perché vede solo se f e g si riferiscono allo stesso metodo.
↘Scrivere boolean equals(Frazione f) è giusto perché confronta il contenuto!!!
↘>= <= < > possono essere usati solo su valori primitivi
String toString()
↘Scrivendo out.println() noi invochiamo implicitamente lo String out.println(f.toString())
NB In java esiste l’OVERLOADING che è un fenomeno per cui possono coesistere tanti metodi con lo stesso nome MA CHE richiedono PARAMETRI DIVERSI.
Esercizio
Stampare un quadrato con bordi composti da asterischi della dimensioni NxN con N input chiesto all'utente.
Int n=in.readInt(“Intero? “); // Chiede un intero all'utente
A
for(int i=0; i<n;i++){
out.print(“*”);
out.println();
}
for(int i=o;i<n-2;i++) {
out.print(“*”);
for(int j=0;j<n-2;j++);
out.print(“ “);
out.println(“*”);
}
A
for(int=0; i<n;i++){
out.print(“*”);
out.println();
}
Creare un triangolo di asterischi con i due cateti come riga e colonna di N asterischi con N numero dato dall'utente.
*******
******
*****
****
***
**
*
Int n=in.readInt(“Intero? “);
A
for(int i=0; i>n;i--){
for(int j=0;j<i;j++)
out.print(“*”);
out.println();
Creare un programma che stampa una X come segue:
(Esempio con inserimento 5)
* *
* *
*
* *
* *
CLASSE STRING
Pacchetto: java-lang (Non va importato)
String s;
S=”ciao”; ## Letterale stringa
↳ Potremmo scrivere anche S=new String(“ciao”)
int lenght()
Esempio:
s=”ciao”
out.println(s.length()) ## Stampa la lunghezza di s (In questo caso 4)
Cosa succede in memoria?
S [ ] → Chiedo alla stringa a cosa fa riferimento e quello diventa l'argomento del print lasciando la prima stringa orfana.
##
toLowerCase() → Prende la stringa trasformando tutte le lettere in minuscole
toUpperCase() → Prende la stringa trasformando tutte le lettere in maiuscole
String st;
s=in.readline();
t=s.toLowerCase();
out.println(t);
Utente inserisce Paolo Boldi;
S ha un riferimento alla Stringa “Paolo Boldi”;
Java mi restituisce una copia IDENTICA ma con tutte le lettere minuscole;
↳Abbiamo due diverse stringhe: una con riferimento alla stringa originale, una con riferimento alla stringa ottenuta con toLowerCase().
##
String concat(String s); ## Concatena stringhe
String s,t,u;
s=”*“;
t=”*”;
u=s.concat(s);
↳Stampa **
C'è un'eccezione al metodo generale di invocazione per questa classe:
s=s+s
##
Ci sono due tipi di metodo:
Di ispezione → Invocati per avere informazioni ma che non cambia la stringa
Di mutazione → Invocati per avere informazioni. Cambiano il contenuto della stringa.
String è una classe IMMUTABILE, perchè non ha metodi che cambiano il contenuto delle stringhe.
Leggere un intero e stampare, usando opportunamente ciclo for e concat, numero N asterischi (con n=intero inserito dall'utente).
Int n=in.readInt(“Intero”);
String s=””;
for(int i=0;i<n;i++)
s=s+”*”; //Invocazione metodo concat
out.println(s);
Con la classe concat si creano stringhe nuove... Ma c'è molto dispendio di memoria. Per evitare tutto ciò si usa:
String substring(int from)
NB in java ogni stringa ha i caratteri numerati da 0. L'ultima lettera, quindi, sarà la n-1 esima lettera.
s=”ciao mamma”;
t=s.substring(3);
Vedere anche:
String substring(int from, int to)
##
Altra classe importante è la classe indexOf (Grande varietà)
int indexOf(String needle) ## Cercare qualcosa in una stringa grande
→ Usandola cerchiamo la prima occorrenza nella stringa
Se cerchiamo in ciaociao l'occorrenza ao la classe ci indica l'indice della prima occorrenza uguale. (Troverà il sottolineato).
Per cercare qualcosa dal un punto in particolare (specificato con l'indice opportuno) si usa:
int indexOf(String needle, int from);
##
Scrivere un programma con la seguente specifica:
Chiede all'utente di inserire un indirizzo – Indirizzo email? (nomeutente@provider.ext)
Il programma deve scrivere Ciao, NOMEUTENTE! (Nome utente UpperCase)
String indirizzo=in.readline(“Indirizzo?”;
int pos=indirizzo.indexOf(“@”); // Mi restituisce la posizione della @
String.nome=indirizzo.substring(0,pos); // Taglia la stringa dalla posizione 0 alla chiocciola excl
Per avere i caratteri tutto in maiuscolo sostituiamo l'ultima riga con:
String.nome=indirizzo.substring(0,pos).toUpperCase();
Per aumentare la sicurezza (fare inserire per forza la chiocciola)
##
http://www.ds.unimi.it/corsi/programmazione/index.html
Protocollo://<host>/<percorso></...>/<file.ext>
Scrivere un programma con le seguenti specifiche:
Protocollo:
Host:
Path:
File:
(Senza usare index of ma cercando la prima occorrenza : per separare protocollo e host)
Ci sono delle variabili che differiscono da int etc...
La variabile CARE contiene un solo carattere (una stringa è un insieme di carattere” e si indica tra singoli apici (' '). Le virgolette limitano costanti STRINGA.
Http://www.pippo.org/corsi/programmazione/syllabus.html (url esercizio)
String url=in.readln();
int pos = url.indexOf(':');
// Cerca i due punti e rende il protocollo Maiuscolo
String prot=url.substring(0,pos).toUpperCase();
//
int posBarra = url.indexOf('/', post3);
//
String host=url.substring(post3,posBarra)
//
pos=url.lastIndexOf('/');
//
string file=url.substring (pos+1);
//String path=url.substring (posBarra, pos+1)
###
TIPI PRIMITIVI
Sono 8 e si dividono in:
-Tipi numerici
-Tipi numerici interi (la differenza tra le varie classi dipende dalla grandezza dei valori)
byte (1 byte) (Numeri rappresentabili: da -27 fino a 27 -1 = -128>127)
short (2 byte) (-2 15 a 215-1)
int (4 byte)
long(8 byte)
-floating point (Numeri con la virgola, la differenza è la precisione)
float
double
-Tipo primitivo char (caratteri) (occupa 1 byte)
-Tipo primitivo boolean (Boleani) (Restituiscono solo TRUE o FALSE) (Occupa 2 byte)
Parliamo dei numerici interi
Se abbiamo
int x;
long l;
l+x sarà una variabile di tipo long (Tra tipi misti prevale il tipo più grande - Promozione)
x=l+x Non è consentito (Non permette i declassamenti se non espressamente dichiarati)
>>x=(int)(l+x); (Così è consentito – Abbiamo effettuato un cast di declassamento)
l=(long)(x+1); E' un cast di promozione (NB Non si cambia la variabile. Prendiamo un espressione che ha un certo valore e la pensiamo come un tipo diverso) – Non si fa quasi mai perchè java lo fa automaticamente.
E' possibile scrivere una costante in valore esadecimale ponendo “0x” davanti al numero.
Ad esempio: 0xa1 = 161
E' possibile scrivere una costante in valore esadecimale ponendo “0” davanti al numero.
Ad esempio: 066 = 54
ATTENZIONE A NON PORRE 0 DAVANTI AI NUMERI IN BASE DIECI (Verrebbero trasformati in base ottale)
Se vogliamo scrivere una costante molto grande possiamo inserire una “L” dopo il numero:
54 000 000 000 L
Non è quasi mai necessario ma semplifica di molto le operazioni del compilatore.
Parliamo dei floating point
float (4 byte)
double (8 byte)
NB Le costanti double si scrivono con il “.” non con la “,” e quindi le costanti con il “.” non possono essere definite come float.
Es. 3.12 -1.7 3E+5 7.82E-12 0.000000078
Possiamo usare il “.” nei float con le seguenti modalità:
float f;
f=(float((3.14);
opp
f=3.14F
int somma, n;
double media;
media=somma/n // Media= double - Somma e n =Int → Complessivamente = int
//Abbiamo perso le cifre dopo la virgola
Possiamo ovviare scrivendo
media=(double)(somma)/n // double e somma=double – n=int
opp
media=somma/(double)(n)
opp
media=(double)(somma)/(double)(n)
opp
media=(somma+0.0)/n
Non possiamo invece scrivere
media=(double)(somma/n)
SELEZIONE MULTINARIA
selettore switch → int / char / boolean
switch (<espressione>) {
case <espress> : <istr>;
<istr>;
....
break;
case <espress> : <istr>;
break;
[default: <istr>;
...; ] // [ ] usate come BNF =Questa espressione può non esserci
}
Flussi possibili:
Espressione corrisponde ad uno dei case → Raggiunto il break si va al termine
Espressione non corrisponde ad uno dei case → Si va alla condizione di default
NB Break importantissimi!
Si può usare la funzione switch anche così:
switch (x) {
case 1:
case 2:
case 3:
...
break;
case 4:
case 5:
...
###
Contare le vocali, le consonanti e tutti gli altri caratteri:
String s=in.readLine();
int voc,cons,altr;
voc=cons=altr=0;
for (int i=0; i<s.lenght(); i++)
[*] Parte sviluppata con gli if e con uno switch
Con gli IF
if (s.carAt(i)=='a' || s.charAt(i)=='e' || s.charAt(i)=='i' || ... avanti con o / u)
voc ++;
else
if (s.charAt(i)>= 'a' && s.CharAt(i)<='z')
cons++;
else
altr++;
Con lo SWITCH
switch (s.charAt(i)) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u': voc++;
break;
case 'b':
case 'c':
case 'd':
cons++
break;
default: altr++;
}
###
Scrivere un programma con le seguenti specifiche:
Leggere un numero da 1 a 19 e restituire lo stesso espresso in lettere.
Intx=in.readInt(“Dimmi”);
switch (x) {
case 1: out.println(“uno”);
case 2: out.println(“due”);
...
case 19: out.println(“diciannove”); break;
default: out.println(“Troppo!”;
}
Il pezzo di sopra ci servirà anche per stampare i numeri da 1 a 99.
int x=in.readInt(“Dimmi ? “;
if (x>19) {
switch (x/10) { // dividendo la x per 10 avremo la prima cifra per l'approssimaz di java);
case 3: out.println(“venti”);
case 2: out.println(“trenta”);
...
case 9: out.println(“novanta”); break;
}
x=x%10; // Mette in x quello che avanza dalle decine
}
C'è un problema. Ventuno sarà scritto ventiuno, trentuno verrà scritto trentauno etc
Vedo se x vale 1 o 8. Se ha questi valori tolgo l'ultima vocale.
CLASSI INVOLUCRO (Wrapper)
byte → Byte
short → Short
int → Integer
long → Long
double → Double
char → Character
boolean → Boolean
Le otto classi si trovano nel pacchetto java.lang (stesso di String)
Set s=new Hash Set ();// Creo insieme vuoto
s.add(“Paolo”); // Aggiungo elemento
s.add(“Maria”); //Aggiungo elemento
if (s.contains(“Giulio”))
//Esempio che al momento non è possibile capire appieno
In java è possibile operare con gli “insiemi” (matematicamente parlando”.
Funziona anche con le frazioni
Set s=new Hash Set ();// Creo insieme vuoto
s.add(“frazione...”); // Aggiungo elemento
s.add(“frazione...”); //Aggiungo elemento
if (s.contains(“...”))
Funziona anche così.. Ma non se vogliamo inserire dei tipi primitivi... E' un grosso problema, e per ovviare la Sun ha inserito le classi involucro. A questo punto possiamo inserire anche i tipi primitivi nel codice come segue:
Set s=new Hash Set ();// Creo insieme vuoto
s.add(“new Integer (12)”); // Aggiungo elemento
s.add(“new Integer(14)”); //Aggiungo elemento
if (s.contains(“Integer (3,2)”))
In java5 è stato inserito il boxing/unboxing. Da Java5 (tiger) la conversione viene effettuata automaticamente (boxing automatico).
Integer x,y, z;
x=3 ; → x=new Integer (3);
y=5; → z=new Integer (x intValue()+yintValue())
METODI STATICI
target.nome(argomenti)
s.substring(3.5).toUpperCase();
target |.|nome |args
Target: Sempre un oggetto (Costante, variabile o oggetto descritto da un'altra involcazione di metodo)
Metodi di istanza VS Metodo statico: La differenza è che i secondi si invocano su una classe a differenza dei primi che si invocano su un oggetto.
Metodi statici:
<nome di una classe>.<nome>(argomenti)
###
Classe Math (java lang)
Contiene solo metodi statici per effettuare operazioni matematiche come il logaritmo, la radice quadrata, etc.
Es.
static double sqrt(double x)
(Per indicare un metodo statico inserisco davanti alla stringa “static”)
Es. double x=Math.sqrt(5.7)
Vi sono anche
static double log(double x) // Logaritmo
static double abs(double) // Prende un double e restituisce un double
static int abs(int x) //Uguale al superiore ma prende un int e restituisce un int
static int max(int x, int y) //Prende due interi e restituisce l'intero maggiore
→ int i=Math.max(a,b);
etc...
###
Rif alle Espressioni (inserire in quel contesto)
Operatore ternario
<condizione>?<espr1>:<espr2>
Java valuta la condizione e vede se è vera o falsa. Se è vera viene valutata la prima espressione, se è falsa la seconda.
Es.
i= a>b?a:b;
Se a maggiore di b → valore di i=a
Se a minore di b → Valore di i=b
Es.
x=(a+b>c?a+1:b)*5
Java valuta prima a+b>c. Se la condizione è verificata valuta a+1, altrimenti valuta b. Alla fine moltiplica il risultato per 5.
Ponendo a=3 ; b=5; c=8
Il risultato sarà x=25
Con gli stessi valori il risultato della seguente espressione:
x=(a++>--b?a+1:b-1)*a
sarà: x=12
###
Integer
static int parseInt(String x)
Es.
int x;
x=Integer.parseInt(“12”);
//Trasforma la seguenza di caratteri 1 2 in numero intero.
###
Scrivere un programma con le seguenti specifiche:
-Chiedere una data nel formato gg/mm/aaa;
-Stampare data nel formato gg mese aaaa (Con il mese scritto in lettere).
String s=in.readLine(“Data? “); //Leggo la stringa data
int posPrimaBarra=s.indexOf(“/”);
int posSecondaBarra=s.lastindexOf('/');
String sGiorno=s.substring(0,posPrimaBarra);
String s.Mese=s.substring(posPrimaBarra+a,posSecondaBarra);
String sAnno=s.substring(posSecondaBarra+1);
int g,m,a;
g=Integer.parseInt(sGiorno);
m=Integer.parseInt(sMese);
a=Integer.parseInt(sAnno);
String nomeMese;
Switch (m) {
case1: nomeMese=”gennaio”;
case2:....
case12: nomeMese=”dicembre”;
}
out.println (g+” “+nomeMese+” “+a);
###
Character
static boolean isDigit(char c) //Guarda se il carattere passato è una cifra
isLetter // Guarda se il carattere è una lettera
isLowerCase // Guarda se il carattere è minuscolo
isUpperCase // Guarda se il carattere è maiuscolo
###
Per un informatico calcolare la data si utilizza come riferimento l'”epoca”, ovvero la mezzanotte del 1/1/1970.
###
Scrivere un programma con le seguenti specifiche:
-Calcolare quanti giorni sono passati dal 1° gennario 1970 ad oggi tenendo conto del febbraio bisestile.
-Stampare il giorno della settimana per la data corrente
Int x=0;
x+=g-1; // Il -1 è relativo al giorno 1/1/1970 che non deve essere conteggiato
for (int i=1; i<m; i++)
switch (i) {
case 11:
case 4:
case 6:
case 9: x+=30; break;
case 2: x+=a%4==0? 29:28; break;
default: x+=31;
}
for (int i=1970; i<a; i++)
x+=i%4==0? 366:365;
[...]
switch (x%7( {
case 0: out.print(“giovedì”); break;
case 1: out.print(“venerdì”); break;
[..]
}
###
ESERCIZIO
Scrivere un programma con le seguenti specifiche:
-Leggere un intero dall'utente corrispondente al numero di giorni passati dall'”epoca” e stampare la data.
###
IMPORTAZIONE STATICA
Integer.parseInt(...)
Math.log(...)
Da java 5 in poi, importando il metodo nello script, questo si potrà usare senza dichiarazione:
Es:
import static java.lang.Math.log; //Importiamo il metodo logaritmo
Nello script, da questo momento, possiamo usare il metodo come segue
log(3.7);
log(32):
[...]
###
Calcolo “scarto quadratico medio”
LA media, da sola, è poso significativa. Lo scarto qadratico medio è uno dei metodi per verificare la dispersione dei valori.
(RIF wikipedia)
Introduciamo, per questo, gli ARRAY (Vettori, da non confondere con i vector di Java)
<tipo>[ ]<id>;
ovvero <int/double/String etc> [vuote]<nome>
es. int [ ] x
Sintassi alternativa <tipo> <id> []
es. int x [ ]
Gli array in Java sono considerati come riferimenti. Ciò significa che x non conterrà l'array ma punterà ad esso.
Dichiarazione di array (non si specifica, per ora, la grandezza dell'array)
es. int [ ] x;
Creazione
es. x=new int[15];
→ Se creo un nuovo array (es x=new int[20] il primo riferimento verrà eliminato e il primo array dventerà orfano)
Gli elementi dell'array si chiama x[o] (x di 0), x[1], x[2],...,x[n-1] Quindi è come se, creando un'array, dichiarassi tante variabili del tipo specificato quanto è grande l'array stesso. (Nell'esempio di prima sono 15 variabili di tipo int, da x[0] a x[14])
Rif. Vedi comportamento con le frazioni.
[...] ARRAY
Ricordiamo:
int [ ] x;
Creazione array (es): x=new int[100] // creazione di un array di 100 elementi
x.lenght //Attributo che restituisce il numero di elementi della x
Es. Creare una semplice agenda telefonica con le seguenti specifiche:
-Chiede quanti nomi inserire? [20]
-Nome? [Paolo Boldi]
-Numero? 347485966624
-Funzione di ricerca //Es inserisce Bold e l'output sarà Paolo Boldi → 347485966624
Chi vuoi cercare?
°°°Prima parte – Inserimento contatti°°°
Fissati i nomi per gli Array → Nome; Numero
int n=in.readInt(“Quanti nomi? “);
String [ ] nome, numero;
nome=new String[n];
numero=new String[n];
for (int i=0;i<n;i++){
nome[i]=in.readLine(“Nome? “);
numero[i]=in.readLine(“Numero? “);
}
°°°Seconda parte – Funziona di ricerca°°°
String query;
do{
query=in.readLine(“Chi vuoi cercare? “);
int i;
for (i=0; i<n; i++)
if (nome[i] soddisfa la query)
break;
if(i<n)
out.println(nome[i]+”->”+numero[i]);
else
out.println(“Nessun numero corrispondente”);
}while (query.lenght>0);
// Se si dovesse cercare ESATTAMENTE LA STRINGA INSERITA dall'utente possiamo usare:
nome[i].equals(query)
nome[i].equalsIgnoreCase(query) → Ignora il case
nome[i].indexOf(query)>=0 //Restituisce la posizione della prima occorrenza
nome[i].toLowerCase().indexOf(query.toLowerCase() )
//Possiamo fare automaticamente il toLowerCase:
String query=in.readLine(“Chi vuoi cercare? “).toLowerCase();
ALTRA SOLUZIONE (Array sovradimensionato)
String[] nome, numero;
nome=new String[1000];
numero=new String[1000];
int n=0;
while (n<1000){
String x=in.readLine(“Nome? “);
if (x.equals(“”)) break;
nome [n]=x;
numero[n]=in.readLine(“Numero? “);
n++;
}
[...]
###
Scrivere un programma con le seguenti specifiche:
-(Tassazione):
--Chiede all'utente di inserire il reddito
---Stampare le imposte da versare secondo il seguente specchietto:
R<10000 0%
10000<= R <= 50000 20%
50000<= R <=100000 40%
100000<R 100%
2 array:
1)Fino a che importo devo pagare la cifra (10000 – 50000 – 100000 – infinito) - Scaglione
2)L'importo da pagare (0 -20 – 40 – 100) - Aliquota
°°°Prima soluzione:°°°
[...]
double[ ] scaglione
double [ ] aliquota
// Supponiamo che gli array siano stati creati e riempiti con i valori di sopra
double reddito=in.readDouble(“reddito? ”);
int i=0;
while (reddito>=scaglione[i]) i++;
while tasse=reddito*aliquota[i];
[...Stampa...]
//Se mettiamo i valori percentuali (0%, 20 etc) bisogna cambiare l'ultima riga in:
while tasse=reddito*aliquota[i]/100;
°°°Seconda soluzione:°°°
[...] // Usando gli inizializzatori di array
double[ ] scaglione={10000,50000,100000,Double MAX_VALUE} // fino al val max dei double
double [ ] aliquota={0,20,40,100}
// Supponiamo che gli array siano stati creati e riempiti con i valori di sopra
double reddito=in.readDouble(“reddito? ”);
int i=0;
while (reddito>=scaglione[i]) i++;
while tasse=reddito*aliquota[i];
###pg 210 Pighizzini
prog.utili
Classe “Rettangolo”
Costruttori:
Rettangolo (double b, double h)
//base e altezza sono DISTINTE, quindi un rettangolo di b=5 e h=7 è DIVERSO da un rettangolo di b=7 e h=5
Metodi:
double getBase()
double getAltezza()
//Non hanno argomenti
double getArea()
double getPerimetro()
//Per il confronto di perimetro e area di rettangoli
boolean haAreaMaggiore(Rettangolo r)
boolean haPerimetroMaggiore(Rettangolo r)
→ Restituisce vero o falso, essendo un booleano
//Prende come argomento un rettangolo e restituisce un booleano (true se l'altezza è uguale)
boolean equals(Rettangolo r)
//Stampa dimensione rettangolo nella forma base=7, altezza=5
String toString()
E' una classe IMMUTABILE; dopo aver inserito i dati possiamo ricevere informazioni ma non cambiarle.
Ex:
Scrivere un programma con le seguenti specifiche:
-Legge base e altezza del primo rettangolo
-Legge base e altezza del secondo rettangolo
-Stampa quale dei due ha area maggiore
Rettangolo r1,r2;
double base=in.readDouble(“Inserire base: “;
double altezza=in.readDouble(“Inserire altezza: “);
r1=new Rettangolo(base,altezza);
r2=new Rettangolo(base,altezza);
if(r1.haAreaMaggiore(r2))
out.println(r1);
else
out.println(r2);
//Usando, invece, l'operatore ternario, avremmo:
Rettangolo rettMax
rettMax=r1.haAreaMaggiore(r2)? R1:r2;
out.pruntln(rett Max);
Nota: Information hidding = Uno degli ingredienti fondamentali nella programmazione ad oggetti. La maggior parte delle volte, infatti, viene invocato un metodo e usato tranquillamente senza sapere “come svolge” la sua funzione. In questo modo, l'uso del metodo rimane invariato anche se svolge sempre lo stesso ruolo ma “facendo i calcoli” in maniera differente.
###
Ex: Scrivere un programma con le seguenti specifiche:
Chiedere all'utente quanti rettangoli vuole inserire;
Leggere base e altezza per n volte (con n=numero specificato dall'utente);
Calcolare la media delle aree;
Stampare le caratteristiche del rettangolo “Medioide”.
(Il medioide è il rettangolo la cui area si avvicina di più alla media delle aree di tutti i rettangoli)
double media=0;
int m=in.readInt(“Quanti rettangoli? “);
Rettangolo[ ] r=new Rettangolo [n];
for (int i=0;i=<n;i++){
double b=in.readDouble(“Base? “);
double h=in.readDouble(“Altezza? “);
r[i]=new Rettangolo(b,h);
media+=r[i].getArea()
}
media/=n;
Supponiamo che il medioide sia il primo elemento dell'array
int indCandidato=0; //Candidato medioide
double distCandidato=Math abs(r[0].getArea()-media);
for (int i=1;i<n,i++){
double dist=Math abs(r[i].getArea()-media);
if(dist<distCandidato){
indCandidato=i;
distCandidato=dist;
}
}
//Se devo solo stampare il candidato
out.println(r[indCandidato]);
Per evitare la duplicazione della condizione al di fuori e dentro il ciclo riscrivo il codice:
int indCandidato=Double.MAX_VALUE; //Candidato medioide
double distCandidato=Math abs(r[0].getArea()-media);
for (int i=1;i<n,i++){
double dist=Math abs(r[i].getArea()-media);
if(dist<distCandidato){
indCandidato=i;
distCandidato=dist;
}
}
### Pighizzini pg 181
CRIVELLO DI ERATOSTENE
2 3 4 5 6 7 8 9 10 11 12 13 14
x x x x x x
dove x=Numero primo (Sul wiki dipende dalla formattazione. Se non visualizzate correttamente le x incolonnate i numeri primi, nel nostro caso, sono naturalmente: 2,3,5,7,11,13)
Partiamo dal primo numero e cancelliamo tutti i suoi multipli
2 3 5 7 9 11 13
Sempre con la stessa operazione eliminiamo i multipli del
2 3 5 7 11 13
Alla fine avremo i numeri primi nell'intervallo considerato.
{Vedere animazione in fondo alla pagina}
La seguente animazione è utilissima per capire la procedura:
//Per problemi di upload media l'immagine verrà caricata a breve//
\\
Voglio creare un array che mi dice che ogni particolare numero di un intervallo considerato è già stato considerato. Lo faccio usando un boolean.
Int n=in.readInt(“Fino a che valore? “);
boolean[ ] criv=new boolean[r+1];
for (int x=2, x<=n, x++){
if (criv[x]) continue;
for(int y=2*x;x=n;y+=x)
criv[y]=true; //Il ciclo considera i multipli e li fa uscire dal crivello
}
//Stampiamo solo gli elementi settati a false (restati, quindi, nel crivello)
for (int x=2;x<=n;x++)
if (!criv[x])
out.println(x)
//Assunto che false=sta ancora nel crivello
###
ToDo @ Home
p1,p2,p3...pn =Sequenza dei numeri primi
Costruire n rettangoli come segue:
Si ha un numero di valori primi...
Rettangolo 1= b=p1 ; h=p2
Rettangolo 2= b=p2; h=p3
etc...
Int x=in.readInt(“Giorni? “);
int a=1970;
int= durata=365;
while (x-durata>0){
x-=durata;
att;
durata=a%4==0?366:365;
}
int m=1;
durata=31;
while (x-durata>0){
x-=durata;
m++
switch (m){
case 11:case 4:case 6:case 9: durata=30;break;
case 2: durata=a%4==0?29:28;break;
default: durata=31
###
Scomposizione di un numero in fattori primi:
-Chiedere numero
-Scomporre in fattori primi
Numero? 120
2^3 * 3^1 * 5^1
int n=in.readInt(“Numero? “);
boolean array [ ] criv=new boolean [n+1];
for(i=2; i>=n;i++){
if(criv[i]) continue;//Restituisce true quindi =true
for(j=2*i;i<=n;j+=i)
criv[j]=true;
}
for (i=”; i<n;i++){
if (criv[i]) continue;
if(n%i !=0) continue;
int x=0;
while (n%i==0){
x++;
n/=1;
}
out.print(i+”^”+x + “\t”);
}
Facciamo ora in modo che, invece di fornire l'input, l'utente può scrivere, per lanciarlo, “java Nomefile n” (con n = numero input) e avere direttamente l'esecuzione del programma con n come input.
ARGOMENTI ADDIZIONALI sulla riga di comando
Es: java Divisori 120 130 22 98
Il programma verrà eseguito normalmente e resituirà il risultato uscente dai valori 120, 130, 22 e 98.
public static void (String[ ] arg){
if (arg.lenght!=1){
out.println(“Dovevi darmi un argomento!”);
return;
}
int n=Integer.parseInt(arg[0]); //Converte la stringa in numero
###
TODO@Home
Scrivere programma per la stringa “Palindromi” ma leggendo una stringa non come readline ma presa sulla riga di comando. Inserire, inoltre, un controllo per le stringhe (si può inserire un solo parametro oppure eseguire il programma per ognuno dei parametri)
###
POLIMORFISMO
Esiste una classe “Medico” le cui istanze sono i vari medici, in particolare i vostri medici di famiglia:
Es. //Diagramma UML // il + davanti = pubblici
Medico
+double controlloPressione(Paziente p|
+certificato certificatoSRC(Paziente p) //Immaginando esista una classe certificato
↑^↑
(Dermatologo ha tutti i metodi di Medico ma non viceversa)
Dermatologo
Void curalaPiaga(Paziente p,Piaga x)
Un'applicazione è, ad esempio:
|Rettangolo| ← |Quadrato|
###
Classe quadrato
Costruttori: Quadrato(double l); //Prende in esame il lato
Metodi:
double getLato()
String toString()
“lato=<dimensione>”
Supponiamo di dichiarare una variaile “Rettangolo” di nome r: Rettangolo r; . In ogni istante la variabile r può avere un riferimento alla classe Rettangolo o ad una qualunque sottoclasse della classe Rettangolo. Tale proprietà è chiamata POLIMORFISMO.
A ← B
Una variabile di tipo A può contenere istanze di tipo A oppure di tipo B. (Più in generale di qualunque sottotipo di A).
NB In ogni istante la variabile r conterrà istanze di quadrati o di rettangoli (o di qualunque altra sottoclasse di rettangoli). Si userà, da ora, come terminologia “classe” e quando verrà detto:
Tipo di r= variabile dichiarata
Classe = La classek di cui fa parte
es.
Rettangolo r;
r=new Rettangolo (5,6);
out.println (r); //Verrà stampato un rettangolo base 5 e altezza 6
r=new Quadrato(7); //Il riferimento precedente verrà eliminato e la prima classe sarà orfana.
Out.println(r); //Verrà stampato quadrato lato 7
Più in generale, quindi: dove è lecido usare un'espressione di tipo A è sempre lecito usare un'espressione di tipo B. [Se vi serve un medico va bene anche un dermatologo]
Rettangolo r1,r2;
r=new Rettangolo(7,9);
q=new Quadrato(12); // Lecita perchè Quadrato fa parte di Rettangolo (e ha qualche carat in +)
if(r1.haAreaMaggiore(q))...
//haAreaMaggiore vuole come argomento un Rettangolo. Per il POLIMORFISMO possiamo, però inserire un argomento Quadrato perchè la classe Quadrato è una sottoclasse di Rettangolo.
...
if(q.haareaMaggiore(r))
//La seconda chiamata ha senso e funziona ma per via dell'EREDITARIETA' perchè la sottoclasse eredita tutti i metodi della sovraclasse.
Ci sono cose che, sebbene sembrino lecite, non sono ammesse:
r=new Quadrato(7);
if(r getLato()>5)...
//Non si può fare...E il compilatore assume che sia stata usata la classe Rettangolo
###
Quali metodi posso invocare sulla variabile?
Dipendono dal tipo della variabile, non dalla classe
I metodi invocabili su una variabile dipendono dal suo tipo (dal tipo per cui la variabile è definita). Una volta invocato un metodo, viene eseguito la versione del metodo dipendente dalla classe (Sovrascrittura o Riscrittura dei metodi).
###
Scrivere un programma con le seguenti specifiche:
Chiedere all'utente di inserire un valore n (n figure)
Chiedere le misure di 20 figure
Chiedere le misure di base e altezza epr ogni figura
Se base e altezza sono diverse → Stampa rettangolo
Se base e altezza coincidono → Stampa quadrato
Usare gli array e stampare le figure nell'ordine di inserimento.
Int n=in.readInt(“Quante figure? “);
Rettangolo[ ] r=new Rettangolo[n];
for (int i=0;i<n;i++){
double b=in.readDouble(“Base ”;
double h=in.readDouble(“Altezza”);
if (b==h)
r[i]=newQuadrato(b);
else
r[i]=new Rettangolo(b,h);
}
for (int i=0;i<n;i++)
out.println(r[i].toString());
____
Da java 5 in poi esiste un nuovo modo per creare cicli for, soprattutto sugli array. Si chiama, a volte, FOREACH. Si scrive:
for (Rettangolo x:r)
out.println(x);
Dichiara la variabile x (con nome Rettangolo). In pratica lui scorre tutto l'array e setta la variabile x.
In questo caso, in realtà non si può usare, perchè con il FOREACH non possiamo scrivere nell'array ma solo utilizzare i dati già in esso.
Non possiamo nemmeno usarlo nel caso in cui esistano array paralleli perchè nella sua sintassi non c'è il numero di indice.
Altro caso è l'impossibilità di usarlo su cicli non continui (con i break).
###
Rettangolo r;
double x;
x=r.getLato() //NO ma si può fare un cast
x=((Quadrato)r).getLato() // Cast, convinciamo java che quello è un quadrato
###
Ci sono circostanze, abbastanza rare, in cui vogliamo sapere se in una classe c'è una determinata istanza.
Rettangolo r;
if (r instanceof Quadrato)
E' un operatore booleano che restituisce true se in quel momento nella classe rettangolo c'è un Quadrato.
Attenzione all'uso... Non può essere, invece, usata al contrario! Risulterebbe, infatti, TUTTI TRUE.
For (Rettangolo x:r){
if(x instanceof Quadrato)
out.print(“Q”);
else
out.print(“R”);
}
###
ARRAY MULTIDIMENSIONALI
int[ ] x | x[0] | x[1] | … | x[n-1] |
| x[0][0] | x[0][1] | x[0][2] |
| x[0][1] | x[1][1] | x[1][2] |
int[ ][ ] m;
m=new int[3][5]
Non c'è limite alla dimensione dell'array.. .Possono essere bidimensionali, tridimensionali, etc...
TODO@Home
Creare un programma con le seguenti specifiche:
-Sudoku
-Controlla che il sudoku sia stato svolto bene facendo inserire all'utente i dati in ogni casellina.
Risoluzione esercizio sudoku:
F: A → B
se f è iniettiva e |A|=|B| => f è suriettiva
La condizione “non ci sono ripetizioni su righe e su colonne” segue dalla condizione “su ogni riga e ogni colonna devono esserci tutti i numeri da 1 a 9”.
Controlleremo, per svolgere l'esercizio, che non ci siano ripetizioni.
Int[][] m= new int[9][9]
for (r=0;r<j;r++){
out.println(“Riga “+r);
for (c=0;c<9;c++)
in.readInt(“colonna “+c);
}
for (r=0;r<9;r++)
se la riga r contiene almeno una ripetizione
break;
if (r<9) {
out.println(”Non corretto alla riga “+r);
return;
}
___
°°°Altra soluzione°°°
Controlliamo che esistano due indici, i e j che contengano lo stesso valore.
Se capita di trovare due indici con lo stesso valore faccio un break.
R → | | | i=3| |j=3| |
Ɐi‡j
Controlliamo quindi, con un for, tutte le coppie tranne quelle di indici uguali
0,1 – 0,2 - ... - 0,8
-- - 1,2 – 1,3-...-1,8
-- - -- - 2,3-2,4-...-2,8
for (r=0;r=9;r++){
for (i=0;i<9;i++){
for(h=1;j<9;j++)
if(m[r][i]==n[r][j])
break;
if(j=9) break;
}
if (i<9) break;
//Bisogna ripetere il codice per le colonne con le opportune modifiche per gli indici, fissando la colonna e cambiando la riga...
Andiamo, ora, ad affrontare la questione dei “quadratoni”...
0
1
2
3
4
5
6
7
8
Il problema cambia... Il quadrato esteerno ha 9 celle, ognuna contente altre 9 celle... In ogni sottoquadrato devono esserci i numeri da 1 a 9 senza ripetizioni...
Ragionando:
q=Indica in quale quadrato grande mi trovo
i=Indica la posizione nel sottoquadrato
q/3 individuiamo il quadrato nelle righe grandi;
3*(q/3) Individuiamo la posizione nel quadrato
3*(q/3)+i/3 Individuiamo la posizione all'interno del sottoquadrato (Riga)
3*(q%3)+i%3 Individuiamo la posizione all'interno del sottoquadrato (colonna)
NB Prendete con le molle gli appunti su quest'ultima parte...Scrivere una sintesi della spiegazione è alquanto arduo e non rende l'idea essendo molto riduttivo...
______
TODO@Home
Poker!
-Un array di 5 per le carte (partendo dall'asso=1)
-Un array di 4 per il seme
-Il programma deve leggere le carte che ha in mano l'utente
--->Il programma deve indicare che punti ha.
###
STATIC TYPING
I metodi invocabili su un oggetto dipendono dal suo tipo.
DYNAMIC BINDING
La versione eseguita di ciascun metodo dipende dalla classe.
###Rif: Pag 232 Pighizzini
-Figura ← Rettangolo ← Quadrato
↑
Cerchio
°Cerchio (double raggio)
°double getRaggio()
°double getArea()
°double getPerimetro()
°boolean haAreaMaggiore(Cerchio c)
°boolean haPerimetroMaggiore(Cerchio c)
//Gli ultimi due confrontano il cerchio su cui sono stati invocati e il cerchio passato come argomento.
°boolean equals(Cerchio c) //Se i due cerchi hanno raggio uguale
°String toString()
“Raggio=...”
Gli autori delle classi Cerchio & Rettangolo/Quadrato hanno constatato che alcune classi sono comuni a tutti e tre. In realtà si può dire che queste classi sono più “generali” e applicabili a tutti e tre. Hanno quindi creato la sovraclasse “Figura” inserendo al suo interno le classi:
°[abstract] double getArea()
°[abstract] double getPerimetro()
°boolean haAreaMaggiore(Cerchio c) → Nella migrazione invece di prendere un cerchio come argomento prende una figura
↘boolean haAreaMaggiore(Figura g)
°boolean haPerimetroMaggiore(Cerchio c)
↘boolean haAreaMaggiore(Figura g)
°boolean equals(Cerchio f)
↘boolean equals(Figura f)
NB Nella lezione precedente abbiamo assegnato gli ultimi 3 alla classe Rettangolo. In realtà questi sono presenti nella classe “Figura”.
______
CLASSI ASTRATTE
1)Non sono istanziabili
2)Contengono metodi non implementati (astratti = abstract)
TODO@Home
Chiedere quante figure;
Chiedere che tipo di figura si vuole inserire per ogni volta;
A seconda dei casi inseriamo in un array i relativi dati (es. Rettangolo b e h);
Stampare i risultati.
###
Object
(Tutte le altre sono sue sottoclassi)
↑Figura ↑String ↑Frazione ↑...
↑Rettangolo
↑Quadrato
Quadrato è comunque una sottoclasse di Object (ad esempio) ma non diretta.
°Strng toString()
°boolean equals(Object x) è presente in ogni sottoclasse.
public class MyMath {
public statici nt mcd (int x, int y){
….
Return espressione;
}
}
// Richiamiamo:
int x=MyMath.mcd(12,25)
Riprendiamo la classe MyFrazione
public class MyFrazione {
private int num;
private int den;
###
Public MyFrazione (int x, int y){
Boolean isNeg=(x<0%%y>0)||(x>0&&y<0);
num=Math.abs(x);
den=Math.abs(y);
int R=MyMath.mcd(num, den);
num/=R;
den/=R;
if (isNeg) nume=-num;
}
###
Intestazione metodo:
public int getNumeratore(){
return }
Rispetto ad un metodo statico l’unica differenza è l’assenza di “static”.
Tutto quelloè che deve fare il metodo è restituire l’intero. Lo richiamiamo:
f.getNumeratore()
### - ###
Metodi per/diviso:
public MyFrazione per(MyFrazione f){
int nuovoNum=num*f.num; //Più efficiente che invocare un metodo
[opp: int nuovoNum=this.num*f.num;]
int nuovoDen=this.den*f.den;
MyFrazione risultato=new MyFrazione(nuovoNum,nuovoDen);
return ritultato;
}
}
// La frazione restituita è “nuova” ed è il risultato del prodotto della frazione su cui invocata per quella passata come argomento.
La semplificazione è fatta dal costruttore.
Richiamiamo con:
h=f.per(g); [dove h è la frazione su cui è invocata e g è la frazione passata come argomento)
###
x/y - x’/y’
La soluzione più veloce è:
(xy’+x’y)/(y y’)
In codice:
public MyFrazione per(MyFrazione f){
int nuovoNum=this.num*f.den+this.den*f.num;
int nuovoDen=this.den*f.den;
MyFrazione risultato=new MyFrazione(nuovoNum,nuovoDen);
return ritultato;
}
}
###
Scriviamo ora il metodo isMinore:
public boolean isMinore(MyFrazione f){
MyFrazione dif=this.meno(f);
return diff.isNegativa();
}
Return this.meno(f).isNegativa();
Possiamo trarre beneficio dal lavoro fatto fino ad ora:
public boolean isNegativa(){
return num<0;
}
In alcuni casi è utile rendere privati i metodi, soprattutto quando c’è la possibilità che questi siano modificati parzialmente e/o pericolosamente.
###
Metodo che confronta due frazioni:
public boolean equals (MyFrazione f){
MyFrazione diff=this.meno(f);
return diff.isZero();
associato al metodo:
private boolean isZero(){
return num==0;
}
###
Public String toString(){
Return den!=1? Num+”/”+den: String.valueOf(num);
}
ORDINAMENTO:
Int[] x
13 – 2 – 17 – 43 – 5 – 28
↓
2 – 5 – 13 – 17 – 28 – 43
--Ordinamento in-place (al momento)
--Stabilità
↘Due numeri consecutivi (con la stessa chiave) se sono ordinati secondo algoritmi stabili vengono ordinati come erano all’inizio. Con l’uso degli algoritmi instabili questa regola viene sconvolta.
--Un ordinamento si dice “Multichiave” se ordiniamo principalmente seguendo una chiave e, nel caso di due chiavi uguali, usiamo un’ulteriore chiave di ordinamento.
°°°Ci sono alcuni algoritmi detti Naif. Sono molto semplici da ricordare ma poco efficienti
↘selection sort
↘insertion sort
↘bubble sort
°°°Gli algoritmi difficili ma molto efficienti sono, ad esempio:
↘headsort
↘quicksort
↘mergesort
↘shellsort
Con efficienza si intende la velocità di ordinamento. Per gli algoritmi naif l’andamento del tempo è quadratico n2. Per gli algoritmi efficienti, invece, è nlogn.
###
Per prima cosa cerchiamo il minimo:
Nella prima scansione segnerò che il minimo si trova alla posizione n. A questo punto scambio il minimo con il numero in prima posizione.
2 - 13 – 12 – 43 – 5 – 28
Passiamo alla seconda posizione. Ricerchiamo un “Nuovo minimo” (non considerando più il precedente) e lo mettiamo in seconda posizione.
2 – 5 - ….
Andiamo avanti fino ad ottenere la soluzione ordinata:
2 – 5 – 12 – 13 – 28 – 43
In codice:
for (int=0;i<n;i++){
imin=i;
vmin=x[i];
}
for (int j=j+1;j<n;j++)
if(x[j]<vmin){
vmin=xx[j];
imin=j;
}
NOTA Alcune ore di lezione, regolarmente svolte dal professor Boldi sono state impiegate per svolgere utili esercizi di preparazione al compitino. Tracce e soluzioni sono presenti sito del Prof. Boldi nella sezione Programmazione [Informatica].
Costruzioni di sottoclassi
Public class Rettangolo {
private double b;
private double h;
public Rettangolo (double b, double h) {
this.b=b;
this.h=h;
}
Richiamandolo con
Public double getBase() {
Return b;
}
Public double getArea(){
Return b*h;
}
Public String toString(){
Return “base: “+b+”,altezza= “+h;
}
//Quando scriviamo una classe senza specificare niente la nostra classe sarà “figlio di Object”
Public boolean equals (Object x)
//Si deve fare così perché dobbiamo SOVRASCRIVERE l’equals di Object.
If (!(x instanceof Rettangolo))
Return false;
Rettangolo r=(Rettangolo)x; //Cast necessario per scrivere gli attributi b e h
return b==r.b && h==r.h;
}
// Le ultime due righe si possono scrivere anche:
return b==((Rettangolo)x).b && h==((Rettangolo)x).h;
public int(hashCode(){
return(int)(b+h);
}
###
Scriviamo, ora, Quadrato:
public class Quadrato extends Rettangolo //Per indicare che è una sottoclasse del Quadrato
//Nel caso in cui non specificassimo niente nell’intestazione stiamo creando una sottoclasse di Object
Public double getLato(){
return b; //Ereditato da Rettangolo
}
//Questo codice non funziona perché b è private e nemmeno la sottoclasse può cambiarlo.
Soluzione1:
Public double getLato(){
Return getBase();
}
Altra soluzione è modificare il primo pezzo di codice (in Rettangolo) come segue:
Public class Rettangolo {
protected double b;
protected double h;
public Rettangolo (double b, double h) {
this.b=b;
this.h=h;
}
L’attributo protected è un altro livello di sicurezza ma, a differenza di private, permette la modifica dei parametri da parte delle sottoclassi.
Continuando con la classe Quadrato:
public class Quadrato extends Rettangolo{
public Quadrato (double lato){
b=lato;
h=lato;
}
e:
public double getLato(){
return b;
}
Public String toString(){
Return “lato: “+b;
}
###
Concatenazione di Costruttori:
Ogni costruttore di una sottoclasse, come prima istruzione, è tenuto ad invocare (esplicitamente o implicitamente) un costruttore della superclasse.
Public class Quadrato extends Rettangolo{
Public Quadrato (double lato){
Super(lato,lato);
}
//Invochiamo un costruttore della Superclasse.
// Se non vi è un super specifico Java lo aggiunge.
###
Proviamo ad impostare la classe di un rettangolo colorato (colore=Stringa)
Public class RettangoloColorato extends Rettangolo {
protected String colore;
public RettangoloColorato(double b,double h, String c){
super (b,h);
this.colore=c;
}
E quindi:
public String getColore(){
return colore;
}
public String toString(){
return “base= “+b+”, altezza= “+h+”, colore= “+colore;
}
…Ma stiamo duplicando un pezzo di codice (scomodo, ad esempio, per la localizzazione)
Risolviamo riscrivendolo così:
public String toString(){
return super.toString() +”, colore=”+colore;
}
//Il super evita l’incorrere in un ciclo continuo…
Possiamo confrontare il metodo equals dell’attuale sottoclasse con la superclasse di livello uno.
Non possiamo tornare su di due livelli (chiamiamola “categoria nonno”)
Per confrontare la sottoclasse con la sovra-sovraclasse:
public.boolean equals (Object x) {
if (! Super.equals(x))
return false;
else{
if (!(x instanceof RettangoloColorato))
return false;
Rettangolo Colorato r=(Rettangolo Colorato) x;
return this.colore.equals(r.colore);
}
###
PACCHETTI
Classe
Nome semplice
String
Rettangolo
Nome completo
Java.lang.String
prog.utili.Rettangolo
al posto di Rettangolo r;
possiamo scrivere tranquillamente il nome completo prog.utili.Rettangolo (7,12); evitando di scrivere le direttive di importazione.
Quando si può usare il nome semplice?
*Quando il pacchetto è java.lang
*Quando il pacchetto è stato importato
*Quando la classe è stata importata
*Quando il pacchetto è lo stesso della classe che sto scrivendo
package paolo boldi.azzardo;
//Package è il paccketto in cui finirà la classe che stiamo scrivendo
Come si compilano queste classi?
E’ fondamentale che ci sia una struttura delle directory che tenga conto del percorso della classe
(Ad es. in windows)
C:\
↘paolino
↘esercizi.java
↘[[robazzardo]]
↘paolo
↘Boldi
↘azzardo
↘Carta.java
↘Carta.class
Per compilare robazzardo: javac paolo\boldi\azzardo\*.java
Si deve compilare così perché il compilatore si aspetta la stessa organizzazione delle cartelle.
L’esecuzione non è delle più semplici:
Eseguendo dal punto in cui abbiamo compilato (origine dei pacchetti) bisogna scrivere tutto il percorso. Ad es java paolo.boldi.azzardo.Carta
Java sa di dover cercare Carta.class ma non sa da dove iniziare. Inizia dai posti indicati dalla classpath.
C:\ ; c:\paolino\esercizijava|;
c:\paolino\esercizijava|robazzardo:
.
//Il “.” È importante se vogliamo far “cercare” anche nella directory corrente.
Un esempio lampante è l’utilizzo di prog.io. Per il suo utilizzo abbiamo dovuto settare la classpath!
Altra utilia è l’utilizzo dei jar. Per la loro creazione è necessario un programma scaricato con la jvm. Il jar è utilizzabile un jar nel settaggio della classpath (in questo caso il jar viene scompattato e scandagliato).