Errata de Introduction à la programmation 2. ANSI/ISO C++ et programmation Windows avec Visual C++ Par Michel Michaud 1999, Loze-Dion éditeur inc. --------------------------------------------------------------------------- Dernière mise à jour : 2 février 2001 Pour le moment, deux erreurs graves assez graves ont été trouvées. À la page 42, j'ai mis un exemple de structures décrivant des modes de paiement et qu'on mettra dans une union. Pour simplifier l'exemple, j'ai remplacé les vecteurs de caractères de ces structures par des strings. Malheureusement, on ne peut pas mettre des strings dans une union parce que ce sont des données d'un classe qui comportent des constructeurs et il n'est pas possible que ce type de données se partagent correctement l'espace dans une union. Pour corriger l'exemple, il faut donc remplacer toutes les strings par des vecteurs de caractères, avec déclarations de tailles appropriées. Le code corrigé qui suit devrait remplacer les deux structures erronées : (on supposerait que les constantes LARGEUR sont définis ailleurs) struct TypeCarteCredit { char noCarteCredit[LARGEUR_NO_CARTE_CREDIT+1]; TypeCieCredit cieCredit; int moisExpiration; int anneeExpiration; }; struct TypeCarteDebit { char noCarteDebit[LARGEUR_NO_CARTE_DEBIT+1]; char nomInstitution[LARGEUR_NOM_INSTITUTION+1]; }; À la page 87, l'explication sur les tableaux multidimensionnels utilisant vector est incorrecte (selon la norme). Voici un texte de remplacement : Pour faire des tableaux multidimensionnels, on peut utiliser des vectors de vectors (etc.), mais ce n'est pas aussi simple qu'on pourrait le penser. En effet, il n'est pas possible de déclarer directement toutes les dimensions d'un tableau multidimensionnel. Dans beaucoup de cas, les tableaux sont de tailles fixes et les tableaux de base seront satisfaisants. Si on veut absolument utiliser vector, par exemple pour profiter de la vérification des indices, voici un exemple de ce qu'il faut faire pour obtenir un tableau de int de 100x200 et un de double de 10x20x30 initialisés à -1.0 : vector > mat(100); // On a 100 lignes vides... for (int i= 0; i < mat.size(); ++i) mat[i].resize(200); // On crée des lignes de 200 éléments à 0 par défaut vector > tab3d(10); // 10 plans vides for (int i= 0; i < tab3d.size(); ++i) { tab3d[i].resize(20); // Les plans auront 20 lignes vides for (int j= 0; j < tab3d[i].size(); ++j) tab3d[i][j].resize(30, -1.0); // 30 éléments à -1, par ligne } N.B. Les espaces entre les > des déclarations sont obligatoires sinon le ... (la suite est correcte) --------------------------------------------------------------------------- Le reste de cet errata ne contient que des erreurs simples : celles dont la correction peut aider la compréhension ont été notées par des numéros de page précédés par **. Certaines erreurs ont été corrigées dans les réimpressions du livre. Il est donc possible que les erreurs qui suivent ne s'appliquent pas à votre exemplaire. Format : numéro de page texte du livre correction --------------------------------------------------------------------------- **5 double x= 1,23; // ... 23 Ici, ... 23 à affecter. (le paragraphe complet) x= 1,23; // On aura x==1.0 au lieu de 1.23 L'expression est interprétée comme (x= 1), 23;. Le 23 est sans conséquence. 14 "Erreur en lecture. Fournissez les données dans le format adéquat.\n" "Erreur en lecture dans cin.\n" (le message se rapportant au format serait approprié si on captait les exceptions pour l'état fail) 23 les lignes du programme avec de les passer les lignes du programme avant de les passer 23 ENtREE_SORTIE ENTREE_SORTIE **26 int k= j++, i++; int k= (j++, i++); **33 while ( !(JANVIER < noMois && noMois < DECEMBRE) ); while ( !(JANVIER <= noMois && noMois <= DECEMBRE) ); 35 float prix; }; // Ou double float prix; // Ou double }; 37 getline(cin, p_s_livre.prenom, '\t'); getline(cin, p_s_livre.nom); getline(cin, p_s_livre.prenomAuteur, '\t'); getline(cin, p_s_livre.nomAuteur); 38 << p_livre.prenom << ' ' << p_livre.nom << ", publié en " << p_livre.prenomAuteur << ' ' << p_livre.nomAuteur << ", publié en " **42 string noCarteCredit; (etc.) char noCarteCredit[LARGEUR_NO_CARTE_CREDIT+1]; (etc., voir ci-haut) 44 << '/' << setw(2) << p_fact.credit.anneeExpiration << setfill(' ') (bug de l'an 2000 !) << '/' << setw(4) << p_fact.credit.anneeExpiration << setfill(' ') **50 typedef char TypeAdresse[NB_LIGNES_ADRESSE][LARGEUR_LIGNE_ADRESSE+1]; typedef char TypeLigneAdresse[LARGEUR_LIGNE_ADRESSE+1]; typedef TypeLigneAdresse TypeAdresse[NB_LIGNES_ADRESSE]; (la version originale est techniquement correcte, sauf qu'on n'a pas vu les tableaux à deux dimensions à ce point dans le livre) 50 int16_t ObtenirScolarite(); TypeScolarite ObtenirScolarite(); 51 void ObtenirInfoSoutien(TypeInfoSoutien& p_s_prof); void ObtenirInfoCadre(TypeInfoCadre& p_s_prof); void ObtenirAdresse(TypeAdresse& p_adresse); // ... void ObtenirInfoSoutien(TypeInfoSoutien& p_s_soutien); void ObtenirInfoCadre(TypeInfoCadre& p_s_cadre); void ObtenirAdresse(TypeAdresse& p_s_adresse); // ... 53 case CADRE : ... case SOUTIEN : ... (les deux case sont inversés) case SOUTIEN : ... case CADRE : ... 63 Imprimer(... (trois fois en bas de la page) Afficher(... **82 par la classe vector. En fait, par la classe vector, disponible quand on inclut . En fait, 100 TYPE_FACTURE TypeFacture 104 TYPE_CLIENT (deux fois) TypeClient 122 ..., p_anneeInscription) // ERREUR ..., int p_anneeInscription) // ERREUR **123 if (uneDate.ChangerDate(jour, mois, annee)) if (! uneDate.ChangerDate(jour, mois, annee)) **130 int ClDate::DateValide(... Il manque un return 0; à la fin de la fonction 133 CetteFonction() CetteFonction(); 135 ClClient(char p_nom[], char p_prenom[], int p_noClient) ClClient(const char p_nom[], const char p_prenom[], int p_noClient) 136 int p_nbPages, p_anneeParution, float p_prix) int p_nbPages, int p_anneeParution, float p_prix) 138 ..., ClDate p_dateLocation); ..., const ClDate& p_dateLocation); 138 class ClLocation... Bien que ce ne soit qu'un exemple simplifié, toutes les fonctions membres, sauf le constructeur, devraient être notées const. 139 ..., ClDate p_dateLocation) (deux fois) ..., const ClDate& p_dateLocation) 139 class ClLocationLongTerme... Bien que ce ne soit qu'un exemple simplifié, toutes les fonctions membres, sauf le constructeur, devraient être notées const. 139 membredu membre du **140 m_noOutil(p_noOutil) m_nbJoursLocation(p_nbJoursLocation) 140 CLocationLongTerme ClLocationLongTerme 141 double ClLocationLongTermer::Cout() // ... double ClLocationLongTerme::Cout() const // ... 141 CLocation::Cout(); ClLocation::Cout(); 142 virtual double Cout(); virtual double Cout() const; 143 /*virtual*/ double Cout(); /*virtual*/ double Cout() const; 169 NB_YESNO MB_YESNO 188 void CLivresView::OnLivresConsulter()... (bas de la page) On peut enlever cette portion de la fonction qui est répétée à la page suivante. 203 d.DoModal()) d.DoModal(); 209 Visualiser les moyennes... Visualiser les aubaines... Au lieu des V, ce sont le m de moyennes et le a de aubaines qui devraient servir de raccourci clavier. 220 Il faut enlever le paragraphe du N.B. du bas de la page. 223 L'accolade sous le premier if (!Open(... est mal placée. 229 p_enr.numero= NO_CLIENT_INEXISTANT; Cette ligne est inutile dans la deuxième version de la fonction (donc à enlever). **232 Le constructeur est déclaré virtual... Le destructeur est déclaré virtual... 236 L'accolade à la fin de la fonction Effacer est mal placée. 242 CAjoutLivre d(m_pDoc); CAjoutLivre d; 246 m_ficLivres->Reinitialiser(); m_ficLivres.Reinitialiser(); 253 pour mettre le titre désirée pour mettre le titre désiré 255 BOOL CAjoutLivre::OnInitDialog() BOOL CSaisieLivre::OnInitDialog() **320 | (seconde << 17); // pas les additionner. | seconde; // pas les additionner. **320 ...0xFC000000) >> 26) // Masquage facultatif ...0xFC000000) >> 26) + 1990 // Masquage facultatif