Newsgroup: it.comp.lang.c++
Titolo: cout e printf

Le funzioni da te citate si usano spesso in C, ma in C++ si devono usare
cout, cin perché più flessibili.
Sono ancora presenti e utlizzabili in C++ solo per compatibilità con codice
C.

 C'e' una regola o e' una decisione lasciata all'abile programmatore? :-)
Se vuoi programmare in C++, usa i costrutti del C++ (ovvero <iostream>
e non <cstdio>).  Perche'?  Cito il Meyers: i metodi di <iostream>, a
differenza di quelli di <cstdio>
- sono typesafes ed estendibili; visto che typesafety ed estensibilita'
  sono concetti fondamentali alla base del C++, perche' rinunciarvi?
- la sintassi e' uguale per l'input e l'output, e non devi ricordare
  ad es. di usare %f per l'output e %lf per l'input di doubles.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 (perlomeno le piu' importanti)!!!
Il C++ e` un linguaggio ricco e complesso e per usarlo bene non si
puo` prescindere dalla conoscenza di massima di quello che offre nelle
sue librerie standard.
Alex

(perlomeno le piu' importanti)!!!
A poco a poco si impara...
Paolo
--------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
--------------------------------------------------

Ok... non tutti i concetti da voi espoti mi sono chiari ma ritengo derivino
dalla mia scarsa conoscenza del linguaggio.
Converrete con me che il C++ non e' per un principiante (con deleteri
ricordi di Basic) facile.
Concettualmente ho capito quanto segue:
nel caso delle 'istruzioni' citate nell'oggetto cout e' C++ ed e' piu'
malleabile di printf vecchio retaggio di C.
Chiedo scusa ad Alex ma la parte di codice che hai incluso e' per me, spero
solo al momento, puro arabo; ne deduco, pero', che uno dei punti di forza
del C++ e' quella di poter costruire pezzi di codice (o funzioni) da poter
utilizzare all'occorrenza in applicativi che hanno risultati e scopi
diversi. Potresti, cioe', 'prestarmi' una funzione che hai creato lo scorso
inverno e che risolve un certo problema ed io potrei utilizzarla all'interno
di un mio codice. In pratica una specie di puzzle....
Non mi e' chiaro il concetto di oggetto applicato a cout... in che senso
oggetto?
Cioe'... i=i++ e' un'istruzione;
cout <<"Ciao"<<endl... cout e' l'oggetto sul quale 'riversare' la parte a
sinistra? Mha...
Grazie ed... abbiate pazienza.
--
--
Ciao... Unlucky Man
Rimuovi no dall'indirizzo per rispondermi
--

Non proprio. L'oggetto cout ha il solo scopo di stampare sullo schermo le
cose(chiamiamole cosě) che gli passi.
Ad esempio:
cout << "ciao" << "ciao" << "ciao" << endl;
in questo caso cout scrive sullo schermo: ciaociaociao, ovvero tre
stringhe.
altro esempio:
int a = 10;
cout << a << endl;
questa volta il cout stampa il valore della variabile a, ovvero 10.
L'operatore << (operatore di immissione) ha il compito di separatore tra le
varie cose che passo a cout.
Pensa solo che pasticcio se facessi:
cout "ciao""ciao""ciao"; //nessun compilatore me lo accetterebbe
Un altro caso:
cout << endl; 
cout << "ciao";
L'endl (end line) ha il compito di segnalare che la linea d'output č finita
e  forza il ritorno a capo. 
Se qualcosa non č ancora chiaro non esitare a chiedere.

sinistra? Mha...
Si, la classe ostream definisce operator << per i tipi primitivi.
Utilizzando l'overloading puoi scrivere
class T2 {
  ...
  friend ostream& operator<<(ostream& os, const T2& t);
             // definito in qualche modo
};
class T {
  public:
      ...
  private:
     double b;
     int a;
     T2 t2;
  friend ostream& operator<<(ostream& os, const T& t);
};
ostream& operator<<(ostream& os, const T& t) {
  os << b;
  os << a;
  os << t2;
  return os;
}
T MyT;
cout << MyT;
si traduce automaticamente in
operator<< (cout, MyT);


 cout "ciao""ciao""ciao"; file://nessun compilatore me lo accetterebbe
Qui ti perdo un attimo... e' evidente che mancano << cioe', consentimi la
rozzezza ed imperfezione, manca il reindirizzamento 8e questo non verrebbe
accettato dal compilatore.
La parte che segue dopo il ; non ha senso per me... credo ci dedda ancora
arrivare ma, in ogni caso, il ; non indica il termine della riga di
codice... cioe':
cout<<"ciao!!"<<endl;i++;
non e' come scrivere
cout<<"ciao!!"<<endl;
i++;
cacchio... ci sono arrivato ora... che schifo outlook express
'//' nessun compilatore me lo accetterebbe... e' l'unico modo di scriverlo
per evitare che diventi un local URL..... :-DD
Era un commento... sono proprio una pippa.
Ancora, se permetti, una piccola riflessione: hai parlato di oggetto (che ho
incontrato sul libro poche ore fa)... vediamo se ho capito...
1) Ho un problema che suddivido in tanti piccolissimi sottoproblemi;
2) un sottoproblema potrebbe essere il calcolo di una somma;
3) non avendo una variabile nativa per questo, creo una classe che chiamo
somma;
4) l'oggetto (al quale ci riferivamo prima con cout) altro non e' che una
variabile che fa parte della classe in precedenza creata.
Non ho ancora gli strumenti ed i concetti per esporre quello che penso nel
modo corretto ma potremmo dire che:
cout e' un oggetto, quindi una variabile di classe, definita in questo caso
all'interno di iostream.h.
iostream.h in realta' e' implementato da tutti i compilatori C++ perche' fa
parte di quelle particolari porzucole di codice messe a disposizione dei
programmatori e definite/incluse/accettate dall'ANSI; ma nulla vieta che
potrei creane io...
E' corretto... almeno concettualmente?
grazie per la pazienza


