• Aucun résultat trouvé

Comme indiqué, l'outil d'extraction de code ExtractCode.cppgénère automatiquement des makefilespour chaque chapitre. De ce fait, ils ne seront pas inclus dans le livre (il sont tous joints au code source que vous pouvez télécharger depuis www.BruceEckel.com). Cependant il est utile de voir un exemple. Ce qui suit est une version raccourcie d'un makefilequi a été automatiquement généré pour ce chapitre par l'outil d'extraction du livre. Vous trouverez plus d'un makefiledans chaque sous-répertoire (ils ont des noms différents ; vous invoquez chacun d'entre eux avec " make -f"). Celui-ci est pour GNU C++:

CPP = g++

OFLAG = -o

.SUFFIXES : .o .cpp .c

.cpp.o :

$(CPP) $(CPPFLAGS) -c $<

.c.o :

$(CPP) $(CPPFLAGS) -c $<

all: \ Return \ Declare \ Ifthen \ Guess \ Guess2

# Le reste des fichiers de ce chapitre est omis Return: Return.o

$(CPP) $(OFLAG)Return Return.o Declare: Declare.o

$(CPP) $(OFLAG)Declare Declare.o Ifthen: Ifthen.o

$(CPP) $(OFLAG)Ifthen Ifthen.o Guess: Guess.o

$(CPP) $(OFLAG)Guess Guess.o Guess2: Guess2.o

$(CPP) $(OFLAG)Guess2 Guess2.o Return.o: Return.cpp

Declare.o: Declare.cpp Ifthen.o: Ifthen.cpp Guess.o: Guess.cpp Guess2.o: Guess2.cpp

La macro CPP affectée avec le nom du compilateur. Pour utiliser un autre compilateur, vous pouvez soit éditer le makefile, soit changer la valeur de la macro sur la ligne de commande de la manière suivante:

make CPP=cpp

Notez cependant, que ExtractCode.cpputilise un système automatique pour construire les fichiers makefiledes autres compilateurs.

La seconde macro OFLAGest le drapeau qui est uilisé pour indiquer le nom de fichier en sortie. Bien que de nombreux compilateurs supposent automatiquement que le fichier de sortie aura le même nom de base que le fichier d'entrée, d'autre ne le font pas (comme les compilateurs Linux/Unix, qui créent un fichier nommé a.outpar défaut).

Vous pouvez voir deux règles de suffixes, une pour les fichiers cppet une pour les fichiers c(au cas où il y aurait du code source C à compiler). La cible par défaut est all, et chaque ligne de cette cible est continuée en utilisant le caractère \, jusqu'à Guess2qui est le dernier de la ligne et qui n'en a pas besoin. Il y a beaucoup plus de fichiers dans ce chapitre, mais seulement ceux là sont présents ici par soucis de brièveté.

Les règles de suffixes s'occupent de créer les fichiers objets (avec une extension .o) à partir des fichiers cpp, mais en général, vous devez spécifier des règles pour créer les executables, parce que, normalement, un exécutable est créé en liant de nombreux fichiers objets différents et makene peut pas deviner lesquels. De plus, dans ce cas (Linux/Unix) il n'y a pas d'extension standard pour les exécutables, ce qui fait qu'une règle de suffixe ne pourrait pas s'appliquer dans ces situations simples. C'est pourquoi vous voyez toutes les règles pour construire les exécutables finaux énoncées explicitement.

Ce makefilechoisit la voie la plus absolument sure possible; il n'utilise que les concepts basiques de cible et dépendance, ainsi que des macros. De cette manière il est virtuellement garanti de fonctionner avec autant de programmes makeque possible. Cela a tendance à produire un makefileplus gros, mais ce n'est pas si grave

puisqu'il est géneré automatiquement par ExtractCode.cpp.

Il existe de nombreuses autres fonctions de makeque ce livre n'utilisera pas, ainsi que de nouvelles et plus intelligentes versions et variations de makeavec des raccourcis avancés qui peuvent faire gagner beaucoup de temps. Votre documentation favorite décrit probablement les fonctions avancées de votre make, et vous pouvez en apprendre plus sur makegrâce à Managing Projects with Makede Oram et Talbott (O'Reilly, 1993). D'autre part, si votre votre vendeur de compilateur ne fournit pas de makeou utilise un makenon-standard, vous pouvez trouver le make de GNU pour virtuellement n'importe quel système existant en recherchant les archives de GNU (qui sont nombreuses) sur internet.

3.12 - Résumé

