Newsgroup: it.comp.lang.c++
Titolo: Stroustrup Cap. 10 Aiuto su esercizio 10.6.1

Cap. 10 esercizio 10.6.1 p. 291
"Si trovi l'errore in Date::add_year() in 10.2.2 e i 2 ulteriori
errori nella versione in 10.2.7"
Da 10.2.2 :
class Date {
	int d,m,y;
        public :
        inline	void add_year(int n) { y+= n;}
        //... 
        };
--------------------------------------
Da 10.2.7 :
class Date {
	int d,m,y;
        public :
	Date& add_year(int n);
        //...
        };
Date& Date::add_year(int n)
{
	if (d==29 && m==2 && !leapyear(y+n)) {
		d = 1;
		m = 3;
		}
	y += n;
	return *this;
};
L'errore potrebbe (?) essere nella formulazione di
y +=n;
nella 1a versione e 
d = 1; m = 3;
nella 2a, ma questo lo dico senza capire realmente cosa dovrebbe poi
esserci di sbagliato in questi assegnamenti, sempre che l'errore sia
lě.
Qualcuno potrebbe aiutarmi a capire di piů ?
Molte grazie.

 Molte grazie.
Io no, ho il tuo stesso dubbbio.
--
Luigi Mantellini
Per il pessimista il bicchiere č mezzo vuoto,
per l'ottimista č mezzo pieno,
per un ingegnere č semplicemente sovradimensionato rispetto l'uso.

era meglio se postavi anche la parte problematica che risulta essere il
leapyear


1a email :
(1) d.add_year(0) on Feb 29, 2004 will incorrectly change the date
(2) I can't think of the other one right now. Sorry.
2a email :
oops, on second thought I *think* I was thinking of this:
(1) Is d.add_year(-3) correct on a Feb 29? I think not
(2) d.add_year(-2002) lands on the non-existent year 0.
Quindi non erano errori di sintassi quanto di logica,
che ne dici ?
Se non altro posso andar oltre più contento,adesso.
Ciao.

Non č necessario il punto e virgola dopo la funzione
Sě che č necessario.
P.S. Quando rispondi ad un messaggio potresti eliminare dal messaggio
quotato le parti inutili (cioč quelle a cui non rispondi)?
-- 
Marco Barisione (ICQ 84277092)

 Ciao.
Ah, ma erano solo degli esempi... poteva scrivere "Migliorare il codice
affinché funzioni anche nel caso xxx". Io pensavo qualche raffinatezza del
C++ o peggio errori nella sintassi! Non avrei mai pensato a quel tipo di
errore!
Grazie comunque dell'aggiornamento!
--
Luigi Mantellini
Per il pessimista il bicchiere è mezzo vuoto,
per l'ottimista è mezzo pieno,
per un ingegnere è semplicemente sovradimensionato rispetto l'uso.

> la parte problematica che risulta essere il leapyear
Mah, problematico leapyear() non direi.
Mi sembra piuttosto un semplice controllo : anno bisestile o no ?
Una funzione che si potrebbe definire così secondo me ( probabilmente,
anzi sicuramente ne esisterà già una versione migliore, ma questa è
comunque quello che ho saputo inventarmi io adesso ) :
bool leapyear (int i)
{
if ((i % 4) == 0  && (i % 100) || (i % 400) == 0)
		return true;
return false;
}
oppure questa versione più contorta che è (spero) l'inverso esatto
speculare della prima :
{
if ((i % 400) && (i % 100 == 0) || (i % 4))
		return false;
return true;
}
Cosa ne dici(dite ) ?

 > };// QUESTO PUNTO E VIRGOLA
Sě, qui secondo me hai ragione, ho sbagliato io a scrivere, infatti dopo
la definizione non ci va. Il libro in effetti a p. 260 fa proprio :
Date& Date::add_year(int n)
 {
 //.....
 return *this;
 }
scusami l'errore.

 errore!
Già, anch'io ho fatto la tua identica considerazione :)
Ehm, non vorrei sembrare presuntuoso, ma una delle risposte non mi
convince proprio...
Vale a dire quando mi dice :
Date& Date::add_year(int n)
{
 if (d==29 && m==2 && !leapyear(y+n)) {
  d = 1;
  m = 3;
  }
 y += n;
 return *this;
}
1a email :
"d.add_year(0) on Feb 29, 2004 will incorrectly change the date"
Ma perché ? Per add_year(0) succede che n == 0 per cui evidentemente
(y += n) == y;
Ora in add_year()
se partivamo da un bisestile 2004 che rimane tale, l'espressione
"leapyear(y+n)" posto che ritorni un bool true in caso di bisestile,
varrà ancora == true, perciò (!leapyear(y+n)) == false
non ti sembra ?
Perciò se fai 29.2.2004 e poi add_year(0) le 2 righe
d = 1;
m = 3;
sono saltate e la data non può mica diventare
1.3.2004, rimane 29.2.2004.
Non vedo perché dica : will incorrectly change the date.
Del resto ho già provato a compilare il programmino e ho visto che
add_year(0) non fa nessun danno.
Secondo me, con tutto il rispetto ecc. ecc. si è sbagliato lui in
questo caso.
E secondo te ?

 Sě che č necessario.