Cout serve solo per stampare informazioni sul video in modo da comunicare
con l'utente. Comunque mi sembra che hai capito i concetti.
Il ; serve a comunicare che l'istruzione è finita.
Il // è un inizio di commento tipico del C++ e per il compilatore vuol dire
che la restante parte della riga che segue il // è interpretata come
commento.
Simile al /* */ che hai studiato in C (puoi anche utilizzarlo in C++), ma
con alcune differenze quali la non possibilità di essere inserito nel
codice.
int a = /* commento*/ 10; //giusto
int a = // commento   // 10 // errore perché tutto dopo = è interpretata
come commento.
Inoltre tu puoi anche scrivere tutto il tuo codice su una sola linea
separando però ogni istruzione da un ;.
Per il resto concettualmente è corretto quello che dici. Ma un oggetto non
è una variabile di classe.Chiarisco con questo esempio:
int a = 10; 
Qua creo una variabile di tipo intero.
class a {};
a oggetto;
Qua un oggetto. Ma la sostanziale differenza è che una classe è solo un
nuovo tipo per definire variabili personalizzate.

 operator<< (cout, MyT);
Grazie


Neach'io sono esperto come Paolo Marotta e compagni. 
Quando si parla di overloading, Unlucky - un nome piů felice non potevi
trovarlo? -, s'intende sovraccaricamento di qualche cosa. Nel caso delle
funzioni tu scrivi in un solo programma piů funzioni con lo stesso nome ma
che prendono diversi parametri e poi tocca al compilatore e al linker
capire quale funzione si sta chiamando in causa.
Riferito agli operatori credo che voglia dire la definizione di operatori
personalizzati.

 wrote in message
8ifrae$ppv$1...@nslave2.tin.it...


 accettato dal compilatore.
Che c'entra il reindirizzamento? Il simbolo << è, in questo contesto,
l'operatore di inserzione.
EMG

 nuovo tipo per definire variabili personalizzate.
Cioe' se dovessi avere bisogno di ulteriori variabili (quindi non native)
posso crearle proprio grazie a class.
Al momento non ne comprendo appieno la necessita' ma se qualcuno si e'
inventato un'implementazione di questo tipo, se tutti sono entusiasti del
C++ perche' consente cose del genere... un motivo ci sara' anzi, sicuramente
piu' di uno... non mi resta che scoprirlo. Studiando.