Ce chapitre était une excursion assez intense parmi les notions fondamentales de la syntaxe du C++, dont la plupart sont héritées du C et en commun avec ce dernier (et résulte de la volonté du C++ d'avoir une compatibilité arrière avec le C). Bien que certaines notions de C++ soient introduites ici, cette excursion est principalement prévue pour les personnes qui sont familières avec la programmation, et doit simplement donner une introduction aux bases de la syntaxe du C et du C++. Si vous êtes déjà un programmeur C, vous pouvez avoir déjà vu un ou deux choses ici au sujet du C qui vous était peu familières, hormis les dispositifs de C++ qui étaient très probablement nouveaux pour vous. Cependant, si ce chapitre vous a semblé un peu accablant, vous devriez passer par le cours du cédérom Thinking in C: Foundations for C++ and Java(qui contient des cours, des exercices et des solutions guidées), qui est livré avec ce livre, et également disponible sur www.BruceEckel.com.

3.13 - Exercices

Les solutions de exercices suivants peuvent être trouvés dans le document électronique The Thinking in C++

Annotated Solution Guide, disponible à petit prix sur www.BruceEckel.com.

1 Créer un fichier d'en-tête (avec une extension ‘ .h’). Dans ce fichier, déclarez un groupe de fonctions qui varient par leur liste d'arguments et qui retournent des valeurs parmi les types suivants : void, char, int, and float. A présent créez un fichier .cppqui inclut votre fichier d'en-tête et crée les définitions pour toutes ces fonctions. Chaque fonction doit simplement imprimer à l'écran son nom, la liste des paramètres, et son type de retour de telle façon que l'on sâche qu'elle a été appelée. Créez un second fichier .cppqui inclut votre en-tête et définit int main( ), qui contient des appels à toutes vos fonctions. Compilez et lancez votre programme.

2 Ecrivez un programme qui utilise deux boucles forimbriquées et l'opérateur modulo ( %) pour détecter et afficher des nombres premiers (nombres entiers qui ne sont divisibles que pas eux-même ou 1).

3 Ecrivez un programme qui utilise une boucle whilepour lire des mots sur l'entrée standard ( cin) dans une string. C'est une boucle while“infinie”, de laquelle vous sortirez (et quitterez le programme) grâce une instruction break. Pour chaque mot lu, évaluez le dans un premier temps grâce à une série de ifpour

“associer” une valeur intégrale à ce mot, puis en utilisant une instruction switchsur cet entier comme sélecteur (cette séquence d'événements n'est pas présentée comme étant un bon style de programmation ; elle est juste supposée vous fournir une source d'entraînement pour vous exercer au contrôle de l'exécution).

A l'intérieur de chaque case, imprimez quelque chose qui a du sens. Vous devez choisir quels sont les mots

“intéressants” et quelle est leur signification. Vous devez également décider quel mot signalera la fin du programme. Testez le programme en redirigeant un fichier vers l'entrée standard de votre programme (Pour économiser de la saisie, ce fichier peut être le fichier source de votre programme).

4 Modifiez Menu.cpppour utiliser des instructions switchau lieu d'instructions if.

5 Ecrivez un programme qui évalue les deux expressions dans la section “précédence.”

6 Modifiez YourPets2.cpppour qu'il utilise différents types de données ( char, int, float, double,et leurs variantes). Lancez le programme et créez une carte de l'arrangement de mémoire résultant. Si vous avez accès à plus d'un type de machine, système d'exploitation, ou compilateur, essayez cette expérience avec autant de variations que you pouvez.

7 Créez deux fonctions, l'une qui accepte un string*et une autre qui prend un string&. Chacune de ces

fonctions devraient modifier l'objet stringexterne de sa propre façon. Dans main( ), créez et iniatilisez un objet string, affichez le, puis passez le à chacune des deux fonctions en affichant les résultats.

8 Ecrivez un programme qui utilise tous les trigraphes pour vérifier que votre compilateur les supporte.

9 Compilez et lancez Static.cpp. Supprimez le mot clé staticdu code, recompilez et relancez le, en expliquant ce qui s'est passé.

10 Essayez de compiler et de lier FileStatic.cppavec FileStatic2.cpp. Qu'est-il indiqué par le message d'erreur

? Que signifie-t-il ?

11 Modifiez Boolean.cpppour qu'il travaille sur des valeurs doubleplutot que des ints.

12 Modifiez Boolean.cppet Bitwise.cpppour qu'ils utilisent des opérateurs explicites (si votre compilateur est conforme au standard C++ il les supportera).

13 Modifiez Bitwise.cpppour utiliser les fonctions définies dans Rotation.cpp. Assurez vous d'afficher les résultats de façon suffisamment claire pour être représentative de ce qui se passe pendant les rotations.

14 Modifiez Ifthen.cpppour utiliser l'opérateur ternaire if-else( ?:).

15 Créez une structure qui manipule deux objets stringet un int. Utilisez un typedefpour le nom de la

structure. Créez une instance de cette struct, initialisez ses trois membres de votre instance, et affichez les.

Récupérez l'adresse de votre instance, et affichez la. Affectez ensuite cette adresse dans un pointeur sur le type de votre structure. Changez les trois valeurs dans votre instance et affichez les, tout en utilisant le pointeur.

16 Créez un programme qui utilise une énumération de couleurs. Créez une variable du type de cette enumet affichez les numéros qui correspondent aux noms des couleurs, en utilisant une boucle for.

17 Amusez vous à supprimer quelques unionde Union.cppet regardez comment évolue la taille des objets résultants. Essayez d'affecter un des éléments d'une unionet de l'afficher via un autre type pour voir ce qui se passe.

18 Créez un programme qui définit deux tableaux d' int, l'un juste derrière l'autre. Indexez la fin du premier tableau dans le second, et faites une affectation. Affichez le second tableau pour voir les changements que ceci a causé. Maintenant essayez de définir une variable charentre la définition des deux tableaux, et refaites un test. Vous pourrez créer une fonction d'impression pour vous simplifier la tâche d'affichage.

19 Modifiez ArrayAddresses.cpppour travailler sur des types de données char, long int, float,et double.

20 Appliquez la technique présentée dans ArrayAddresses.cpppour afficher la taille de la structet les adresses des éléments du tableau dans StructArray.cpp.

21 Créez un tableau de stringet affectez une string à chaque élément. Affichez le tableau grâce à une boucle for.

22 Créez deux nouveaux programmes basés sur ArgsToInts.cpppour qu'ils utilisent respectivement atol( )et atof( ).

23 Modifiez PointerIncrement2.cpppour qu'il utilise une unionau lieu d'une struct.

24 Modifiez PointerArithmetic.cpppour travailler avec des longet des long double.

25 Definissez une variable du type float. Récupérez son adresse, transtypez la en unsigned char, et affectez la à un pointeur d' unsigned char. A l'aide de ce pointeur et de [ ], indexez la variable floatet utilisez la fonction printBinary( )définie dans ce chapitre pour afficher un plan de la mémoire du float(allez de 0 à sizeof(float)).

Changez la valeur du floatet voyez si vous pouvez expliquer ce qui se passe (le floatcontient des données encodées).

26 Définissez un tableau d' ints Prenez l'adresse du premier élément du tableau et utilisez l'opérateur

static_castpour la convertir en void*. Ecrivez une fonction qui accepte un void*, un nombre (qui indiquera un nombre d'octets), et une valeur (qui indiquera la valeur avec laquelle chaque octet sera affecté) en

paramètres. La fonction devra affecter chaque octet dans le domaine spécifié à la valeur reçue. Essayez votre fonction sur votre tableau d' ints.

27 Créez un tableau constant ( const) de doubles et un tableau volatilede doubles. Indexez chaque tableau et utilisez const_castpour convertir chaque élément en non- constet non- volatile, respectivement, et affectez une valeur à chaque element.

28 Créez une fonction qui prend un pointeur sur un tableau de doubleet une valeur indiquant la taille du tableau.

La fonction devrait afficher chaque élément du tableau. Maintenant créez un tableau de doubleet initialisez chaque élément à zero, puis utilisez votre fonction pour afficher le tableau. Ensuite, utilisez

reinterpret_castpour convertir l'adresse de début du tableau en unsigned char*, et valuer chaque octet du tableau à 1 (astuce : vous aurez besoin de sizeofpour calculer le nombre d'octets d'un double). A présent utilisez votre fonction pour afficher les nouveaux résultats. Pourquoi, d'après vous, chaque élément n'est pas

égal à la valeur 1.0 ?

29 (Challenge) Modifez FloatingAsBinary.cpppour afficher chaque partie du doublecomme un groupe de bits séparé. Il vous faudra remplacer les appels à printBinary( )avec votre propre code spécialisé (que vous pouvez dériver de printBinary( )), et vous aurez besoin de comprendre le format des nombres flottants en parallèle avec l'ordre de rangement des octets par votre compilateur (c'est la partie challenge).

30 Créez un makefile qui compile non seulement YourPets1.cppet YourPets2.cpp(pour votre compilateur en particulier) mais également qui exécute les deux programmes comme cible par défaut. Assurez vous d'utiliser la règle suffixe.

31 Modifiez StringizingExpressions.cpppour que P(A)soit conditionné par #ifdefpour autoriser le code en déboggage à être automatiquement démarré grâce à un flag sur la ligne de commande. Vous aurez besoin de consulter la documentation de votre compilateur pour savoir comment définir des valeurs du

préprocesseur en ligne de commande.

32 Définissez une fonction qui prend en paramètre un doubleet retourne un int. Créez et initialisez un pointeur sur cette fonction, et appelez là à travers ce pointeur.

33 Déclarez un pointeur de fonction recevant un paramètre intet retournant un pointeur de fonction qui reçoit un charet retourne un float.

34 Modifiez FunctionTable.cpppour que chaque fonction retourne une string(au lieu d'afficher un message) de telle façon que cette valeur soit affichée directement depuis main( ).

35 Créez un makefilepour l'un des exercices précédents (de votre choix) qui vous permettra de saisir makepour un build de production du programme, et make debugpour un build de l'application comprenant les

informations de déboggage.