mi spiace contraddirti Marco, ma il punto e virgola e` opzionale. Basta 
guardare la grammatica del C++:
member-declaration:
        ...
        function-definition ;opt
        ...
come vedi il ';' dopo function-definition e` marcato come opt, quindi 
puo` anche non esserci.
ciao Anto
-- 
Antonio Cuni, 20 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

puo` anche non esserci.
Sono stupido, non ho letto il messaggio bene e ho visto quel class
davanti. Pensavo fosse la chiusura di una classe.
Perň non sapevo che dopo una funzione si potesse mettere il ";" e
virgola.


 Non è necessario il punto e virgola dopo la funzione
Cosi' come e' scritta il membro add_year e' dichiarato e non definito.
In questo caso il punto e virgola e' obbligatorio. Si fosse invece
trattato di una definizione, sarebbe in effetti stato facoltativo.
Ciao,
Nicola

 virgola.
a dire la verita` IMHO la grammatica e` ambigua. Consideriamo il caso 
delle funzioni non-metodi:
void foo()
{
}; // notare il punto e virgola
sempre se spulciamo la grammatica notiamo che una definizione di funzione 
non ammette il punto e virgola finale:
function-body:
        compound-statement
...
compound-statement:
        { statement-seq opt }
nota che dopo la } di compound statement il punto e virgola non e` 
ammesso. Tuttavia il codice che ho postato sopra e` perfettamente 
legale, in quanto il compilatore interpreta quel punto e virgola come 
una dichiarazione vuota:
simple-declaration:
        decl-specifier-seq opt init-declarator-list opt ;
come vedi sia "decl-specifier-seq" che "init-declarator-list" sono 
opzionali, quindi un punto e virgola da solo e` a tutti gli effetti una 
simple-declaration, e sino a qui non ci sono problemi.
Il caso delle funzioni definite all'interno delle classi e` simile:
member-declaration:
        decl-specifier opt member-declarator-list opt ;
        function-definition ; opt
        ...
Il punto e virgola dopo la definizione puo` essere interpretato in due 
modi: come parte opzionale dopo function-definition oppure come 
dichiarazione vuota!
Sebbene a livello semantico non cambi nulla a livello sintattico le cose 
cambiano, non credete?


 E secondo te ?
Credo di sì. Una svista! Oppure voleva dire qualcos'altro... ;(


 Cosa ne dici(dite ) ?
Se non ricordo male:
un anno è bisestile se e solo se il numero identificativo dell'anno è:
(divisibile per 4 ma non per 100) oppure (divisibile per 400)
#define bisestile(a) \
((!a%4&&a%100)||(!a%400))


 ciao Anto
Ciao.
-- 
Andrea Bergia - studente
Linux Registred User #281550

> Non è necessario il punto e virgola dopo la funzione
hai ragione! Non avevo visto che mancava la graffa aperta...
quanto e` bello python e le sue regole di indentazione! ;-)


 ((!a%4&&a%100)||(!a%400))
Infatti se non vado errato corrisponde in pieno al mio :
bool leapyear (int i)
{
if ((i % 4) == 0  && (i % 100) || (i % 400) == 0)
		return true;
return false;
}
O no ? ;)

 O no ? ;)
Esiste anche la forma "compressa":
bool leapyear(int i)
{
 return ((i % 4) == 0  && (i % 100) || (i % 400) == 0);
}
Ma penso, cmq, che gia' ne fossi a conoscenza...:-)
-- 
C Ya!
/* Cut "DO NOT DISTURB" to reply */

 O no ? ;)
certo! certosino! Non volevo dire "lui ha sbagliato" o cose simili! Ma solo:
"Non può essere un problema la funzione bisestile", e dare l'ennesimo
rimpasto del problema.
Scusa ;)


 Credo di sì. Una svista! Oppure voleva dire qualcos'altro... ;(
Secondo me alla fine quando ha scritto il 2° messaggio
"oops, on second thought I *think* I was thinking of this:
(1) Is d.add_year(-3) correct on a Feb 29? I think not
(2) d.add_year(-2002) lands on the non-existent year 0"
voleva appunto correggere l'idea di add_year(0) che era una svista nel 1° messaggio.

 O no ? ;)
No.  Lo short-circuiting di && e ||, nel caso si tratti di un anno
secolare, ti restituisce 'true' senza controllare se l'anno sia o meno
divisibile per 400.  Le parentesi sono necessarie.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy          loreti at pd dot infn dot it

 divisibile per 400.  Le parentesi sono necessarie.
Non capisco.
Poniamo che :
i == 100 (anno secolare, NON bisestile)
&& precede ||
if ((i % 4) == 0  && (i % 100) || (i % 400) == 0)
((i % 4) == 0) è TRUE
(i % 100) è FALSE
TRUE && FALSE è FALSE
(i % 400) == 0) è FALSE
(TRUE && FALSE) || FALSE infine vale FALSE (non bisestile).
Dov'è l'errore ?