cosa stai definendo con esattezza? friend come oggetto di T2?
estende gli stream per consentire l'output di un oggetto T2.
E` definita sulla falsariga dell'analogo operatore friend di T,
in particolare nota che l'output di un oggetto da te definito viene
ottenuto in termini dell'output delle sue componenti.


personalizzati.
La stessa identica cosa delle funzioni. Un operatore e` una funzione,
l'unica differenza e` la sintassi che si puo` utilizzare:
" a + b "   puoi anche scriverlo come  " operator+(a,b) "
ma chiaramente la prima scrittura ci e` molto piu` familiare.


Un datore di lavoro ti dice di fare un programma per gestire il profilo
utente di tre persone. Il  programma deve tenere l'età, il nome e il
cognome.
Se tu volessi creare tale cosa dovresti definire tre variabili per ciascuna
persona, quindi:
int eta_primapersona = 10;
char* nome_primapersona = "caio";
char* cognome_primapersona = "ciao"
int eta_secondapersona = 20;
char* nome_secondapersona = "Veronica"
char* cognome_secondapersona = "tommaso"
//altro codice
Pensa solo che casino nella dichiarazione e quando dovrò far riferimento ad
essi.
A questo punto mi sarebbe più utile scrivere:
struct profilo {
         int eta;
         char* nome;
         char* cognome;
}; 
profilo 1 = {10, "caio", "bonus"};
profilo 2 = {20, "40", "80"};
// altro codice
Come vedi in alcuni casi è utile creare nuovi tipi. Se ti stai chiedendo
cos'è una struttura ti rispondo col dirti che una classe ed una struttura
sono la medesima cosa. L'unica differenza è che i campi sono tutti
pubblici.
A presto.

     friend int operator == (Punto3D oper1, Punto3D oper2)
Forse sarebbe meglio passare i due oggetti per riferimento:
friend int operator == (Punto3D &oper1, Punto3D &oper2)
EMG

 wrote in message
394C9C02...@flashnet.it...

Probabilmente hai ragione, ma esattamente cosa cambia?
Forse non viene allocata ulteriore memoria per oper1 e oper2 ?
Gerolamo

 Forse non viene allocata ulteriore memoria per oper1 e oper2 ?
Se li passi per valore vengono passate delle intere copie degli oggetti
con tutti i loro dati membri (o comunque con le regole di copia prevista
dall'eventuale costruttore di copia) mentre se li passi per riferimento
vengono passati solo i puntatori agli oggetti originali. E nel caso
dell'operator == che non deve alterarli mi sembra la cosa più opportuna.
Anzi, meglio scrivere
friend int operator == (const Punto3D &oper1, const Punto3D &oper2)
EMG

Probabilmente hai ragione, ma esattamente cosa cambia?
Efficenza, gli oggetti potrebbero essere molto grandi!


Bene, bene... ricapitoliamo, se permettete le info fino ad ora ricevute,
grazie a tutti (Paolo, Gerolamo, Francesco):
certo che semplicemente chiedendo la differenza tra cout e printf siamo
arrivati ad affrontare questioni ben piu' delicate... figo!!!
---[Overloading]---
Vi spiace se facciamo un discorso concettuale? Con le istruzioni e le
modalita' ho ancora delle difficolta' perche' (ed e' un mio limite) mi
chiedo sempre: "vabbe... ma a che serve?"... :-)
Overloading: posso aver definito una funzione che mi serve, ad esempio, per
fare la media di due valori short ma, successivamente, mi accorgo che ne ho
bisogno di una che la faccia sui float. Non e' il caso di riscrivere la
funzione o modificarla... e' sufficiente richiamarla dichiarando, pero',
quali sono i tipi di variabile sulla quale operare.
Sara', quindi, compito del compilatore regolarsi di conseguenza.
Se quel che ho detto e' piu' o meno corretto, presumo che questo possa
servire (e' una delle cose che mi viene in mente) per l'economia del
programma. Sarebbe, cioe', piu' semplice scrivere una funzione che allochi
il massimo delle risorse disponibili - trattando tutto come long double, per
esempio, ma che senso avrebbe?
Non e' un approccio corretto per il C++ dove il 'non sprecare risorse' e'
fondamentale.
Inoltre, questo non consentirebbe al compilatore di 'avvisarmi' nel caso in
cui il valore di una variabile long finisse erroneamente in uno short
(sarebbero entrambi trattate come long double) ma questo potrebbe essere
deleterio per la funzionalita' dell'applicazione.
Ci sono?
Il discorso e' estendibile a qualsiasi operatore... in questo caso e' come
'gonfiare' il singolo operatore. Da reminescenze, vi prego non castigatemi,
non ci sono ancora arrivato... e' solo un lieve ricordo... Gerolamo usava
array e operatori logici.
Scrivendo la funzione (applicata agli oggetti P1 e P2 di tipo definito da
Punto3D) che ritorna un valore vero/falso sul confronto degli elementi
dell'array. Mi sono perso?
PS. per Francesco... Unlucky Man... e' scaramantico perche' spero che prima
o poi possa 'rinominarmi' lucky man; me lo merito perche', in questo periodo
la mia vita va che e' uno schifo... garantito!!!
Grazie a tutti.


 l'operatore di inserzione.
Hai ragione... non uso la terminologia giusta ma... sono sul C++ da meno di
un mese... :-(
Volevo dire (non conoscendo ancora il termine operatore di inserzione) che
<< 'veicola' il valore a destra in quello a sinistra.
La difficolta', per me, e' divincolarsi tra quelle che sono le variabili
native e quelle implementate (si dice cosi'?).
Nel caso di cout (correggimi se sbaglio) e' una variabile (o variabile
funzione) che consente di avere in video il risultato di una certa
istruzione. Cout non e' nativa ma implementata da iostream.h.
Credo... :-(
Grazie...
PS. sono felice di constatare che sia tu che Paolo Marotta continuiate a
partecipare a questo NG. Molto tempo fa lo agganciai perche' avevo
intenzione di imparare il C++ (ma poi desistetti); ritrovarvi ora e notare
che siete sempre prodighi di consigli sottolinea una passione ed una
disponibilita' rare.
Ancora grazie



...a chi lo dici....
Gerolamo

Il concetto dell'overloading delle funzioni è un po' diverso da quello che
hai detto, ma ci siamo quasi.
Es.:
int funzione(int a, int b) {}
int funzione(float a, float b) {}
// entrambe le funzioni hanno lo stesso nome
int main() {
     funzione(10,20); // chiamata alla prima funzione
     funzione(0.4, 0.4); // chiamata alla seconda funzione
     return 0;
}
Le funzioni tu le definisci sempre con lo stesso nome, poi tocca al
compilatore ed al linker capire qual è la funzione che si sta realmente
chiamando.  Bada però che risulta errore scrivere:
void funzione(int a);
int funzione(int a);
float funzione(int a);
Il compilatore si basa essenzialmente sui valori che passi alla funzione.
In questo caso se io chiamassi funzione il compilatore non capisce quale
sto effettivamente chiamando.   

 quali sono i tipi di variabile sulla quale operare.
No, no, la funzione devi riscrivertela. Solo che puoi dare ad essa lo
stesso nome di quella che tratta short in quanto, differendo nei tipi
dei parametri, il complilatore non si confonde e sa quale chiamare.
EMG

 disponibilita' rare.
Stiamo tutti imparando qualcosa.
EMG

 A presto.
Grazie


Mi rendo conto ora che la tua domanda era più generica e non specifica per
l'overload degli operatori.
Così ho pensato di "espandere" l'esempio del Punto3D per renderlo più
completo.
Ora abbiamo
1) 2 costruttori della classe Punto3D
2) 2 significati dell'operatore ==
3) 2 funzioni stampa
Cosa significa tutto ciò?  significa che io posso usare ad es. stampa(...)
senza problemi ed essa si comporterà in modo differente a seconda del
parametro che gli ho passato.
Nota che il nome è lo stesso, è il parametro (o l'oggetto su cui è
applicato) che cambia!!!
Ho detto vaccate? Spero di no!!!
Gerolamo
///////////////////////////////////
#include <iostream>
#include <string>
using namespace std;
class Punto3D
{
public:
    float x;
    float y;
    float z;
    // prima definizione del costruttore (è senza parametri)
    Punto3D()
    {
        x=0;
        y=0;
        z=0;
    }
    // seconda definizione del costruttore  (passandogli i valori di x, y e
z)
    Punto3D(float X, float Y, float Z)
    {
        x=X;
        y=Y;
        z=Z;
    }
    friend bool operator == (Punto3D &oper1, Punto3D &oper2)
    {
        return(
                    (oper1.x == oper2.x) &&
                    (oper1.y == oper2.y) &&
                    (oper1.z == oper2.z)
                );
    }
};  // fine classe
// definisco 2 funzioni stampa che differiscono solo per il tipo di
parametro che gli passo
void stampa(int x)
{
    cout << x;
}
void stampa(Punto3D P)
{
    cout << P.x << ", " ;
    cout << P.y << ", " ;
    cout << P.z ;
}
int main()
{
    int a,b;
    a=0;
    b=0;
    Punto3D P0;  // viene usato il primo costruttore
                 // Domanda: Perchè  se scrivo Punto3D P0()
                 // non viene invocato il costruttore ???
   // Ma questo forse è meglio che lo
   // chiedo su un nuovo thread !!
    Punto3D P1(1.1,2.2,3.3); // viene usato il secondo costruttore
    Punto3D P2(1.1,2.2,3.3);
    // uso l' == con il significato ridefinito per Punto3D
    if (P1 == P2)
    {
    cout << "P1 è uguale a P2" << endl;
    cout << "P1: ";
    stampa(P1);      // viene chiamata stampa(Punto3D)
    cout << endl;
    cout << "P2: ";
    stampa(P2);
    cout << endl;
    }
    // uso l' == con il significato definito per gli interi
    if (a == b)
    {
    cout << "a è uguale a b" << endl;
    cout << "a: ";
    stampa(a);        // viene chiamata stampa(int)
    cout << endl;
    cout << "b: ";
    stampa(b);
    cout << endl;
    }
    cout << "PO vale: ";
    stampa(P0);     // viene chiamata stampa(Punto3D)
    cout << endl;
        string s;          //  non servono a nulla
        getline(cin,s);    //  solo per controllare l'output con CB4
    return 0;
}

Una piccola parentesi sulla terminologia di base:
1) Per membro s'intende un campo di una classe, di una struttura o di una
unione.
Per esempio le funzioni e le variabili che definisci dentro una classe
prendono rispettivamente il mome di funzioni membro(o metodi) e attributi.
2) Una variabile di tipo classe prende il nome di oggetto.
Ma dopo tutto non era errato il tuo modo di chiamarle.
Il problema delle terminologia c'č l'ho anch'io. E' molto piů  facile
ricordarsi la teoria e le keywords piuttosto che la semantica in generale.
Cmq con un po' d'impegno puoi anche farcela (vedi Paolo Marotta, Alex
Martelli,
Luc, Max M., Andrea Laforgia, Nicola Musatti e molti altri).
Saluti, Lucky Man

 E' una istanza predefinita della classe ostream.
Cacchio... e' peggio che imparare una nuova lingua e temo che la confusione
sull'utilizzo dei termini appropriati generi sovrana.
Vediamo un po'...
Classe
e' la possibilita' che offre il C++ di creare degli strumenti non
disponibili immediatamente. Questi strumenti possono essere nuovi tipi di
variabili o nuove funzioni.
Come li creo?
Creando un'interfaccia di classe, in questo modo il compilatore sa quali
sono questi nuovi strumenti. Estensione del file .h
Implementazione di una classe
Scrittura del codice che dica al compilatore come realizzare l'interfaccia
di classe, e' un file sorgente.
Istanza predefinita... cos'e'... cioe' ho capito ma come potrei definirla?
grazie


 Ho detto vaccate? Spero di no!!!
Non saprei... ma il concetto mi e' ora chiaro.
Grazie


 float funzione(int a);
Tutto chiaro, direi.
L'errore, in questo caso e' dovuto al fatto sono diversi i tipi di valori
restituiti da una funzione che ha i medesimi parametri formali. Il
compilatore, avendo un int da dare in pasto ad una funzione non saprebbe
quale utilizzare perche' le funzioni sono sostanzialmente identiche ma
dovrebbero ritornare tipi diversi.
grazie


 dei parametri, il complilatore non si confonde e sa quale chiamare.
Chiarissimo... ti ringrazio


 Istanza predefinita... cos'e'... cioe' ho capito ma come potrei definirla?
Semplicemente, per analogia, è come se chi ha scritto la libreria
standard avesse messo da qualche parte
int n;
Quella variabile n sarebbe un'istanza predefinita di tipo int come cout
lo è del tipo ostream.
EMG

Il compilatore se ne frega del tipo restituito, sono i parametri quelli che
contano.

 contano.
Cacchio... allora sono deficiente... non capisco...
Avevamo un overload accettabile se scrivevamo:
int mia_funzione(int a)
float mia_funzione(float a)
ma mi dicevi che scrivere:
int mia_funzione(int a)
float mia_funzione(int a)
void mia_funzione(int a)
genera degli errori in fase di compilazione. Come mai?
Ho creduto che l'errore sia dovuto alla differenza esistente tra il 'tipo di
funzione' ed il 'tipo del parametro formale'... giusto?


 lo è del tipo ostream.
Ok... ci sono, spero di aver fissato i concetti.
Tnks


 void mia_funzione(int a)
Il tipo ritornato NON viene considerato per l'overloading
(cfr. e.g. Stroustrup, pag. 151); queste due dichiarazioni sono
indistinguibili e DEVONO generare un errore.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 genera degli errori in fase di compilazione. Come mai?
Perche` Stroustrup decise, proprio ai primordi dello sviluppo del
C++, che imperniare la risoluzione di overload (anche) sul tipo di
ritorno era LA ragione per cui l'overload-resolution di Algol-68
aveva (giustamente) la fama di essere inusabile per l'eccessiva
complessita` -- si creano veri e propri "cicli di dipendenza" e
l'overload che alla fine fiene scelto applicando le regole diviene
virtualmente impossibile da capire per un essere umano, in una
espressione di pur modesta complessita`.
Stroustrup penso` invece che risolvendo l'overload "a senso unico",
cioe` DA argomenti VERSO funzione da usare, la complessita` si
sarebbe ridotta sino a divenire gestibile.  Sulla riduzione aveva
certamente ragione, se il risultato sia ancora gestibile e` un
tema piu` controverso (ma se non fosse per gli overload i template
in C++ non avrebbero molta della potenza che hanno, quindi la
complessita` risultante e` certo un prezzo che val la pena pagare).
Alex

genera degli errori in fase di compilazione. Come mai?
Il compilatore non considera il tipo di ritorno (che non e`
propriamente quello della funzione), distingue solo
sulla base del numero e dei tipi dei parametri formali


 funzione' ed il 'tipo del parametro formale'... giusto?
No, dipende dal fatto che tutte e tre le funzioni hanno lo stesso tipo
di parametro.
EMG

 sulla base del numero e dei tipi dei parametri formali
Hummm... dalla tua risposta e da quelle di Alex e Maurizio capisco quanto
segue:
appurata l'utilita' di avere la possibilita' di overload se nel mio codice
avessi:
float mia_funzione(int a)
non avrei problemi in fase di compilazione ma se scrivessi:
float mia_funzione(int a)
int mia_funzione(int a)
non sarebbe possibile distinguerle e, di conseguenza, il generare un errore.
Altro sarebbe scrivere:
int mia_funzione(int a)
float mia_funzione(float a)
infatti, mia_funzione potrebbe sembrare identica in entrambi i casi ma non
lo sono perche' il/i parametro/i formali
delle stesse differiscono rendendole, di fatto, diverse. E' come se avessero
(e lo hanno per il compilatore) nome diverso.
Ditemi, per favore, che ho capito!!!! :-)
Grazie...


 Ditemi, per favore, che ho capito!!!! :-)
Gli aspetti "di sostanza" sembri averli capiti.  Poi ci sono mille
dettagli, tipo, perche` nel caso "altro sarebbe scrivere" che sopra
riporti...:
    mia_funzione(1.23);
sia *USO AMBIGUO*, che un compilatore conformate DEVE segnalarti
come errore (una delle diecimila cose che frastornano e lasciano
sconcertati i poveracci che stanno imparando il C++).  (Hint: tu
pensi che 1.23 sia un float...?).
Alex

 Ditemi, per favore, che ho capito!!!! :-)
Hai capito perfettamente.
EMG