Vous êtes sur la page 1sur 124

Cours de C

Eric Berthomier Laurent Signac eric.berthomier@free.fr signac@sic.sp2mi.univ-poitiers.fr

Table des matires

1 Premiers pas 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 Prologue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple de programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Normalisation du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Petit mot sur ce quest une bibliothque . . . . . . . . . . . . . . . . . . . . . . . . . . . Un exemple de chier bibliothque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les diffrentes fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Squelette de programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les blocs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 7 7 8 9 9 10 10 11 11 11

1.10 Exercices dapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 Les variables (1 partie) 2.1 2.2 2.3 2.4 2.5 2.6 2.7 printf : fonction indispensable pour afcher le contenu dune variable . . . . . . . . . . . Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dclaration dune variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Application : exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation multiple du % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices dapplications directes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rutilisation dune variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15 15 15 16 16 17 17 17

2.8 2.9

Caractres spciaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices raliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17 18

3 Les variables (2 partie) 3.1 3.2 3.3 Exercice de mise en bouche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dclaration des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Saisie des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 Les conditions 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 Exercice de mise en bouche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les conditions : Si Alors Sinon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateurs logiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateurs logiques purs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vrai ou faux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Combinaison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Astuce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Les accolades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 Mise au point 5.1 5.2 5.3 5.4 5.5 5.6 Prologue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retour sur getchar() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Boucle Faire ... Tant que (vrai) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24 24 24 25

32 32 33 33 33 34 34 34 35 35

39 39 39 39 40 41 41

6 Et les shadocks pompaient 6.1 6.2 6.3 6.4 6.5 6.6 6.7 Prambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Et les Shadoks apprenaient que reprendre quivaut apprendre . . . . . . . . . . . . . . . Fonction toupper () . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . O tant que en emporte le Shadok . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Et les Shadoks continuaient pomper pour obtenir le rsultat . . . . . . . . . . . . . . . . Au clan des Shadoks, on trie, voyelles, chiffres premiers . . . . . . . . . . . . . . . . . .

45 45 45 46 46 47 47 48

7 Les boucles 7.1 7.2 7.3 7.4 Et les shadoks pdalrent pendant 15 tours . . . . . . . . . . . . . . . . . . . . . . . . . . Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Notion de double boucle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 3 : Et les Shadoks ftrent Nol... . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.1 7.4.2 7.4.3 7.5 Cne du sapin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Afchage du tronc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Afchage des boules de Nol . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54 54 55 56 57 57 57 57 58

Exercice 4 : Table Ascii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 Pointeurs et Fonctions 8.1 Variables : pointeurs et valeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 8.1.2 8.1.3 8.2 Les variables et la mmoire. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices dapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

62 62 62 63 64 64 64 65 65

Les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2.1 8.2.2 8.2.3 Dnition gnrale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variables globales et locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

8.2.4 8.2.5 8.2.6

Utilisation et modication de donnes dans les fonctions . . . . . . . . . . . . . . Pige ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 3 : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67 68 68

9 Tableaux & Chanes de caractres 9.1 Tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.1 9.1.2 9.1.3 9.2 Dnition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71 71 71 71 72 72 72 73 73 73 73 74 75 75 75 77 77 78 79

Chanes de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.2.6 9.2.7 9.2.8 9.2.9 Dclaration dune chane de caractres . . . . . . . . . . . . . . . . . . . . . . . . criture dans une chane de caractres . . . . . . . . . . . . . . . . . . . . . . . . Afchage dune chane de caractres . . . . . . . . . . . . . . . . . . . . . . . . . Longueur dun chane . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gets : saisie dune chane de caractres . . . . . . . . . . . . . . . . . . . . . . . . Passage dune chane de caractres en paramtres . . . . . . . . . . . . . . . . . . Bugs en chanes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.3

Correction des exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.1 9.3.2 9.3.3 Boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fonction de saisie (1re partie) . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fonction de saisie (2re partie) . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10 Fichiers et Structures 10.1 Bases sur les chiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Cration dun autre chier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

80 80 83 83

10.3.1 Dclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.3 Taille dune structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4 Fichiers et Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.5 Fin et commencement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6 Correction de lexercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

84 85 85 86 87 88

11 Curses 11.1 Concepts de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Quelques fonctions dafchage de Curses . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Localisation du curseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 Afchage de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.3 Effacement de la fentre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.4 Afchage dune chane de caractres . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.5 Afchage format dune chane de caractres . . . . . . . . . . . . . . . . . . . . 11.2.6 Botes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.7 Les anciennes fonctions dafchage . . . . . . . . . . . . . . . . . . . . . . . . . 11.3 1re utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4 Quelques fonctions de saisie de Curses . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.1 Saisie dun caractre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.2 Saisie dune chane de caractre . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.3 Saisie formate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5 Afchage de caractres spciaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6 Les couleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.1 Dnomination des couleurs : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6.2 Fonctions lies au couleurs : . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90 90 91 91 91 91 92 92 92 92 92 94 94 95 96 97 98 98 98

12 Le Jeu des Allumettes

100

12.1 Enonc de lexercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 12.2 Ce quil faut faire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 12.3 Aide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 12.4 Corrections de lexercice sans Curses . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 12.5 Corrections de lexercice avec Curses . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

13 Le Jeu de la Vie

109

13.1 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 13.2 Rgles du jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 13.3 Damier torique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 13.4 Implmentation du jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 13.4.1 Rappels utiles sur ncurses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 13.4.2 Algorithme du jeu de la vie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 13.4.3 Structures de donnes utilises . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 13.4.4 Difcults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 13.5 Possibilits damlioration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 13.5.1 Contrle interactif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 13.5.2 Afchage des coordonnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 13.5.3 Chargement de formes prdnies . . . . . . . . . . . . . . . . . . . . . . . . . . 114 13.6 Exemples obtenus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 13.7 Exemple de corrig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

A Code Ascii

119

B Bibliothque Asciiart

122

B.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 B.2 Utilisation de la bibliothque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 B.3 Fichier den-tte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 6

Chapitre 1

Premiers pas
1.1 Prologue
Ce cours est destin vous faire connatre le C sous Linux.

1.2 Exemple de programme


Voici pour exemple un premier programme qui fonctionne malgr le fait quil ne soit pas normalis. Celuici afche le mot Bonjour lcran. laide de votre diteur de texte favori, ouvrez un chier nomm programme1.c (1 programme du cours) puis tapez le texte suivant : programme1.c main () { puts ("Bonjour"); getchar (); }

ce moment, si vous entendez hurler, crier, pleurer, vomir ou tout autre ignominie de ce genre, cest normal, un puriste est pass derrire votre dos. Mais nous sommes l pour apprendre et il faut bien commencer par quelque chose. Une fois le texte du programme frapp, il faut le compiler, cest dire en analyser la syntaxe. Ceci se fait avec le compilateur gcc. Dans un premier temps, nous allons continuer dans le sale et compiler salement :

En ligne de commande, tapez : gcc

c programme1.c

Si vous navez pas fait derreur, ceci va vous donner un chier nomm programme1.o. Ce chier est nomm le chier objet. Le chier que vous avez pass en paramtre au compilateur se nomme le chier source (source de tous les bonheurs de Linux ...). An de pouvoir obtenir un chier excutable, il nous faut transformer le chier objet en un excutable. Pour cela, excutez la commande suivante : gcc o programme1 programme1.o Il ne reste plus qu excuter le programme : ./programme1 Et comme par magie, safchera alors Bonjour et attendra que vous appuyez sur la touche Entre. Code source : le code source reprsente le programme sous sa forme textuelle (en langage C).

1.3 Normalisation du programme


Bon, je lai dit prcdemment, nous avons fait dans le sale. Pourquoi me direzvous ? Eh bien rendons notre compilateur bavard en lanant la commande gcc c Wall programme1.c. Observez la borne dinsulte.

prog_1_1.c:5: warning: return-type defaults to int prog_1_1.c: In function main: prog_1_1.c:6: warning: implicit declaration of function puts prog_1_1.c:9: warning: control reaches end of non-void function

Peu comprhensible et cest normal. En fait, loption de compilation Wall permet de dclencher la production de messages soulignant toute technique autorise mais discutable , en deux mots viter. Nous allons donc normaliser ce programme. sa base, le langage C nest quun ensemble de bibliothques partir desquelles le compilateur trouve les fonctions et les applications qui lui permettent de crer un programme excutable. Exactement ce que vous fates lorsque vous recherchez dans une encyclopdie pour raliser un expos. Certaines bibliothque (les plus courantes) sont incluses dans des compilateurs ce qui permet notre programme de se compiler. Normalement puts a besoin de la bibliothque stdio.h. Pour ajouter une bibliothque, il suft dajouter #include <nom de la bibliothque> en dbut de programme. Le second point corriger est labsence de valeur de retour. La valeur de retour permet un programme ou lutilisateur de savoir si le programme que lon excute sest correctement termin. En gnral 0 signie une terminaison sans erreur. En lui rajoutant quelques lignes on obtient donc : programme2.c

#include <stdio.h> int main () { puts ("Bonjour"); getchar (); /* Permet dattendre la frappe dune touche */ return (0); } La valeur de retour nest pas obligatoire mais fortement conseille. Pour ne pas utiliser de valeur de retour, on utilise void main() la place de int main(). Le mot cl void peut se traduire par ne contenant rien . Attention : Dans le cas de void main(), on utilise return ; et non return(0) ;.

Le programme devient donc : programme3.c #include <stdio.h> void main () { puts ("Bonjour"); getchar (); return; } La normalisation nest pas nie, malgr tout. Pour tre au plus pur, il faudrait crire : int main (int argc, char** argv) Mais, pour tre explique, cette formulation elle seule ncessiterait tout le cours de programmation (les 15 cours ;-)). Donc nous en resterons l pour la normalisation.

1.4 Petit mot sur ce quest une bibliothque


linstar de ltudiant qui recherche dans des livres, on peut dire que le .h reprsente lindex du livre et le .c le contenu du chapitre concern, le .o ou .obj ntend que la forme pr compile du .c . Exemple : Lorsque le compilateur C rencontre le mot puts, il regarde dans chacun des .h dclar par linstruction #include si ce mot y est dni. Il trouve celui-ci dans la bibliothque stdio.h. linverse, sil ne le trouve pas, celui-ci mettra une erreur de syntaxe.

1.5 Un exemple de chier bibliothque


Vous trouverez ci-dessous, un extrait de la bibliothque stdio.h. On y retrouve notamment la dclaration de puts que lon voit dans ce cours et la dclaration de printf que lon verra dans le second cours. Vous trouverez ce chier dans le rpertoire /usr/include. 9

Extrait du chier stdio.h :

/* Write formatted output to STREAM. */ extern int fprintf __P ((FILE *__restrict __stream, __const char *__restrict __format, ...)); /* Write formatted output to stdout. */ extern int printf __P ((__const char *__restrict __format, ...)); /* Write formatted output to S. */ extern int sprintf __P ((char *__restrict __s, __const char *__restrict __format, ...)); /* Write formatted output to S from argument list extern int vfprintf __P ((FILE *__restrict __s, __const char *__restrict __format, _G_va_list __arg)); /* Write formatted output to stdout from argument extern int vprintf __P ((__const char *__restrict _G_va_list __arg)); /* Write formatted output to S from argument list extern int vsprintf __P ((char *__restrict __s, __const char *__restrict __format, _G_va_list __arg)); ARG. */

list ARG. __format, ARG. */

*/

/* Write a string, followed by a newline, to stdout. extern int puts __P ((__const char *__s));

*/

1.6 Les diffrentes fonctions


puts : permet dafcher du texte suivi dun retour la ligne. getchar : permet dattendre la frappe dune touche suivie dun retour chariot ou un retour chariot seul. /* Commentaire*/ : permet de mettre un commentaire. On trouvera aussi // qui permet de mettre le reste de la ligne en commentaire. Notre programme afche bonjour et attend que lon appuie sur une touche an que lon puisse voir ce quil a crit.

1.7 Squelette de programme


On peut dnir le squelette dun programme C de la faon suivante :

10

/* Dclaration des bibliothques */ int main () { /* Dclaration des variables */ cf. chapitre 2 /* Corps du programme */ getchar();/* Facultatif mais permet dattendre lappui dune touche */ return (0);/* Aucune erreur renvoye */ }

1.8 Les blocs


La partie de programme situe entre deux accolades est appele un bloc. Je conseille de prendre lhabitude de faire une tabulation aprs le retour la ligne qui suit laccolade. Puis retirer cette tabulation aprs laccolade fermante du bloc. Ainsi, on obtient :

{ Tabulation Tout le code est frapp cette hauteur } Retrait de la tabulation Tout le texte est maintenant frapp cette hauteur.

Cette mthode permet de contrler la fermeture des accolades et de leurs correspondances.

1.9 Les commentaires


Commenter signie quune personne ne connaissant pas le langage C doit pouvoir lire le programme et le comprendre. Les commentaires sont indispensables dans tout bon programme. Les commentaires peuvent tre placs nimporte quel endroit dans le programme. Ils commencent par /* et se terminent par */. /* Commentaire */ Vous trouverez aussi : // Le reste de la ligne est un commentaire

1.10 Exercices dapplication


1. crire un programme qui crit au revoir. 2. crire un programme qui : crit Salut toi, appuie sur une touche sil te plat

11

Attend lappui dune touche crit Merci davoir appuy sur une touche 3. Commentez le prcdent programme. Par exemple : puts ("Cours de programmation" ) ; /* Ecrit Cours de programmation lcran */ 4. crire un programme qui crit : Hamlet says To be or not to be, that is the question.

12

Corrigs des exercices du chapitre 1


Ecrire un programme qui crit au revoir. programme4.c #include <stdio.h> void main() { puts("Au revoir "); /* Affiche Au revoir */ getchar (); } Ecrire un programme qui : 1. Ecrit Salut toi, appuie sur une touche sil te plat 2. Attend lappui dune touche 3. Ecrit Merci davoir appuy sur une touche programme5.c #include <stdio.h> int main () { puts ("Salut toi, appuie sur une touche sil te plat"); /* Affiche le message Salut toi, ... sil te plat */ getchar (); /* Attend la frappe dune touche */ puts ("Merci davoir appuy sur une touche"); /* Affiche le message Merci davoir appuy sur une touche */ return (0); }

Commentez le prcdent programme. Dj fait !

13

Ecrire un programme qui : Ecrit : Hamlet says To be or not to be, that is the question. programme6.c #include <stdio.h> int main() { puts ("Hamlet says To be or not to be, that is the question."); getchar(); return (0); }

14

Chapitre 2

Les variables (1 partie)


2.1 printf : fonction indispensable pour afcher le contenu dune variable
programme7.c #include <stdio.h> int main () { printf ("Coucou cest moi\n"); /* Affiche Coucou cest moi lcran */ getchar(); /* Attendre lappui dune touche */ return (0); } On pourrait dire que la fonction printf est la mme que linstruction puts vue prcdemment mais il nen est rien... Celle-ci est beaucoup, beaucoup, beaucoup plus puissante. Syntaxe : La syntaxe de printf est trs complexe et pourrait elle seule faire lobjet dun cours, nous en verrons donc des applications au fur et mesure des besoins.

2.2 Variable
Comme son nom lindique une variable est quelque chose qui varie. Cest vrai mais ce nest pas sufsant. Une variable peut tre considre comme une bote dans laquelle on met des donnes que lon peut lire ou crire. La manire la plus facile de lire le contenu dune variable est la fonction printf que lon a aperue prcdemment. La manire la plus simple de donner une valeur une variable est loprateur mathmatique =. crire dans une variable ayant dj une valeur revient la modier.

15

Une variable ne peut contenir quune seule chose la fois. Si vous mettez une seconde donne dans la variable, la prcdente est efface.

2.3 Dclaration dune variable


La dclaration dune variable se fait simplement en crivant : <son type> <son nom> ; Exemples de type de variables : char : caractre int : entier

2.4 Application : exemple


programme8.c #include <stdio.h> int main () { int i; /* i : variable de type entier */ char car; /* car: variable de type caractre */ i = 65; /* i vaut 65 */ car = E; /* car vaut E */ printf ("i vaut %d.\n", i); /* Affiche la valeur de i */ printf ("car vaut %c.\n",car); /* Affiche la valeur de car */ getchar(); /* Attendre lappui dune touche */ return (0); } Explications : 1. On met dans la variable i la valeur 65. 2. On met dans la variable car la valeur de E. Note : En informatique, tout nest que nombre, je dis donc la valeur de E et non E car cest le code Ascii de E qui est sauvegard dans cette variable. Nous reviendrons l dessus un peu plus tard. 3. printf ("i vaut %d.\n", i) ; : %d signie que lon attend une valeur entire, le programme va donc remplacer le %d par la valeur de i. 4. printf ("car vaut %c \n", car) ; : %c signie que lon attend une valeur de type caractre, le programme va donc remplacer le %c par la valeur de car. \n permet de raliser un retour chariot cest dire un retour la ligne.

16

2.5 Utilisation multiple du %


Le code %x signie que le compilateur C doit remplacer ce code par la valeur correspondante (qui lui est fourni dans la suite de linstruction) en la transformant dans le type x. Cette transformation est appel un cast. Exemple :

int i; i =65; printf ("Le caractre %d est %c",i,i); nous donnera lafchage suivant : Le caractre 65 est A. Le %d est remplac par la valeur numrique de i cest dire 65. Le %c est remplac par la valeur alphanumrique (ASCII) de i cest dire A (cf. Table Ascii en Annexe).

2.6 Exercices dapplications directes


1. En utilisant ce qui a t fait prcdemment, fates afcher les valeurs 70, 82, 185 et 30. 2. En utilisant ce qui a t fait prcdemment, fates afcher, les caractres c, o, u, C, O, U.

2.7 Rutilisation dune variable


On peut rutiliser une variable autant de fois que lon veut, la prcdente valeur tant efface : i = 3 ; i = 5 ; i = 7 ; donnera au nal pour valeur de i la valeur 7. car = E ; car = G ; car = h ; donnera au nal pour valeur de car la valeur de h.

2.8 Caractres spciaux


Certains caractres utiliss par la fonction printf ( % par exemple) ou mme tout simplement pour dclarer une variable ( pour les caractres par exemple) obligent utiliser le caractre de sufxe \ pour pouvoir tre afchs. Pour afcher un % avec printf jcrirai : printf("La rduction tait de 20 \%") ; Pour dclarer un caractre avec la valeur (prononce quote en informatique et non pas apostrophe (franais)), on crira : char car ; car = \ ; Exemple :

17

2.9 Exercices raliser


1. Faire un programme qui ralise lafchage suivant en utilisant les variables. Aide : Sans retour chariot, on afche la suite. Coucou 17 2. De la mme faon, raliser un programme qui ralise lafchage suivant : C O U Cou 1 2 3 456 Cest rigolo Rappel : Pour mettre une variable c gale on crit c=\ 3. Ecrire un programme qui crit : Hamlet says "To be or not to be, that is the question." avec les " bien sr. Rappel : Pour pouvoir afcher un caractre de syntaxe C, par exemple ", on utilise le caractre \ comme prxe ce caractre. Pour obtenir un ", on utilise donc \".

18

Corrigs des exercices du chapitre 2


Faites afcher, en utilisant ce qui a t fait prcdemment, les valeurs 70, 82, 185 et 30. programme9.c #include <stdio.h> int main () { int i,a,b,c; i=70; a=82; b=185; c=30; printf ("i printf ("a printf ("b printf ("c getchar(); vaut vaut vaut vaut %d.\n",i); %d.\n",a); %d.\n",b); %d.\n",c);

return (0); }

19

Faites afcher, en utilisant ce qui a t fait prcdemment, les caractres c, o, u, C, O, U. programme10.c #include <stdio.h> int main () { char a,b,c,d,e,f; a=c; b=o; c=u; d=C; e=O; f=U; printf printf printf printf printf printf printf ("a vaut %c.\n",a); ("b vaut %c.\n",b); ("c vaut %c.\n",c); ("d vaut %c.\n",d); ("e vaut %c.\n",e); ("f vaut %c.\n",f); ("a, b, c, d, e, f valent : %c, %c, %c, %c, %c, %c.\n",a,b,c,d,e,f);

getchar(); return (0); }

20

Faire un programme qui ralise lafchage : Coucou 17 programme11.c #include <stdio.h> int main () { char car = C; int nbre = 17; printf ("%c",car); car = o; printf ("%c",car); car = u; printf ("%c",car); car = c; printf ("%c",car); car = o; printf ("%c",car); car = u; printf ("%c",car); printf ("\n%d\n",nbre); /* Attente */ getchar(); return (0); }

21

Faire un programme qui ralise lafchage : C O U Cou 1 2 3 456 Cest rigolo programme12.c #include <stdio.h> int main () { char car = C; int nbre = 1; car = C; printf ("\n%c",car); car = O; printf ("\n%c",car); car = U; printf ("\n%c",car); car = C; printf ("\n%c",car); car = o; printf ("%c",car); car = u; printf ("%c",car); printf ("\n%d",nbre); nbre = 2; printf ("\n%d",nbre); nbre = 3; printf ("\n%d",nbre); nbre = 456; printf ("\n%d",nbre); car = C; printf ("\n%c",car); car = \; printf ("%c",car); car = e; printf ("%c",car); car = s; printf ("%c",car); car = t; printf ("%c",car); car = ; printf ("%c",car); car = r; printf ("%c",car); car = i; printf ("%c",car); car = g; printf ("%c",car); car = o; printf ("%c",car); car = l; printf ("%c",car); car = o; printf ("%c\n",car); /* Attente */ getchar(); return (0); }

22

Faire un programme qui crit : Hamlet says "To be or not to be, that is the question." programme13.c #include <stdio.h> int main () { printf ("Hamlet says : \"To be or no to be, that is the question.\"\n"); /* Attente */ getchar(); return (0); }

23

Chapitre 3

Les variables (2 partie)


Durant tout ce chapitre, nous aurons pour but simple, mais complet et complexe dans sa programmation, de faire une malheureuse calculatrice. Attention : An de pouvoir utiliser la bibliothque mathmatique du C (#include <math.h>), il est ncessaire dajouter au moment de ldition de liens -lm ce qui nous donne :

gcc -o monprog monprog.o -lm

3.1 Exercice de mise en bouche


Ecrire un programme qui : crit Calculatrice : et saute 2 lignes ; crit Valeur de a : et saute 1 ligne ; attend lappui dune touche ; crit Valeur de b : et saute 1 ligne ; attend lappui dune touche ; crit Valeur de a + b : ; Pas pas, nous allons maintenant raliser notre petit programme de calculatrice.

3.2 Dclaration des variables


Compltez le programme en : dclarant 2 variables a et b de type int (entier) ; assignant ces deux variables les valeurs 36 et 54 ; faisant afcher le rsultat de la somme de a + b (et non pas en faisant afcher 90 !). Pour faire afcher le rsultat il est possible dutiliser la fonction printf directement ou indirectement en utilisant une troisime variable. Pour plus de facilit, nous allons utiliser un afchage direct. Celui-ci

24

seffectue de la faon suivante : printf ("Valeur de a + b : %d",a+b) ; Le %d est remplac par la valeur de a+b.

3.3 Saisie des variables


Si une calculatrice se limitait excuter la somme de deux nombres xes, le boulier serait encore de mise. Pour saisir une variable, il est ncessaire dutiliser la fonction scanf. La fonction scanf sutilise de la faon suivante : Saisie de la valeur a : scanf ("%d", &a) ; Comme pour printf, on reconnat le %d pour la saisie dun nombre entier. Le & devant le a signie que lon va crire dans la variable a. Ae... En fait &a signie ladresse mmoire de a . La fonction scanf va donc crire dans lemplacement mmoire (la petite bote contenant la variable) de a. Si lon oublie le &, on crira chez quelquun dautre, une autre adresse. Et l a peut faire mal, trs mal...Mais ceci est une autre histoire. Nous allons maintenant saisir les variables a et b. Pour exemple, je mets ici le code pour la saisie de a, la saisie de b reste faire par vos soins titre dexercice.

/* Saisie de la valeur de a */ printf ("Valeur de a :\n"); scanf ("%d",&a);

Il est conseill dinitialiser les variables avant de les utiliser. Au dbut du programme, aprs leur dclaration, assignez a et b la valeur 0. Exemple : a = 0; Si tout sest bien pass, vous avez maintenant entre les mains une super calculatrice qui ralise des additions ! N.B. Appuyez sur la touche Enter (Entre) aprs avoir tap votre valeur.

Pour aller plus rapidement, il est possible dinitialiser une variable dans le mme temps que sa dclaration. Pour cela, rien de plus simple, ajoutez la n de la dclaration = suivi de la valeur dinitialisation : Exemple : int i = 10 ;

Evolution du logiciel : exercice Ae ae ae, dur dur dtre informaticien. Jai envie de faire une super calculatrice et je me dis quen fait la simplicit qui a eu lieue tout lheure nest pas forcment adapte lvolution dsire. Dclarer une troisime valeur de type int (penser linitialiser 0) que lon nommera btement s comme somme. Une fois les valeurs de a et b saisies, initialisez s avec la valeur de a + b. Comme en mathmatiques lmentaires. Afchez la valeur de s. On devrait avoir les mme rsultats quauparavant, bien sr.

25

Exercices dapplication : Ralisez 2 petits programmes qui font : la soustraction de 2 nombres ; la multiplication de 2 nombres. Un nouveau type : les nombres virgule ou ottants (float). Le type float permet de dclarer un nombre virgule. Transformez les 3 prcdents programmes en utilisant le type float au lieu du type int et %f pour saisir les valeurs de a et b, et pour afcher le rsultat. Petite aide : Ce petit morceau de programme saisit la valeur de a et la fait afcher :

float a; printf ("Saisie de a :"); scanf ("%f",&a); printf ("\na vaut : %f",a); getchar ();

Pour un afchage plus agrable il est possible de xer le nombre de chiffres aprs la virgule de la faon suivante : %.[nombre de chiffres aprs la virgule]f Exemple : printf ("%.2f",a) ; Ouah, les 4 oprations ! ! ! Crer un quatrime programme qui ralise la division de deux nombres. Tester avec une division par 0 ! ! ! La solution ce petit problme sera vu dans le cours sur les conditions (if).

Exercices raliser Complter les 4 programmes an de raliser les oprations suivantes : s = a + b + c s = a -b-c s = a / b / c s = a * b * c o a,b et c sont des nombres virgules (float). La fonction abs permet dobtenir la valeur absolue dun nombre entier. Utiliser cette fonction pour calculer la valeur absolue de (a-b). Exemple dutilisation de abs : S = abs (a-b) ; La fonction ceil permet dobtenir larrondi entier suprieur dun nombre rel. Utiliser cette fonction pour calculer larrondi suprieur de (a / b). Exemple dutilisation de ceil : S = ceil (a/b) ;

26

Corrigs des exercices du chapitre 3


Soustraction de 2 nombres programme14.c #include <stdio.h> #include <math.h> int main () { int a,b; int d; a=0; b=0; printf("Calculatrice :\n\n"); printf("Valeur de a : "); scanf("%d",&a); printf("\n"); printf("Valeur de b : "); scanf("%d",&b); d=a-b; printf("Valeur de a-b : %d\n",d); getchar (); return (0); }

/* Dclaration des variables */ /* Diffrence entre les 2 nombres */ /* Initialisation des variables */

/* Affichage de la diffrence */

27

Multiplication de 2 nombres programme15.c #include <stdio.h> #include <math.h> int main () { int a,b; int m; a=0; b=0; printf("Calculatrice :\n\n"); printf("Valeur de a : "); scanf("%d",&a); printf("\n"); printf("Valeur de b : "); scanf("%d",&b); m = a*b; printf("Valeur de a*b : %d\n", m); /* Affichage de la multiplication */ getchar (); return (0); }

/* Dclaration des variables */ /* Rsultat de la multiplication */ /* Initialisation des variables */

28

Transformez les 3 prcdents programmes avec le type float Aucune difcult dans cet exercice, je ne mettrai ici la correction que de la multiplication, les autres oprations se ralisent sur le mme schma. programme16.c #include <stdio.h> #include <math.h> int main () { float a,b; float m; a=0; b=0; printf("Calculatrice :\n\n"); printf("Valeur de a : "); scanf("%f",&a); printf("\n"); printf("Valeur de b : "); scanf("%f",&b); m = a*b; printf("Valeur de a*b : %f\n", m); /* Affichage de la multiplication */ getchar (); return (0); }

/* Dclaration des variables */ /* Rsultat de la multiplication */ /* Initialisation des variables */

Pour laddition :

m = a + b; printf ("Valeur de a+b : %f", m);

Pour la soustraction :

m = a - b; printf ("Valeur de a-b : %f", m);

29

Calculer la somme a + b + c programme17.c #include <stdio.h> #include <math.h> int main () { float a,b,c,s; a=0; b=0; c=0; s=0; printf("Saisie de a : "); scanf("%f",&a); printf("Saisie de b : "); scanf("%f",&b); printf("Saisie de c : "); scanf("%f",&c); s = a+b+c; printf("Valeur de s : %.2f\n",s); getchar (); return (0); }

/* Dclaration des variables */ /* Initialisation des variables */

/* Saisie variables flottantes */

/* Calcul de la somme */ /* Affichage de la somme */

30

Calculer la diffrence a - b - c

d = a-b-c; printf("Valeur de d : %.2f\n",d);

/* Calcul de la diffrence */ /* Affichage de la diffrence */

Calculer la multiplication a * b * c

m = a*b*c; printf("Valeur de m : %.2f\n",m);

/* Calcul de la multiplication */ /* Affiche la multiplication */

Calculer la division a / b / c

d = a/b/c; printf("Valeur de d : %.2f\n",d); Calculer la valeur absolue de a - b

/* Calcul de la division */ /* Affichage de la division */

r=abs(a-b); printf("Valeur de r : %f\n",r); Calculer larrondi de a + b

/* Calcul de la valeur absolue */ /* Affiche la valeur absolue */

c=ceil(a/b); printf("Valeur de c : %f\n",c);

/* Calcul de larrondi */ /* Affichage de larrondi */

Il aurait t possible dutiliser %d du fait que larrondi est un nombre entier !

31

Chapitre 4

Les conditions
4.1 Exercice de mise en bouche
Ecrire un programme qui met en application le thorme de Pythagore pour calculer lhypothnuse dun triangle rectangle. Rappel : Dans un triangle rectangle, lhypothnuse (le plus grand ct) peut se calculer en applicant la formule suivante : o a et b sont les longueurs des cts hypothnuse = adjacents langle droit. Notes : La racine carre sobtient par lutilisation de la fonction sqrt (valeur) contenue dans la bibliothque math.h. (#include <math.h>) peut sobtenir par a*a. Mthodologie : 2. Faire saisir a au clavier. 3. Faire saisir b au clavier. 4. Effectuer lopration de la racine carre et afcher le rsultat. Attention : An de pouvoir utiliser la bibliothque mathmatique du C (#include <math.h>), il est ncessaire dajouter au moment de ldition de liens -lm ce qui nous donne :

1. Rechercher les variables ncessaires et les dclarer dans le programme.

gcc -o monprog monprog.o -lm

32

4.2 Les conditions : Si Alors Sinon


if (condition vraie) { instructions 1 } else { instructions 2 } si (condition vraie) { alors faire instructions 1 } sinon { faire instructions 2 }

Les conditions sexpriment avec des oprateurs logiques.

4.3 Oprateurs logiques


Ils servent comparer deux nombres entre eux.

Libell Infrieur Suprieur Egal Diffrent Infrieur ou gal Suprieur ou gal

Oprateur < > == != <= >=

4.4 Oprateurs logiques purs


Ce sont des oprateurs logiques permettant de combiner des expressions logiques.

Libell Et (and) Ou (or) Non (not)

Oprateur && || !

| se nomme en informatique un pipe (prononcer pape). 33

4.5 Vrai ou faux


La valeur Vrai peut tre assimile la valeur numrique 1 ou toute valeur non nulle. La valeur Faux peut tre assimile la valeur numrique 0. Loprateur Ou (||) correspond alors une addition.

Ou Vrai Faux

Vrai Vrai Vrai

Faux Vrai Faux

+ 1 0

1 2 1

0 1 0

Loprateur Et (&&) correspond alors une multiplication Et Vrai Faux Vrai Vrai Faux Faux Faux Faux * 1 0 1 1 0 0 0 0

On notera que !Vrai = Faux et !Faux = Vrai.

4.6 Combinaison
Toutes les oprations logiques peuvent se combiner entre elles. La seule condition dutilisation dun si (if) avec de telles combinaisons est de lentourer de (). Exemple : if ((car == a) || (car == A))

4.7 Astuce
Vous verrez souvent ce type de code crit :

if (er) { /* Alors faire quelque chose */ }

En appliquant ce qui a t vu prcdemment, on en dduit que ce code signie que

si (er != 0) /* si er diffrent de 0 */ { /* Alors faire quelque chose */ }

34

4.8 Les accolades


Les accolades entourant les blocs dinstructions dune condition peuvent tre omises si le bloc nest constitu que dune seule instruction. Exemple :

if (car == b) printf ("car vaut b."); else printf ("car est diffrent de b.");

4.9 Exercices
1. Faites saisir une variable de type entier et indiquez lutilisateur si celle-ci est strictement positif ou strictement ngatif ou nulle. Aide : if (a>0) printf ("Valeur positive"); else printf ("Valeur ngative"); 2. Faites saisir une variable de type caractre et indiquez lutilisateur si celle-ci est une voyelle ou une consonne. On considrera que le caractre saisi est en minuscule.

35

Corrections des exercices du chapitre 4


crire un programme qui met en application le thorme de Pythagore. programme18.c #include <stdio.h> #include <math.h> int main () { float a; /* base du triangle */ float b; /* ct du triangle rectangle */ float p; /* valeur de lhypotnuse (p pour Pythagore !) */ /* Initialisation des variables pour palier aux erreurs */ a = 0; b = 0; /* Saisie de a */ printf ("Valeur de la base : "); scanf ("%f",&a); /* Saisie de b */ printf ("Valeur du ct : "); scanf ("%f",&b); /* Calcul par Pythagore */ p = sqrt (a*a + b*b); /* Affichage du rsultat */ printf ("Lhypotnuse mesure : %.2f\n",p); /* Attendre avant de sortir */ getchar (); return (0); }

36

Tester le signe dune valeur saisie au clavier. programme19.c #include <stdio.h> int main () { /* Valeur que lon va saisir */ int a = 0; /* Saisie de a */ printf("Saisie de a : "); scanf("%d",&a); /* Test condition a<0 */ if (a<0) { printf("la variable a est ngative.\n"); } else { /* Test condition a>0 */ if (a>0) { printf("la variable a est positive\n"); } /* Sinon a est nulle */ else { printf("la variable a est nulle\n"); } } getchar (); return (0); }

37

Tester si un caractre saisi au clavier est une consonne ou une voyelle. programme20.c #include <stdio.h> int main () { /* Valeur que lon va saisir */ char car; /* Saisie du caractre a */ printf("Saisie du caractre : "); scanf("%c",&car); /* Test condition car voyelle minuscule */ if ((car == a) || (car == e) || (car == i) || (car == o) || (car == u) || (car == y)) { printf("la variable car est une voyelle.\n"); } else { printf("la variable car est une consonne.\n"); } getchar (); return (0); }

38

Chapitre 5

Mise au point
5.1 Prologue
Lobjet de ce cours est de raliser un petit break dans lapprentissage du C et de sattacher voir ce que lon est capable de raliser avec le peu de moyen que lon a. Ce cours sera donc constitu de 3 exercices de difcult croissante avec apprentissage dune nouvelle fonction et dun exercice complet de programmation.

5.2 Exercice 1
Raliser un programme qui saisisse un nombre et indique lutilisateur si celui-ci est plus grand ou plus petit quun autre nombre x par le programme. Exemple :

si (nbre_saisi<10) alors "plus petit" Reprendre lexercice du chapitre 4 qui disait si un nombre est strictement positif, strictement ngatif ou nul.

5.3 Retour sur getchar()


La fonction getchar () permet dattendre la frappe dun caractre au clavier, de le lire et de le renvoyer. 2 utilisations peuvent tre faites de getchar (), la premire est celle permettant dattendre la frappe dune touche sans se soucier de sa valeur, la seconde est celle permettant de lire un caractre au clavier.

39

Exemples : 1. Attente getchar () ; 2. Saisie dun caractre char car ; car = getchar () ; A chaque fois, getchar () effectue le mme traitement : Attendre la frappe dune touche au clavier suivi dun retour chariot (Entre). Renvoyer le caractre frapp. Dans le 1er cas, ce caractre nest simplement pas rcupr.

5.4 Boucle Faire ... Tant que (vrai)


Do ... while, traduisez par Faire ... Tant que permet de raliser une suite dinstructions tant quune condition ou un ensemble de conditions est rempli. Exemple : programme21.c #include <stdio.h> int main () { char car; int sortie; do { printf ("Tapez S pour sortir !\n"); /* On saisit un caractre */ car = getchar (); /* On le compare pour savoir si lon peut sortir */ sortie = ((car == s) || (car == S)); } while (!sortie); return (0); }

Rappel : Un nombre entier vaut la valeur logique vraie si celui-ci est diffrent de 0. Un nombre entier vaut la valeur logique faux si celui-ci est gal 0. || signie un ou logique (or). Remarque : Cette utilisation nest pas trs belle, le retour chariot utilis pour la saisie du caractre tant renvoy et interprt nous donne un afchage double. Malgr cel, au niveau de ce cours, nous nous en contenterons.

40

5.5 Exercice 2
Tapez lexemple prcdent, amnagez le, comprenez le, puis transformez le an que lon sorte de la boucle uniquement lorsque lutilisateur a tap le nombre 10. Attention : La saisie dun nombre ne se fait pas par getchar mais par scanf (cf. Chapitre 3).

5.6 Exercice 3
Voici un petit exemple de programme qui permet dobtenir des nombres alatoires entre 0 et 100. programme22.c #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int nb_alea; /* Nombre alatoire */ srand (time (NULL)); /* Initialisation des nombres alatoires */ /* Le nombre alatoire est stock dans une variable puis affich */ nb_alea = (int) (((float) rand () / RAND_MAX) * 100); printf ("%d",nb_alea); getchar (); return (0); }

srand (time (NULL)) permet dinitialiser le systme alatoire. rand () permet dobtenir un nombre entre 0 et RAND_MAX. (float) rand () permet de dire au langage C que lon dsire raliser des calculs avec des nombres virgules (ottants). ((float) rand () / RAND_MAX) permet dobtenir un nombre entre 0 et 1, qui multipli par 100 nous donne un nombre entre 0 et 100. En vous aidant de ce petit programme et de ce qui a t fait prcdemment, ralisez un petit jeu qui : 1. Initialise un nombre entre 0 et 100 ; 2. Tente de faire deviner ce nombre lutilisateur en lui indiquant sil est plus petit ou plus grand.

41

Corrigs des exercices du chapitre 5


programme23.c #include <stdio.h> int main () { int nb_choisi = 33; int nb_saisi = 0; printf ("Votre nombre : "); scanf ("%d",&nb_saisi); if (nb_choisi < nb_saisi) printf ("Mon nombre est plus petit.\n"); else { if (nb_choisi == nb_saisi) printf ("Mon nombre est gal.\n"); else printf ("Mon nombre est plus grand.\n"); } /* Attente */ getchar (); return (0); }

42

programme24.c #include <stdio.h> #include <stdlib.h> int main () { int valeur; do { printf ("Votre nombre : "); scanf ("%d",&valeur); } while (valeur != 10); return (0); }

43

programme25.c #include <stdio.h> #include <stdlib.h>/* pour les valeurs alatoires */ #include <time.h> int main () { int nb_hasard = 0; int votre_nb = 0;

srand (time (NULL)); nb_hasard = (int) (((float) rand () / RAND_MAX) * 100); /* Nombre entre 0 et 100 do { printf("Votre nombre : "); scanf("%d",&votre_nb); if (nb_hasard < votre_nb) printf ("\nMon nombre est plus petit\n"); else { if (nb_hasard > votre_nb) /* il peut tre aussi gal ... */ printf ("\nVotre nombre est plus grand\n"); } } while (votre_nb != nb_hasard); printf ("Trouv\n"); getchar (); return (0); }

44

Chapitre 6

Et les shadocks pompaient


6.1 Prambule
Du fait que la fonction getchar() attend lappui de la touche Enter, nous allons utiliser une bibliothque cre pour le cours. Cette bibliothque se nomme ASCIIART et est dtaille en annexe. Elle donne entre autres accs la fonction getch() qui permet la saisie dun caractre sans attente de retour chariot. Pour lutiliser, il nous faut : ajouter #include "asciiart.h" notre programme (ce chier est livr avec la bibliothque) ; linker le programme avec asciiart.o : gcc -o mon_prog mon_prog.o asciiart.o Vous pouvez utiliser cette fonction dans les exercices, chaque fois que vous souhaitez attendre lappui dune touche. Une fonction similaire (getche()) fait le mme travail mais afche le caractre Entre. On remarquera que le #include est diffrent de celui utilis prcdemment, les <...> ont t remplacs par des " ". Lexplication en est simple, les bibliothques du compilateur sont insres via #include <nom de la bibliothque> et les personnelles sont insres via #include "nom de la bibliothque". A noter que dans le cas dune bibliothque personnelle, celle-ci doit se situer dans le mme rpertoire que le programme source (du moins on le considrera dans le cadre de ce cours).

6.2 While
De la mme faon que do {...} while(condition) ; , il est possible dutiliser : while (condition == Vrai) {...}

45

Exemple :

char car = ; while ((car != s) && (car != S)) { car = getche (); }

Attention : while (condition) ; signie que tant que condition est vrai, on revient la mme ligne. Si condition est toujours vraie, on tombe alors dans un puts. Si condition est fausse, on passe alors immdiatement la ligne/commande suivante.

6.3 Et les Shadoks apprenaient que reprendre quivaut apprendre


Exercice 1 prenez : Traduisez en langage C, compltez avec les variables ncessaires, compilez, excutez, com-

Faire Saisir une touche Tant Que (touche != S) et (touche != s) Exercice 2 prenez : Traduisez en langage C, compltez avec les variables ncessaires, compilez, excutez, com-

Faire Saisir un nombre Tant Que (nombre != 10)

Attention : La saisie dun nombre ne se fait pas par la fonction getch () mais par la fonction scanf (reportez vous au chapitre correspondant pour plus de prcisions).

6.4 Fonction toupper ()


Le problme de la comparaison de la minuscule et de la majuscule de lexercice 1 peut tre contourn par lutilisation de la fonction toupper (#include <ctype.h>) qui transforme un caractre minuscule en majuscule.

46

La fonction toupper sutilise de la faon suivante :

int main () { char car; char car_min; car_min = a car = toupper (car_min); printf ("%c",car); return (0); } Le programme prcdent afchera A.

6.5 O tant que en emporte le Shadok


Exercice 3 Ecrire le programme : Tant que je ne tape pas un nombre impair compris entre 1 et 10 je recommence la saisie dun nombre Exercice 4 Ecrire le programme : Tant que je ne tape pas une voyelle je recommence la saisie dune touche

6.6 Et les Shadoks continuaient pomper pour obtenir le rsultat


Dans les exercices qui suivent, la notion de compteur intervient. Un compteur est une variable numrique que lon dcrmente (-1) ou incrmente (+1) suivant nos besoins.

Exemples :

int i; i++; i--; i++; i--; /* /* /* /* Incrmente le compteur i */ Dcrmente le compteur i */ revient la mme chose que i=i+1;*/ revient la mme chose que i = i-1;*/

Dans les exemples prcdents, le nombre de caractres entrs peut donc tre comptabilis en ajoutant 1 une variable chaque fois quune touche est frappe. Exercice 5 Ecrire le programme : Tant que je nai pas saisi 10 caractres, je recommence la saisie dune touche 47

Exercice 6 Ecrire le programme : Tant que je nai pas saisi 10 nombres, je recommence la saisie dun nombre

6.7 Au clan des Shadoks, on trie, voyelles, chiffres premiers


Exercice 7 Ecrire le programme : Tant que je nai pas saisi 10 voyelles, je recommence la saisie dune touche On prendra soin dindiquer lutilisateur combien de voyelles il lui reste entrer. Exercice 8 Ecrire le programme : Tant que je nai pas saisi 10 chiffres premiers (1,3,5,7), je recommence la saisie dun chiffre On prendra soin dindiquer lutilisateur combien de chiffres premiers il lui reste entrer.

48

Corrigs des exercices du chapitre 6


Exercice 1 programme26.c #include <stdio.h> #include "asciiarth" int main () { char car = 0; printf ("Tapez S pour arrter ...\n"); do { car = getch (); } while ((car != s) && (car != S)); return (0); }

Exercice 2 programme27.c #include <stdio.h> int main () { int nbre = 0; printf ("Tapez 10 pour arrter ...\n"); do { scanf ("%d", &nbre); } while (nbre != 10); return (0); }

49

Exercice 3 programme28.c #include <stdio.h> int main () { int nbre = 0; printf ("Tapez un chiffre impair pour arrter ...\n"); while ((nbre != 1) && (nbre != 3) && (nbre != 5) && (nbre != 7) && (nbre != 9)) { scanf ("%d", &nbre); } return (0); }

ou bien : programme29.c #include <stdio.h> int main () { int nbre = 0; printf ("Tapez un chiffre impair pour arrter ...\n"); while ((nbre < 0) || (nbre > 10) || (nbre%2==0)) { scanf ("%d", &nbre); } return (0); }

50

Exercice 4 programme30.c #include <stdio.h> #include <ctype.h> #include "asciiart.h" int main () { char car = ; printf ("Tapez une voyelle pour arrter ...\n"); while ((car != A) && (car != E) && (car != I) && (car != O) && (car != U) && (car != Y)) { car = getch (); car = toupper (car); } return (0); }

Exercice 5 programme31.c #include <stdio.h> #include "asciiart.h" int main () { char car = ; int nbre = 0; printf ("Tapez 10 caractres pour arrter ..."); do { car = getch (); nbre ++; } while (nbre != 10); return (0); }

51

Exercice 6 programme32.c #include <stdio.h> int main () { int nbre = 0; int nb_nbre = 0; printf ("Tapez 10 nombres pour arrter ..."); do { scanf ("%d",&nbre); nb_nbre ++; } while (nb_nbre != 10); return (0); }

Exercice 7 programme33.c #include <ctype.h> #include "asciiart.h" int main () { char car; int nb_nbre = 10;

printf ("Tapez encore %d voyelles pour arrter...\n",nb_nbre); do { car=getch(); car=toupper(car); if (car==A || car==E || car==I || car==O || car==U) { nb_nbre--; printf ("Tapez encore %d voyelles pour arrter...\n",nb_nbre); } } while (nb_nbre != 0); return (0); }

52

Exercice 8 programme34.c #include <ctype.h> #include "asciiart.h" int main () { int nb_nbre = 10; int nbre; printf ("Tapez encore %d chiffres premiers...\n",nb_nbre); do { scanf("%d",&nbre); if (nbre==1 || nbre==2 || nbre==3 || nbre==5 || nbre==7) { nb_nbre--; printf ("Tapez encore %d chiffres premiers arrter...\n",nb_nbre); } } while (nb_nbre != 0); return (0); }

53

Chapitre 7

Les boucles
7.1 Et les shadoks pdalrent pendant 15 tours
Pour faire effectuer un certain nombre de fois une tche, on utilise linstruction for de la faon suivante (avec i, une variable de type entier (int par exemple)).

for (i=point de dpart; i<point darrive; i=i+pas) { instruction(s) rpte(s); } Par souci de simplicit, nous dirons simplement que la formule suivante :

for (i=0; i<15; i++) { instr; }

signie que lon va excuter instr pour i variant de 0 14 (<15) cest dire 15 fois.

54

Exemple : programme35.c #include "asciiart.h" #include <stdio.h> int main () { int i; for (i=0; i<15; i++) { printf ("Je me rpte pour i valant %d\n",i); } printf ("Je me suis rpte... 15 fois\n"); getch (); return (0); }

7.2 Syntaxe
De la mme faon que le if, le for ne ncessite pas daccolades si le nombre dinstructions rpter est de 1. Exemple : On peut utiliser cette fonctionnalit dans le programme prcdent en remplaant :

for (i=0; i<15; i++) { printf ("Je me rpte pour i valant %d\n",i); } par

for (i=0; i<15; i++) printf ("Je me rpte pour i valant %d\n",i); Exercice 1 Utilisez une boucle pour i variant de 0 7 inclus pour afcher : Ceci est la couleur i o i est remplac par sa valeur et o la phrase est crite avec la couleur i. Aide : La fonction textcolor(i) de notre bibliothque asciiart change la couleur courante :

textcolor (i); printf ("Ceci est la couleur %d",i); La fonction textreset()de la bibliothque permet de remettre les valeurs par dfaut ( employer avant de terminer un programme). 55

7.3 Notion de double boucle


Il est possible de remplacer les instructions par une boucle an de raliser une double boucle. On obtient donc :

Pour i allant de ... ... { ... Pour j allant de ... ... { ... } }

Exemple : programme36.c #include "asciiart.h" #include <stdio.h> int main () { int i; int j; for (i=0; i<5; i++) { printf ("\nJe suis dans la boucle i, i vaut %d\n",i); for (j=3; j>0; j--) { printf ("Je suis dans la boucle j, j vaut %d\n",j); } } getch (); return (0); }

Exercice 2 En utilisant la double boucle, crire un programme qui crit une toile, passe la ligne, crit deux toiles, passe la ligne, crit trois toiles... jusqu cinq toiles an dobtenir ceci : * ** *** **** *****

56

7.4 Exercice 3 : Et les Shadoks ftrent Nol...


7.4.1 Cne du sapin
laide dune double boucle, ralisez un cne pour dessiner le haut du sapin en vert sur 10 lignes. Vous devriez obtenir ceci : * *** ***** ******* ********* *********** ************* *************** ***************** ******************* Aide : Sur la ligne no 1, on afche 9 espaces puis 1 toile ; Sur la ligne no 2, on afche 8 espaces puis 3 toiles ; Sur la ligne no 3, on afche 7 espaces puis 5 toiles ; Sur la ligne no i, on afche 10-i espaces puis 2*i-1 toiles. On obtient donc par exemple pour lafchage des toiles sur la ligne i :

for (j=0; j<((2*i)-1); j++) { printf ("*"); }

7.4.2 Afchage du tronc


Pour poursuivre le sapin, il nous faut maintenant dessiner le tronc. Ecrire la suite du programme en dessinant le tronc laide du caractre @. Vous devriez obtenir ceci (en brun) : @@@ @@@ @@@

7.4.3 Afchage des boules de Nol


On peut rajouter des boules des Nol dans le sapin en modiant le dessin du feuillage et en remplaant alatoirement certains caractres @ verts par un O de couleur diffrente.

57

Aide :

On peut tirer un nombre alatoire entre 0 et 9 ainsi (voir chapitre 5) :

int i; srand (time (NULL)); i=rand()%10;

On pourra donc remplacer la ligne qui trace un lment de feuillage :

printf("@");

par :

if (rand()%10==0) { textcolor(rand()%8); printf("O"); } else { textcolor(2); printf("@"); }

7.5 Exercice 4 : Table Ascii


Les codes Ascii (i.e. les nombres qui reprsentent les caractres en informatique) vont de 0 255. Ecrire un programme qui fait afcher sur des lignes successives puis de faon propre, par exemple un tableau sur 8 colonnes, les codes Ascii avec les caractres qui leur correspondent (On pourra commencer lafcher partir du code 32). Aide : Pour faire afcher le caractre associ un code Ascii, on crit : printf ("%03d : %c", code_ascii, code_ascii) ;

Exemple :

int i = 65; printf ("%03d : %c", i, i); // affichera 065 : A

58

Corrigs des exercices du chapitre 7


Exercice 1 programme37.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" int main () { int i; for (i=0; i<=7; i++) { textcolor (i); printf ("Ceci est la couleur %d\n", i); } getch (); return(0); }

Exercice 2 programme38.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" int main () { int i; int j; for (i=1; i<=5; i++) { for (j=1; j<=i; j++) { printf ("*"); } printf ("\n"); } getch (); return(0); }

59

Exercice 3 programme39.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" int main () { int i; int j; /* Initialisation des nombres alatoires */ srand (time (NULL)); textcolor(2); for (i=1; i<=10; i++) { for (j=0;j<10-i;j++) { printf(" "); } for (j=1; j<= (i*2-1); j++) { if (rand()%10==0) { textcolor(rand()%8); printf("O"); } else { textcolor(2); printf("*"); } } printf ("\n"); } textcolor (3); for (i=1; i<=3; i++) { printf (" @@@\n"); } textreset(); getch (); return (0); }

60

Exercice 4 programme40.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" int main () { int i; int j; for (i=4; i<32; i++) { for(j=0; j<8; j++) { printf ("%03d %c } printf("\n"); } getch (); return (0); }

",i*8+j,i*8+j);

programme41.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" int main (void) { int i; int j; int car = 32; printf (" 0 1 2 3 4 5 6 for (i=3; i<=16; i++) { for (j=1; j<=16; j++) { printf (" %c",car); car ++; } printf ("\n"); } getch (); return (0); } 7 8 9 10 11 12 13 14 15\n");

61

Chapitre 8

Pointeurs et Fonctions
Peu dexercices dans ce cours dans lequel limportant est de comprendre les nombreux exemples cits.

8.1 Variables : pointeurs et valeurs


8.1.1 Les variables et la mmoire.
Une variable (par exemple char car) est en fait une petite zone mmoire ici de 1 octet que lon salloue et o lon va ranger les informations. Chaque type de variable utilise au moins 1 octet. Le type int varie selon les compilateurs, pour nous il utilise 4 octets cest dire 4 cases mmoire. Nous avons vu prcdemment quil tait possible de voir le contenu dune variable avec la fonction printf et quil tait possible de mettre une valeur dans une variable avec loprateur = ou la fonction scanf. Exemple :

char car = C; printf ("%c",car);

Reprsentons-nous la mmoire comme une rue remplie de maisons. Chaque case mmoire est reprsente par une maison. Chaque maison porte un numro, son adresse postale, pour une case mmoire, on parlera dadresse mmoire. Ladresse est unique pour chaque maison. Cependant, rien ne vous empche de vous tromper intentionnellement ou non de maison. De la mme faon, une adresse mmoire dune case mmoire est unique mais rien ne vous empche de vous tromper intentionnellement ou non de case mmoire. Exemple de la vie courante :

Mr Leneuf adresse : 99, grand rue

Exemple en C :

62

char car adresse : 0x001F (soit 31 en dcimal)

0x signie adresse hexadcimale (en base 16). En langage C, ladresse mmoire est accessible en faisant prcder la variable de loprateur &. Exemple :

char car = C; int nbre = 12; printf ("Adresse de car : %lu [%lx]",&car, &car); printf ("Adresse de nbre : %lu [%lx]",&nbre, &nbre);

On ajoute "l" devant le u (%lu) et devant le x (%lx) an de faire afcher un entier long (> 65536). u signie un nombre non sign. Les crochets ne sont l que pour des raisons desthtique.

8.1.2 Pointeurs
Pour utiliser les adresses mmoire des variables la place des variables elles-mmes, on utilise les pointeurs. Les pointeurs sont dnis par un type et se dclarent de la faon suivante :

type* variable; ou type *variable; Le signe * indique lutilisation dun pointeur i.e. lutilisation dune adresse mmoire. Le type permet simplement de savoir comment le compilateur C doit interprter ladresse mmoire lors de sa lecture. Nous en verrons des exemples lors de lutilisation des chanes de caractres. Pour enregistrer une valeur dans une adresse mmoire on crit :

*variable = <valeur>

*variable signie contenu de ladresse mmoire.

63

Exemple : programme42.c #include <stdio.h> int main () { char car=C; char* ptr_car = NULL; printf ("Avant, le caractre est : %c\n",car); ptr_car = &car; /* ptr_car = adresse de car */ *ptr_car = E; /* on modifie le contenu de ladresse mmoire */ printf ("\nAprs le caractre est : %c\n",car); /* i.e. on a modifi car */ return (0); }

NULL signie ladresse 0. Il indique que ladresse mmoire est invalide. Explicitons cet exemple laide de notre rue borde de maison. ptr_car = &car ; *ptr_car = E ; printf ("%c",car) ; Signie que lon ma donn ladresse postale de M. car. Signie que je rentre chez M. car et que jy dpose le caractre E. Signie que lon va lire le contenu de car pour lafcher.

8.1.3 Exercices dapplication


Exercice 1 Exercice 2 Raliser un programme quivalent qui change la valeur en K. Raliser un programme quivalent qui change une valeur numrique (int) de 10 35.

8.2 Les fonctions


8.2.1 Dnition gnrale
Une fonction est un petit bloc de programme qui limage dune industrie va crer, faire ou modier quelque chose. Un bloc de programme est mis sous la forme dune fonction si celui-ci est utilis plusieurs fois dans un code (un programme) ou simplement pour une question de clart (Imaginez un livre sans paragraphe !). A lidentique de notre fonction principale main (), une fonction scrit de la faon suivante :

64

<type de sortie> <nom de la fonction> (<paramtres dappels>) { Dclaration des variables internes la fonction Corps de la fonction Retour }

8.2.2 Void
Le type void signie indni, il est utilis : comme type de sortie pour les fonctions qui ne retournent aucun rsultat. dans la dclaration de pointeurs sur des zones mmoires dont on ne connat pas le type. Exemples :

/* Pointeur sur une zone mmoire indfinie */ void* m_ptr; /* Fonction bte affichant un caractre */ void Affiche_car (char car) { printf ("%c",car); }

8.2.3 Variables globales et locales


Les variables dclares dans les fonctions sont dites locales. Il existe aussi les variables dites globales qui sont dclares en dehors de toute fonction y compris le main (). Les variables globales sont modiables et accessibles par toutes les fonctions sans avoir besoin de les passer en paramtre. Il est de ce fait extrmement dangereux dutiliser des variables globales. Les variables locales ne sont modiables et accessibles que dans la fonction o elles sont dclares. Pour les modier ou les utiliser par une autre fonction, il est ncessaire de les passer en paramtres.

65

Exemple de variable locale : programme43.c #include <stdio.h> int carre (int val) { int val_retour = 0; /* Dclaration variable locale */ val_retour = val * val; return (val_retour); } int main () { int val_retour = 0; /* Dclaration variable locale */ val_retour = carre (2); printf ("Le carr de 2 est : %d\n", val_retour); return (0); } val_retour est dans les deux cas une variable locale. Bien quelles aient le mme nom dans les fonctions main et carre, les deux variables nont rien voir entre elles. Exemple de variable globale : programme44.c #include <stdio.h> int val = 0; int val_retour = 0; void carre () { val_retour = val * val; } int main () { val = 2; carre (); printf ("Le carr de 2 est %d\n", val_retour); return (0); }

val est une variable globale. 66

On constate que le programme devient rapidement illisible...

8.2.4 Utilisation et modication de donnes dans les fonctions


Lappel dune fonction peut seffectuer laide de paramtres. Ces paramtres peuvent tre utiliss en les dclarant dans les parenthses. Exemple : programme45.c #include <stdio.h> void Affiche_Nombre (int no) { printf (Le nombre est : %d\n,no); } int main () { Affiche_Nombre (12); return (0); }

Ces paramtres peuvent tre modier condition quils soient passs par adresse cest dire que la fonction reoive un pointeur.

67

Exemple : programme46.c #include <stdio.h> void Avance_Position (int* x) { *x = *x + 2; } int main () { int i=0; int x=0; printf ("Position de dpart : %d\n",x); for (i = 0; i<5; i++) { Avance_Position (&x); printf ("Nouvelle position : %d\n",x); } return (0); }

8.2.5 Pige !
Attention, les oprateurs unaires (avec une seule oprande) sur les pointeurs sont dangereux.

int* x; *x++; augmentera ladresse de x (on va chez le voisin) et non la valeur, pour cela il faut crire :

(*x)++; Ceci est une faute courante, prenez garde ...

8.2.6 Exercice 3 :
Reprendre le programme du sapin de Nol du chapitre prcdent et raliser 2 fonctions : Cone (int n) & Tronc (int n) qui dessinne respectivement le cne du sapin sur n lignes et le tronc en position n (n blancs avant le tronc). Ecrire un programme qui, utilisant ces deux fonctions, dessinne un sapin sur n lignes. 68

Corrigs des exercices du chapitre 8


Exercice 1 programme47.c #include <stdio.h> int main () { char car = C; char* ptr_car = NULL; printf ("Avant le caractre est : %c\n",car); ptr_car = &car; *ptr_car = K; printf ("Aprs le caractre est : %c\n",car); return (0); }

Exercice 2 programme48.c #include <stdio.h> int main () { int val = 10; int* ptr_val = NULL; printf ("Avant le nombre est : %d\n",val); ptr_val = &val; *ptr_val = 35; printf ("Aprs le nombre est : %d\n",val); return (0); }

69

Exercice 3 programme49.c #include #include #include #include <stdio.h> <stdlib.h> <time.h> "asciiart.h"

// Dessin du cne du sapin void cone (int n) { int i=0, j=0; textcolor(2); /* Initialisation des nombres alatoires */ srand (time (NULL)); for (i=1; i<=n; i++) { for (j=0;j<n-i;j++) { printf(" "); } for (j=1; j<= (i*2-1); j++) { if (rand()%10==0) { textcolor(rand()%8); printf("O"); } else { textcolor(2); printf("*"); } } printf ("\n"); } } } void tronc (int n) { int i=0, j=0; textcolor (3); for (j=1; j<=3; j++) { for (i=1; i<=n; i++) { printf (" "); } printf ("@@@\n"); } } int main () { int nb_lig = 15; cone (nb_lig); tronc (nb_lig - 2); textreset (); getch (); return (0);

70

Chapitre 9

Tableaux & Chanes de caractres


9.1 Tableaux
9.1.1 Dnition
Un tableau est un ensemble dlments conscutifs. Celui-ci peut tre constitu de plusieurs lignes et colonnes. Nous nutiliserons dans un premier temps que les tableaux une seule ligne. Exemple de tableau de caractres : Case Contenu 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H

Les cases dun tableau sont numrotes partir de 0.

9.1.2 Dclaration
Un tableau se dclare de la manire suivante : <type> <nom du tableau> [<taille du tableau>] ; Exemples :

char tab_char [10]; /* Dclaration dun tableau de 10 caractres */ int tab_int [10]; /* Dclaration dun tableau de 10 nombres. */ Un tableau plusieurs lignes se dclare de la faon suivante : <type> <nom du tableau> [<taille 1re dimension 1>][<taille 2nde dimension>] ; 71

Exemple :

int table [5] [5]; /* reprsente un tableau dentiers de 5 lignes * 5 colonnes.*/

9.1.3 Utilisation
On accde un tableau en lappelant par son nom et son numro de case. Exemple :

int tab_int[10]; int tab_char[10]; tab_char [3] = C; tab_int [6] = 10;

/* /* /* /*

tableau tableau Accs Accs

de de la la

10 cases (0 9) dentiers */ 10 cases (0 9) de caractres */ case 3 (la quatrime) de tab_char */ case 6 (la septime) de tab_int */

Attention : Le compilateur ne vrie pas que vous utilisez le tableau dans ses limites. Il vous est donc possible dcrire lextrieur de votre tableau donc chez le voisin. Cest lun des bugs le plus courant de linformatique.

9.2 Chanes de caractres


Les chanes de caractres sont des tableaux de caractres suivis dun 0 binaire (ne pas confondre avec le caractre O, nous parlons ici du code A SCII) qui est considr lui aussi comme un caractre. Une chane scrit donc : chane + 0. Exemple : Caractre Code A SCII Case Eric scrit dans un tableau de 5 caractres de la faon suivante : E 69 0 r 114 1 i 105 2 c 99 3

0 4

9.2.1 Dclaration dune chane de caractres


Une chane de caractres se dclare sous la forme dun tableau de caractres de longueur xe. Attention, comme signal auparavant, si vous dpassez la longueur de tableau, vous crivez chez le copain. Exemple : char m_chaine [20] ; permettra denregistrer des chanes de 19 caractres maximum (20-1 pour le 0 de n de chane).

72

Dautre part, il est possible de dclarer une chane de caractres sans en spcier la longueur de dpart de la faon suivante : char chaine [] = "Eric" ; Cest pratique condition de ne pas la rutiliser (on ne connat sa taille que par son contenu).

9.2.2 criture dans une chane de caractres


La premire mthode de dclaration ne permettant pas dinitialiser la chane, on pourra lui affecter une valeur de la faon suivante : sprintf (<variable de type chane de caractres>, "%s","<valeur dinit.>") ; Exemple : sprintf (m_chaine, "%s","Eric") ; remplira m_chaine par Eric0 (le 0 nest l que pour vous rappeler que lon a besoin du 0 pour terminer la chane).

9.2.3 Afchage dune chane de caractres


Une chane de caractres safche grce la commande printf et le format %s. Exemple : printf ("%s",chaine) ;

9.2.4 Longueur dun chane


La longueur dune chane de caractres sobtient par la fonction strlen. Le 0 de n de chane nest pas compt dans cette longueur. Exemple :

char ch [] = "toto" ; printf ("La longueur de %s est : %d", ch, strlen (ch)) ;

Afchera : La longueur de toto est 4 lcran.

9.2.5 Exercices
En utilisant une boucle (for) : remplissez un tableau de 10 caractres avec les lettres de lalphabet en commenant par A (code A SCII 65) ; fates afcher la chane de caractres ainsi obtenue (noubliez pas de rajouter le 0) ; fates afcher chaque caractre du tableau sous la forme Caractre n o 0 : A .

73

Rappel : Je peux crire Tab_car [i] = code_ascii ; o code_ascii est un entier reprsentant le code A SCII du caractre dsign. Aide : Pour faire afcher un seul caractre, on utilisera la syntaxe suivante :

int pos /* Position dans le tableau */ printf ("Caractre n %d : %c",pos, Tab_car [pos]); La valeur 0 peut tre assigne un lment de tableau de la faon suivante : Tab_car [la bonne position] = 0 ;

9.2.6 gets : saisie dune chane de caractres


Description La fonction gets permet de saisir une chane de caractre valide par un retour chariot. Attention, bien que cette chane ncessite dtre valide par un retour chariot, celui-ci nest pas enregistr dans le tableau de caractres. Exemple dutilisation programme50.c #include <stdio.h> int main(void) { char line[81]; /* 81 : taille arbitraire suppose suffisante */ /* Une ligne cran = 80 caractres + 1 case pour le 0 de fin de chane */ printf( "Saisissez une chane de caractre :\n" ); gets( line ); /* La frappe de lutilisateur sera enregistre dans line, on suppose quil ne frappera pas plus de 80 caractres, sinon ae ae ae */ printf( "\nLa chane de caractres saisie est : \n%s\n", line ); printf ("Notons quil ny a quun retour chariot.\n") ; return (0); }

Exemple dexcution :

Saisissez une chane de caractre : Bonjour ! La chane de caractre saisie tait : Bonjour !

Notons quil ny a quun retour chariot (celui afch par la fonction printf).

74

9.2.7 Passage dune chane de caractres en paramtres


Il est bien agrable de pouvoir utiliser cette fonction mais son efcacit est trs limite. Nous allons donc crer notre propre fonction de saisie. Pour cela, il est ncessaire de passer en paramtre une chane de caractres. Ceci seffectue de la faon suivante :

int ma_saisie (char* chaine) { ...Faire ce quil faut... return (0); } void main () { char ma_chaine [30]; ma_saisie (ma_chaine); return (); }

On nutilise pas ici le passage par adresse (&) car un tableau est en fait une adresse mmoire sur une suite doctets. Par contre, on pourrait crire : ma_saisie (&chaine [0]) &chaine[0] reprsentant ladresse mmoire de la premire case mmoire du tableau. Cest un peu compliqu mais il suft de se dire : je passe un tableau donc un ensemble de cases mmoire, donc une adresse, donc je ne mets pas de & ou bien je transmets une case donc un lment dun type comme un autre donc je mets le & pour obtenir son adresse .

9.2.8 Bugs en chanes


Reprenez lexercice 9.2.5 et mettez 12 caractres dans votre tableau de 10 cases... Essayez avec 80 caractres. On peut sans se tromper dire que le cas de dpassement de la taille dun tableau est le bug le plus frquent rencontr en programmation C alors prenez garde... Note : Ce problme nexiste pas sous Turbo Pascal, mais on ne peut pas concilier scurit et rapidit, ce qui fait que le C est de loin plus rapide que Turbo Pascal. Il suft de simaginer quil est ncessaire deffectuer un test chaque assignation dun lment du tableau ! ! !.

9.2.9 Exercices
Raliser votre propre fonction de saisie de chane de caractres. Paramtres dentre : chane de caractres, nombre de caractres maximum saisir

75

Algorithme : Initialiser car une valeur diffrente de 10 (valeur du retour-chariot) tant que ((car est diffrent dun retour chariot (10) ) et (nombre de caractres saisis maximum)) faire car = saisie_car afcher car lcran ajouter car dans le tableau mettre jour la positions dans le tableau n tant que ajouter le 0 binaire de n de chane.

nombre de caractres

Aide : Pour afcher un caractre lcran instantanment, sans envoyer de retour chariot, il faut utiliser fflush(stdout), qui vide le buffer de la sortie standard : printf("a\n") ; afche un a puis un retour chariot ; printf("a") ; afchera un a plus tard, lors de la rception dun retour chariot ; printf("a") ;fflush(stdout) afche un a instantanment, sans retour chariot. Ajouter votre fonction de saisie de caractres la gestion de la touches backspace permettant de corriger la saisie, ainsi que la gestion du retour chariot nal (qui doit tre supprim). Aide : Lors de lappui sur la touche backspace, cest le le caractre 127 est renvoy. Pour afcher un caractre backspace, on pourra faire :

printf("\b");/* Retour du curseur vers la gauche */ fflush(stdout); /* force lexcution de laffichage immdiatement */

76

9.3 Correction des exercices


9.3.1 Boucle for
En utilisant une boucle (for), remplissez un tableau de 10 caractres avec les lettres de lalphabet en commenant par A (code A SCII 65). Fates afcher la chane de caractres ainsi obtenue (noubliez pas de rajouter le 0). Fates afcher chaque caractre du tableau sous la forme "Caractre n o 0 : A". programme51.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" int main () { /* 10 caractres + 0 de fin de chane */ char tableau [11]; int i=0; /* compteur */ /* Remplissage du tableau avec les caractres */ for (i=0; i<10; i++) tableau [i] = 65 + i; /* Ajout du 0 de fin de chaine */ tableau [10] = 0; /* Affichage de la chane */ printf ("Tableau : %s\n",tableau); /* Saut dune autre ligne */ printf ("\n"); /* Affichage de chacun des caractres */ for (i=0; i<10; i++) { printf ("Caractre n %d : %c\n",i,tableau [i]); } /* Attente de la saisie dune touche */ getch (); return (0); }

77

9.3.2 Fonction de saisie (1re partie)


Raliser votre propre fonction de saisie de chane de caractre. programme52.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" void saisie (char *chaine, int max_car) { char car = ; int nb_car = 0; while ((car != 10) && (nb_car < max_car)) { /* Saisie dun nouveau caractre */ car = getch(); /* Ajout du caractre dans le tableau */ chaine [nb_car] = car; printf("%c",car); fflush(stdout); /* Mise jour de la position dans le tableau */ nb_car ++; } chaine [nb_car] = 0; } int main () { char chaine [11]; char message [] = "Votre saisie : "; printf ("%s\n", message); /* 10 : Laisser de la place pour le 0 binaire de fin de chane */ saisie (chaine,10); /* Affichage du rsultat */ printf ("Votre saisie : %s\n",chaine); /* Attente pour visualisation */ getch (); return(0); }

78

9.3.3 Fonction de saisie (2re partie)


Raliser votre propre fonction de saisie de chane de caractre, en grant les pressions sur la touche backspace et le retour chariot nal. programme53.c #include <stdio.h> #include <stdlib.h> #include "asciiart.h" void saisie (char *chaine, int max_car) { char car = ; int nb_car = 0; while ((car != 10) && (nb_car < max_car)) { car = getch();/* Saisie dun caractre */ /* Si la touche backspace a t prsse ... */ if (car==127) { printf("\b"); /* Mise jour de la position dans le tableau */ nb_car--; } else { /* Ajout du caractre dans le tableau */ chaine [nb_car] = car; printf("%c",car); /* Mise jour de la position dans le tableau */ nb_car ++; } fflush(stdout); } if (chaine[nb_car-1]==10) nb_car--; else printf("\n"); chaine [nb_car] = 0; } int main () { char chaine [11]; char message [] = "Votre saisie : "; printf ("%s\n", message); /* 10 : Laisser de la place pour le 0 binaire de fin de chane */ saisie (chaine,10); printf ("Votre saisie : %s\n",chaine); /* Affichage du rsultat */ getch (); /* Attente pour visualisation */ return(0); }

79

Chapitre 10

Fichiers et Structures
Dans ce chapitre qui ne comporte pour ainsi dire pas dexercices, nous allons survoler des notions difciles. Prenez le temps de bien comprendre les exemples et nhsitez pas poser des questions ;-). Pour une tude plus prononce des chiers, il est ncessaire davoir une connaissance minimale du systme Linux ou dUnix. Pour lassimilation de la notion de structure, lexprience sera le matre mot.

10.1 Bases sur les chiers


Un chier reprsente tout ce qui est enregistr sur votre disque dur ou presque, on va dire tout ce qui porte un nom. Il est possible de crer, de lire ou dcrire dans des chiers. A noter, que certains chiers par contre peuvent tre protgs en lecture, en criture ou les deux. An de ne rien endommager, crez laide de votre diteur de texte favori un chier nomm test.txt dans lequel vous taperez un texte de louanges pour ce superbe cours ( votre libre inspiration).

Voici un petit exemple de la lecture du chier test.txt. A noter que lutilisation des chiers ncessite la bibliothque unistd.h

80

Exemple : programme54.c #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main () { int fd = 0; char ligne [81]; int nb_car_lus = 0; /* Ouverture du fichier */ fd = open ("test.txt", O_RDONLY); /* Test si fichier ouvert */ if (fd < 0) { printf ("Impossible douvrir le fichier\n"); getchar (); return (-fd); } do { /* Lecture de 80 octets maximum */ nb_car_lus = read (fd, ligne, 80); if (nb_car_lus > 0) { /* Fin de chane de caractre */ ligne [nb_car_lus] = 0; /* Ecriture de ce qui a t lu */ printf ("%s",ligne); } } while (nb_car_lus > 0); /* Fermeture du fichier */ close (fd); /* Ecrire que cest termin */ printf ("\n --- Fin ---\n"); getchar (); return (0); } Analysons lensemble

81

/* Ouverture du fichier */ fd = open ("test.txt", O_RDONLY);

La fonction open permet douvrir un chier, le second paramtre est son mode douverture. O_RDONLY signie ouverture en lecture seule. La fonction open renvoie un nombre ngatif si louverture du chier est un chec et un handle (poigne) sur le chier dans le cas contraire (positif). What is an handle ? Un lien sur quelque chose. On appelle ceci une poigne car comme avec un sac, vous le prenez par la poigne pour le porter.

/* Test si fichier ouvert */ if (fd < 0) { printf ("Impossible douvrir le fichier\n"); getchar (); return (-fd); } La fonction read permet de lire des octets (ici transforms en caractres (char)). Elle prend pour paramtre le handle de chier, la zone de mmoire dans laquelle on va recevoir les donnes et la taille maximale que lon veut lire (attention au dpassement (cf. chapitres prcdents)). Elle renvoie un nombre ngatif lorsquelle ne peut plus lire doctets dans le chier, dans le cas contraire, elle retourne le nombre de caractres lus.

/* Lecture de 80 octets maximum */ nb_car_lus = read (fd, ligne, 80); if (nb_car_lus > 0) ...

On afche alors les donnes saisies en ajoutant un 0 de n de chane de caractresce qui explique char chaine [81]. A ne pas oublier, il faut fermer le chier aprs lavoir ouvert !

/* Fermeture du fichier */ close (fd); /* Ecrire que cest termin */ printf ("\n --- Fin ---\n"); getchar (); return (0); Trs simple non !

82

10.2 Cration dun autre chier


Reprenez lexemple prcdent et modier le avec les lments qui suivent : programme55.c int fd2;

/* Cration dune copie */ fd2 = open ("copie.txt", O_CREAT | O_RDWR, 0777); /* Test si fichier bien crer */ if (fd2 < 0) { printf ("Impossible de crer le nouveau fichier"); getchar (); return (-fd2); } do { ... / ... /* Ecriture dans notre copie de fichier */ write (fd2, ligne, nb_car_lus); } /* Fermeture de ma copie de fichier */ close (fd2); A vous de voir comment ajouter ces donnes dans le programme prcdent. Une petite modication sur la fonction open, ici nous crons un chier, lors de la cration ce chier possde des droits qui sont donns par 0777 (se rfrer un cours de Linux pour le dtail des droits). De plus, il nous faut pouvoir crire dans ce chier, nous ajoutons donc O_RDWR loption de cration (O_CREAT) an douvrir le chier en mode Lecture/Ecriture (Reading/Writing).O_CREAT signie ouverture en lecture si le chier existe ou cration dans le cas contraire (sil nexiste pas). La fonction write permet dcrire des octets sur le chier. Les paramtres sont le handle de chiers, les octets crire et la taille crire. Mettez 80 au lieu de nb_car_lus au niveau du write. Regardez, avec un peu de chance, vous allez trouver des morceaux de texte non dsirs, eh oui, personne ne vous a dit que votre chane de dpart tait vide !

10.3 Structures
Une structure peut sidentier une che de travail avec des zones remplir. Ces structures sont trs pratiques pour arranger les donnes. 83

10.3.1 Dclaration
2 choix soffrent nous.

Solution 1 :

struct { /* Dfinition de la structure */ } nom de la variable qui aura comme forme cette structure;

Solution 2 :

typedef struct { /* Dfinition de la structure */ } nom de la structure; <nom de la structure> nom de la variable qui aura comme structure cette structure.

Exemple :

typedef struct { char nom [40]; char prenom [20]; int age; } elt_fiche_nom; elt_fiche_nom une_fiche ; elt_fiche_nom une_seconde_fiche ;

La macro typedef signie dnition dun type, de ce fait l elt_fiche_nom se comporte comme un nouveau type de donnes (comme int, char, ...).

84

10.3.2 Utilisation
struct { char nom [40]; char prenom [20]; int age; } fiche_nom; fiche_nom une_fiche; fiche_nom une_seconde_fiche; une_fiche.age = 20;

10.3.3 Taille dune structure


La taille dune structure ou dun type se dtermine par la fonction sizeof. Exemple : programme56.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> int main() { typedef struct { char nom [40]; char prenom [20]; int age; } fiche; fiche ma_fiche; printf ("Taille de la structure : %d\n",sizeof (fiche)); sprintf (ma_fiche.nom, "%s","BERTHOMIER"); sprintf (ma_fiche.prenom, "%s","Eric"); ma_fiche.age = 30; printf ("%s %s est g de %d",ma_fiche.prenom, ma_fiche.nom, ma_fiche.age); getchar (); return (0) ; }

85

10.4 Fichiers et Structures


programme57.c #include #include #include #include <stdio.h> <stdlib.h> <fcntl.h> <unistd.h>

int main(int argc, char* argv[]) { typedef struct { char nom [40]; char prenom [20]; unsigned char age; } fiche; fiche ma_fiche; int h_fic ; int i; /* Cration du du fichier -> le vider sil existait */ h_fic = open ("fiche.dat", O_CREAT | O_TRUNC | O_WRONLY, 0777); /* Test si fichier ouvert */ if (h_fic < 0) { printf ("Impossible douvrir le fichier"); getchar (); return (-h_fic); } printf ("Taille de la structure : %d\n\n",sizeof (fiche)); sprintf (ma_fiche.nom, "%s","BERTHOMIER"); sprintf (ma_fiche.prenom, "%s","Eric"); ma_fiche.age = 30; printf ("Fiche 1 : %s %s est g de %d\n",ma_fiche.prenom, ma_fiche.nom, ma_fiche.age); write (h_fic, &ma_fiche, sizeof (fiche)); sprintf (ma_fiche.nom, "%s","PTIT"); sprintf (ma_fiche.prenom, "%s","Luc"); ma_fiche.age = 48; printf ("Fiche 2 : %s %s est g de %d\n",ma_fiche.prenom, ma_fiche.nom, ma_fiche.age); write (h_fic, &ma_fiche, sizeof (fiche));

86

sprintf (ma_fiche.nom, "%s","Tolkien"); sprintf (ma_fiche.prenom, "%s","JRR"); ma_fiche.age = 89; printf ("Fiche 3 : %s %s est g de %d\n",ma_fiche.prenom, ma_fiche.nom, ma_fiche.age); write (h_fic, &ma_fiche, sizeof (fiche)); /* Fermeture du fichier */ close (h_fic); /* --------------------------------- */ /* Lecture des lments du fichier */ /* --------------------------------- */ /* Ouverture du fichier */ h_fic = open ("fiche.dat", O_RDONLY); /* Test si fichier bien ouvert */ if (h_fic < 0) { printf ("Impossible douvrir le fichier"); getchar (); return (-h_fic); } for (i=0; i<3; i++) { /* Lecture de la fiche */ read (h_fic, &ma_fiche, sizeof (fiche)); /* Affichage des donnes lues */ printf ("Fiche n %d : %s %s est g de %d\n", i, ma_fiche.prenom, ma_fiche.nom, ma_fiche.age); } /* Fermeture du fichier */ close (h_fic); getchar (); return 0; }

10.5 Fin et commencement


Vous disposez maintenant d peu prs toutes les connaissances ncessaires pour llaboration de petits programmes.

87

10.6 Correction de lexercice


Lintgralit du programme de rfrence pour la Cration dun autre chier ne vous est pas donne dans le cours, la voici donc :

#include <fcntl.h> #include <stdio.h> #include <unistd.h> int main () { int fd = 0, fd2 = 0, nb_car_lus = 0; char ligne [81]; /* Ouverture du fichier */ fd = open ("test.txt", O_RDONLY); if (fd < 0) { printf ("Impossible douvrir le fichier\n"); getchar (); return (-fd); } /* Cration du fichier */ fd2 = open ("copie.txt", O_CREAT | O_RDWR, 0777); if (fd2 < 0) { printf ("Impossible douvrir le fichier\n"); getchar (); return (-fd2); }

88

do { /* Lecture de 80 octets maximum */ nb_car_lus = read (fd, ligne, 80); if (nb_car_lus > 0) { /* Fin de chane de caractre */ ligne [nb_car_lus] = 0; /* Ecriture de ce qui a t lu */ printf ("%s",ligne); /* Ecriture dans le second fichier */ write (fd2, ligne, nb_car_lus); } } while (nb_car_lus > 0); /* Fermeture du fichier */ close (fd); /* Fermeture du second fichier */ close (fd2); /* Ecrire que cest termin */ printf ("\n --- Fin ---\n"); getchar (); return (0); }

89

Chapitre 11

Curses
Ce cours est ddi un joyeux luron nomm "Bernard" et mon oeil !

Ce cours a t ralis grce au livre Programming with Curses de John Strang Editions OReilly & Associates, Inc. au cours "The Linux Programmers Guide" de Sven Godt, Sven van der Meer, Scott Burtkett, Matt Welsh.

11.1 Concepts de base


Curses est une bibliothque qui offre des fonctionnalits de manipulation de lcran. Il faut savoir que chaque console possde des caractristiques qui lui sont propres (taille dcran, vitesse dafchage ...), de ce fait il est trs difcile de raliser des applications portables (qui vont dun systme un autre). Curses nous fait le travail en nous proposant un large ventail de fonctions qui nous permettent de grer lcran. Pour plus de dtails sur ces fonctions, une documentation trs fournie et trs complte est disponible sur le Web. Le principe de fonctionnement de Curses est un tableau de nLignes et nColonnes contenant dune part tous les caractres de fentre de traitement mais aussi toutes les carcactristiques de ces caractres. Tous ses renseignements sont enregistrs dans une structure nomme WINDOW. An doptimiser au maximum les programmes tous les afchages sont bufferiss. Un changement ne sera actif que lorsque la commande refresh () est appele. En attendant que cette commande soit appele, les changements sont oprs dans limage mmoire de la fentre (WINDOW). On obtient donc le principe de fonctionnement suivant :

Initialisation de la fentre Modification de la fentre Affichage des modifications Restauration de la fentre

{\tt initscr ()}

{\tt refresh ()} {\tt endwin ()}

initscr ()

initialise Curses, il renseigne le type de terminal et les caractristiques qui lui sont associes.

90

endwin () restaure le terminal dans son tat initial. Ceci permet de mettre n toutes les modications opres par Curses lors de son fonctionnement. refresh () afche les modications opres dans lcran. Cette commande est facultative lorsquune demande de saisie est effectue (scanw par exemple). Tout ceci est bien beau mais pour linstant, nous navons rien vu et surtout rien fait. Avant de commencer pianoter sur son joli clavier, il est ncessaire de savoir comment inclure la bibliothque curses. 1. Ajoutez #include <curses.h> 2. Lors de la compilation, ajoutez -lcurses Je ne dtaille pas plus, reportez vous aux cours prcdents si vous avez un trou de mmoire &-). Bon maintenant passons en revue quelques fonctions

11.2 Quelques fonctions dafchage de Curses


11.2.1 Localisation du curseur
move (y,x) permet de positionner le curseur sur lcran. Bien entendu, ce positionnement ne sera effectif quaprs lappel de la fonction refresh. Le coin heut gauche de la fentre possde les coordonnes (0,0).

11.2.2 Afchage de caractres


addch (char ch) afche un caractre la position courante du curseur. Certains caractres spciaux donnent les rsultats suivants :

\t \r \b \n

Tabulation Retour-Chariot Backspace

8 caractres blancs Dplace le curseur sur la prochaine ligne Ecrit un blanc en arrire Efface le reste de la ligne et dplace le curseur au dbut de la prochaine ligne

Beaucoup dautres caractres permettent aussi lafchage de caractres spciaux semi-graphique, nous en verrons un peu plus tard.

11.2.3 Effacement de la fentre


clear () efface la fentre en la remplissant de blancs.

91

11.2.4 Afchage dune chane de caractres


addstr (char* ch) afche une chane de caractres. Il est important de faire attention ce que la chane ne dpasse pas la n de la ligne, enn, vous de voir et de tester ...

11.2.5 Afchage format dune chane de caractres


printw (...) est ladaptation de printf pour lafchage format de chane de caractres. Exemple :

printw ("%s",chaine);

11.2.6 Botes
Tout est plus beau dans une bote, bote de dialogue, bote de saisie ..., pour se faire Curses nous offre la fonction box (WINDOW* win, char vert, char horz). Dans le cadre de ce cours, nous nutiliserons pas les possibilits de fentres multiples, de ce fait, win sera toujours stdscr traduisez standard screen. vert dnit le caractre qui servira de bord vertical, horz dnit le caractre qui servira de bord horizontal. Exemple : !=======================! !box (stdscr, !, =);! !=======================!

11.2.7 Les anciennes fonctions dafchage


Les anciennes fonctions dafchage sont tout simplement proscrites. Cette recommendation sapplique aussi aux fonctions de saisie que nous verrons par la suite.

11.3 1reutilisation
Voici un programme exemple qui rsume ce que lon vient de voir ...

92

programme58.c #include <stdio.h> #include <curses.h> int main () { initscr (); // Initialisation de Curses box (stdscr, |, -); // Dessin dune bote move (3,2); // Positionnement en 3,2 addstr ("Quel superbe bibliothque !"); // Affichage dun message refresh (); // Application des changements getch (); // Attente, pour que lon puisse voir ! endwin (); // Fin de Curses return (0); }

Compilation : gcc -c -Wall programme58.c gcc -o programme58 programme58.o -lcurses

93

11.4 Quelques fonctions de saisie de Curses


11.4.1 Saisie dun caractre
getch permet de saisir un caractre. programme59.c #include <stdio.h> #include <curses.h> int main () { char car; initscr (); // Initialisation de Curses box (stdscr, |, -); // Dessin dune bote move (3,2); // Positionnement en 3,2 addstr ("Votre caractre : "); // Demande la saisie dun caractre car = getch (); // Saisie du caractre move (4,2); // Positionnement en 4,2 printw ("Caractre : %c", car); // Affiche le caractre saisi refresh (); // Affichage des modifications getch (); // Attente pour voir le rsultat endwin (); // Fin de Curses return (0); }

94

11.4.2 Saisie dune chane de caractre


getstr (char* str) permet de saisir une chane de caractres. Au vue que lon ne connat jamais la taille de ce qui va tre saisi par lutilisateur, cette fonction demeure dangereuse (risque de dpassement de tableau). programme60.c #include <stdio.h> #include <curses.h> int main () { char chaine [256]; initscr (); // Initialisation de Curses box (stdscr, |, -); // Dessin dune bote move (3,2); // Positionnement en 3,2 addstr ("Votre chane de caractre : "); // Demande la saisie dun caractre getstr (chaine); // Saisie de la chane move (4,2); // Positionnement en 4,2 printw ("Chaine : %s", chaine); // Affiche le caractre saisi refresh (); // Affichage des modifications getch (); // Attente pour voir le rsultat endwin (); // Fin de Curses return (0); }

95

11.4.3 Saisie formate


scanw (...) est lquivalent de scanf pour Curses. programme61.c #include <stdio.h> #include <curses.h> int main () { int nbre = 0; initscr (); // Initialisation de Curses box (stdscr, |, -); // Dessin dune bote move (3,2); // Positionnement en 3,2 addstr ("Votre nombre : "); // Demande la saisie dun caractre scanw ("%d",&nbre); // Saisie du nombre move (4,2); // Positionnement en 4,2 printw ("Nombre : %d", nbre); // Affiche le nombre saisi refresh (); // Affichage des modifications getch (); // Attente pour voir le rsultat endwin (); // Fin de Curses return (0); }

96

11.5 Afchage de caractres spciaux


Voici quelques caractres spciaux que permet dafcher curses.

tl

ts

tt

ts

tr

ls lt

rs rt

ls

rs

bl Caractre tl ts tr ls rs bl bs br rt lt tt bt

bs

bt

bs

br

Position top left top side top right left side right side bottom left bottom side bottom right right tee left tee top tee bottom tee

Valeur ACS_ULCORNER ACS_HLINE ACS_URCORNER ACS_VLINE ACS_VLINE ACS_LLCORNER ACS_HLINE ACS_LRCORNER ACS_RTEE ACS_LTEE ACS_TTEE ACS_BTEE

97

Exemple : programme62.c #include <stdio.h> #include <curses.h> int main () { initscr (); // Initialisation de Curses box (stdscr, ACS_VLINE, ACS_HLINE); // Dessin dune bote refresh (); // Affichage des modifications getch (); // Attente pour voir le rsultat endwin (); // Fin de Curses return (0); }

11.6 Les couleurs


Les couleurs se dnissent par paires, une couleur de fond et une couleur de premier plan. Le nombre de paires de couleurs maximal est COLOR_PAIRS - 1, la paire numro 0 tant rserve pour le blanc sur fond noir).

11.6.1 Dnomination des couleurs :


Couleur Noir Rouge Vert Jaune Bleu Magenta Cyan Blanc Dnition COLOR_BLACK COLOR_RED COLOR_GREEN COLOR_YELLOW COLOR_BLUE COLOR_MAGENTA COLOR_CYAN COLOR_WHITE

11.6.2 Fonctions lies au couleurs :


has_colors () renvoie TRUE si le terminal supporte les couleurs. can_change_color () renvoie TRUE si le terminal permet de rednir les couleurs. start_color () initialise les couleurs. Cette fonction doit tre appele avant lutilisation de couleurs. init_pair (pair, fg, bg) permet de dnir la paire de couleur pair sauf 0. 98

wattrset (win, COLOR_PAIR (pair)) permet dutiliser la paire de couleur pair comme couleur dcriture. win est la fentre concerne, dans notre cas, ce sera toujours la fentre standard i.e. stdscr. programme63.c #include <stdio.h> #include <ncurses.h> int main () { initscr (); // Initialisation de Curses start_color (); box (stdscr, ACS_VLINE, ACS_HLINE); // Dessin dune bote move (3,3); addstr ("Coucou cest moi"); move (4,3); printw ("Nombre de paires : %d", COLOR_PAIRS); init_pair (1, COLOR_BLUE, COLOR_WHITE); wattrset (stdscr, COLOR_PAIR(1)); move (5,3); addstr ("Coucou cest moi"); refresh (); // Affichage des modifications getch (); // Attente pour voir le rsultat endwin (); // Fin de Curses return (0); }

99

Chapitre 12

Le Jeu des Allumettes


Adapte du livre de Jacques Deconchat : "102 Programmes Pour MO6, TO8 et TO9+"

12.1 Enonc de lexercice


Un certain nombre dallumettes est dispos entre les deux partis, lordinateur et vous. Le but du jeu est de ne pas retirer la dernire allumette. Pour se faire, une prise maximale est dsigne par le joueur. En dbut de partie, on demande : 1. Le nombre dallumettes disposes entre les deux joueur (de 10 60). 2. Le nombre maximal dallumettes que lon peut retirer. 3. Qui commence (0 pour le joueur et 1 pour lordinateur). Puis, tour tour, chaque parti donne le nombre dallumettes quil prend. La partie se termine lorsquil n y a plus dallumettes sur la table. La personne ayant tire la dernire allumette est le perdant, lautre le vainqueur.

12.2 Ce quil faut faire


Lisez lintgralit de lnonc !-). Dans un premier temps, essayer de raliser lexercice sans faire dafchage graphique, i.e. sans utiliser Curses. Dans un second temps, adaptez votre programme. Pour se faire, crivez une fonction qui dessine une allumette et une qui, utilisant le dessin dune allumette, dessine le jeu dans son intgralit (toutes les allumettes).

100

12.3 Aide
Lordinateur rpond grce la fonction dcrite ci-dessous :

int jeu_ordi (int nb_allum, int prise_max) { int prise = 0; int s = 0; float t = 0; s = prise_max + 1; t = ((float) (nb_allum - s)) / (prise_max + 1); while (t != floor (t)) { s--; t = ((float) (nb_allum-s)) / (prise_max + 1); } prise = s - 1; if (prise == 0) prise = 1; return (prise); }

La fonction floor donne larrondi infrieur dun nombre. Nb_allum est le nombre dallumettes sur la table (au moment du coup jouer). Prise_max est le nombre maximum dallumettes autoris lors dune prise. La fonction retourne en sortie le nombre dallumettes prises par lordinateur. Exemple :

prise = jeu_ordi (10,3) ;

Une allumette sera dessine de la faon suivante :

0 | |

La fonction floor ncessite la bibliothque <math.h> Lutilisation de la bibliothque <math.h> oblige linker avec -lm : gcc -o monprog monprog.o -lm

101

12.4 Corrections de lexercice sans Curses


Ces programmes ne sont pas optimiss ni trs beaux. Ils se veulent simplement clairs pour les dbutants que vous tes. programme64.c #include <stdio.h> #include <stdlib.h> #include <math.h> int jeu_ordi (int nb_allum, int prise_max) { int prise = 0; int s = 0; float t = 0; s = prise_max + 1; t = ((float) (nb_allum - s)) / (prise_max + 1); while (t != floor (t)) { s--; t = ((float) (nb_allum-s)) / (prise_max + 1); } prise = s - 1; if (prise == 0) prise = 1; return (prise); } int main () { int nb_max_d=0; /*nbre dallumettes maxi au dpart*/ int nb_allu_max=0; /*nbre dallumettes maxi que lon peut tirer au maxi*/ int qui=0; /*qui joue? 0=Nous --- 1=PC*/ int prise=0; /*nbre dallumettes prises par le joueur*/ int nb_allu_rest=0; /*nbre dallumettes restantes*/ printf ("Nombre dallumettes disposes entre les deux joueurs (entre 10 et 60) : scanf ("%d",&nb_max_d);

102

do { printf ("\nNombre maximal dallumettes que lon peut retirer : "); scanf ("%d",&nb_allu_max); if (nb_allu_max >= nb_max_d) printf ("Erreur !"); } while (nb_allu_max >= nb_max_d); /* On rpte la demande de prise tant que le nombre donn nest pas correct */ do { printf ("\nQuel joueur commence? 0--> Joueur ; 1--> Ordinateur : "); scanf ("%d",&qui); if ((qui != 0) && (qui != 1)) printf ("\nErreur"); } while ((qui != 0) && (qui != 1)); nb_allu_rest = nb_max_d; do { printf ("\nNombre dallumettes restantes : %d",nb_allu_rest); if (qui==0) { do { printf ("\nCombien dallumettes souhaitez-vous piocher ? "); scanf ("%d",&prise); if ((prise > nb_allu_rest) || (prise > nb_allu_max)) { printf ("Erreur !\n"); } } while ((prise > nb_allu_rest) || (prise > nb_allu_max)); /* On rpte la demande de prise tant que le nombre donn nest pas correct */ } else { prise = jeu_ordi (nb_allu_rest , nb_allu_max); printf ("\nPrise de lordi : %d\n",prise); } qui=!qui; nb_allu_rest= nb_allu_rest - prise; } while (nb_allu_rest >0);

103

if (qui == 0) /* Cest nous de jouer */ printf ("\nVous avez gagn!\n"); else printf ("\nVous avez perdu!\n"); return (0); }

104

12.5 Corrections de lexercice avec Curses


programme65.c #include #include #include #include <stdio.h> <stdlib.h> <math.h> <curses.h>

int jeu_ordi (int nb_allum, int prise_max) { int prise = 0; int s = 0; float t = 0; s = prise_max + 1; t = ((float) (nb_allum - s)) / (prise_max + 1); while (t != floor (t)) { s--; t = ((float) (nb_allum-s)) / (prise_max + 1); } prise = s - 1; if (prise == 0) prise = 1; return (prise); } void dessine_allumette (int emplacement) { move (15, emplacement); wattrset (stdscr, COLOR_PAIR (1)); addch (*); // On repasse en couleur standard wattrset (stdscr, COLOR_PAIR (0)); move (16, emplacement); addch (ACS_VLINE); move (17, emplacement); addch (ACS_VLINE); }

105

void dessine_jeu (int nb_allumettes) { int allu = 0; for (allu = 0; allu < nb_allumettes; allu ++) { dessine_allumette (5+allu); } refresh (); } int main () { int nb_max_d=0; /*nbre dallumettes maxi au dpart*/ int nb_allu_max=0; /*nbre dallumettes maxi que lon peut tirer au maxi*/ int qui=0; /*qui joue? 0=Nous --- 1=PC*/ int prise=0; /*nbre dallumettes prises par le joueur*/ int nb_allu_rest=0; /*nbre dallumettes restantes*/ initscr (); start_color (); // Dfinition de la couleur rouge sur fond noir * de lallumette init_pair (1, COLOR_RED, COLOR_BLACK); box (stdscr, ACS_VLINE, ACS_HLINE); do {

move (1,1); addstr ("Nombre dallumettes disposes entre les deux joueurs (entre 10 et 60) scanw ("%d",&nb_max_d); if ((nb_max_d > 60) || (nb_max_d < 10)) { move (2,1); addstr ("Erreur !"); refresh (); } } while ((nb_max_d < 10) || (nb_max_d > 60)); /* On rpte la demande du nombre dallumettes */ /* tant que le nombre donn nest pas correct */

106

do { move (2,1); addstr ("Nombre maximal dallumettes que lon peut retirer : "); scanw ("%d",&nb_allu_max); if (nb_allu_max >= nb_max_d) { move (3,1); addstr ("Erreur !"); refresh (); } } while (nb_allu_max >= nb_max_d); /* On rpte la demande de prise */ /* tant que le nombre donn nest pas correct */ do { move (3,1); addstr ("Quel joueur commence? 0--> Joueur ; 1--> Ordinateur : "); scanw ("%d",&qui); if ((qui != 0) && (qui != 1)) { move (4,1); addstr ("Erreur"); refresh (); } } while ((qui != 0) && (qui != 1)); nb_allu_rest = nb_max_d; do { // Ce nest pas beau mais cest efficace clear (); box (stdscr, ACS_VLINE, ACS_HLINE); dessine_jeu (nb_allu_rest);

107

if (qui==0) { do { move (2,2); addstr ("Combien dallumettes souhaitez-vous piocher ? "); scanw ("%d",&prise); if ((prise > nb_allu_rest) || (prise > nb_allu_max)) { move (3,2); addstr ("Erreur !"); refresh (); } } while ((prise > nb_allu_rest) || (prise > nb_allu_max)); /* On rpte la demande de prise */ /* tant que le nombre donn nest pas correct */ } else prise = jeu_ordi (nb_allu_rest , nb_allu_max); qui=!qui; nb_allu_rest= nb_allu_rest - prise; } while (nb_allu_rest >0); move (5,5); if (qui == 0) addstr ("Vous avez gagn !"); else addstr ("Vous avez perdu !"); refresh (); getchar (); endwin (); return (0); }

108

Chapitre 13

Le Jeu de la Vie
Le prsent exercice consiste implmenter une version sur damier torique du jeu de la vie de John Conway, en C, et en utilisant la librairie ncurses pour lafchage.

13.1 Historique
John Conway tait un mathmaticien de lUniversit de Cambridge. Trs prolique en matire de jeux mathmatiques, il dcrivit en 1970 le jeu de la vie, visant modliser dune faon simple lvolution dorganismes vivants. Le jeu de la vie est une application particulire dautomates cellulaires.

13.2 Rgles du jeu


Le jeu de la vie volue normalement sur un damier inni. Chaque case est occupe par une cellule qui peut tre vivante ou morte. chaque gnration, chaque cellule peut natre, mourir, ou rester dans son tat. Les rgles qui permettent de passer dune gnration lautre sont prcises et ont t choisies avec soin pour que lvolution des organismes soit intressante et imprvisible. En premier lieu, notons que sur un damier inni, chaque case a exactement 8 voisins. Les rgles donnes par J. Conway sont les suivante : Une cellule ayant exactement 2 ou 3 voisins vivants survit la gnration suivante. Une cellule ayant au moins 4 cellules voisines vivantes meurt dtouffement la gnration suivante. Une cellule ayant au plus une cellule voisine vivante meurt disolement la gnration suivante. Sur une case vide ayant exactement 3 voisins vivants, une cellule natra la gnration suivante. Notons que cest lensemble de la gnration actuelle qui doit tre pris en compte pour ltablissement de ltat des cellules la gnration suivante. Voici un exemple de gure sur un petit damier. Les cellules qui devront mourir la gnration suivante sont grises :

109

Gnrations :

13.3 Damier torique


Reprsenter le damier par un tableau est la solution la plus simple. Mais on ne peut pas reprsenter un tableau inni. Plusieurs choix sont alors possibles : considrer labsence de voisin (au bord du tableau) comme une cellule morte ; considrer labscence de voisin (au bord du tableau) comme une cellule vivante ; jouer sur un damier torique. La troisime solution, respecte mieux le jeu initial. On doit considrer que les bords droit et gauche du tableau sont relis entre eux, ainsi que les bords suprieurs et infrieurs. Le voisinage des points est donc le suivant :

13.4 Implmentation du jeu


Pour raliser lafchage de notre jeu de la vie, nous utiliserons la librairie ncurses.

13.4.1 Rappels utiles sur ncurses


On initialise la libraire proprement avec la fonction initscr() ;. On la prpare lutilisation des couleurs, et on dnit les couleurs ainsi :

if (has_colors()) { start_color(); init_pair(1,COLOR_WHITE,COLOR_BLUE); init_pair(3,COLOR_RED,COLOR_BLACK); } Le bout de code prcdent vrie que le terminal supporte lutilisation de couleurs, initialise leur utilisation et dni les couleurs 1 et 3 comme tant du blanc sur bleu et rouge sur noir. 110

On utilise les couleurs et on afche un caractre un endroit donn ainsi :

/* Slection du blanc sur fond bleu */ wattrset(stdscr,COLOR_PAIR(1)); /* dplacement de la position courant ligne 10, colonne 14 */ move(10,14); /* Affichage dun espace (donc un carr bleu avec la df. prcdente) */ addch( );

Les commandes dafchages termines, un appel la fonction refresh() ; permet dobtenir lafchage effectif. Enn, on quitte proprement la librairie par un appel la fonction endwin()

13.4.2 Algorithme du jeu de la vie


On pourra reprendre lalgorithme suivant, qui dcrit le programme globalement :

// Initialise la librairie procedure init_curses() // Termine proprement la librairie procedure fin_curses() // Initialise le damier avec des cellules vivantes prises au hasard procedure damier_hasard() // Renvoie le nombre de voisins de la cellule (x,y) du damier (utilis // par la procdure prochaine_generation) fonction nombre_voisins(x,y) // met jour le damier pour la gnration suivante procedure prochaine_generation() // Affiche le damier procedure affiche(monde) procedure principale : init_curses() damier_hasard() rpter : affiche_damier() prochaine_generation() saisir un caractre au clavier jusqu ce que le caractre saisi soit q fin_curses

111

13.4.3 Structures de donnes utilises


On pourra reprsenter le damier par un tableau de char. Un damier de taille sera donc dclar ainsi : char monde[30][30] ; On pourra choisir de mettre la valeur 0 dans une case si la cellule est morte et la valeur 1 dans le cas contraire. Mme si il est gnralement conseill dviter de dclarer des variables globales, on pourra dans cet exemple simple dclarer un tableau monde global.

13.4.4 Difcults
Si vous vous sentez sufsament en forme pour crire le programme, ne vous en privez pas. Vous pourrez regarder cette section uniquement en cas de problme. Les principales difcults sont : le comptage du nombre de voisins sur damier torique ; le calcul de la gnration suivante ; La premire difculte peut tre traite ainsi :

// Renvoie le nombre de voisins vivants de la cellule (x,y) // monde est le damier // TAILLEX et TAILLEY les dimensions du damier int nombre_voisins(int x,int y) { int ofx,ofy; int x0,y0; int n=0; for (ofx=-1;ofx<=1;ofx++) { for (ofy=-1;ofy<=1;ofy++) { x0=x+ofx%TAILLEX; y0=y+ofy%TAILLEY; while (x0<0) x0+=TAILLEX; while (y0<0) y0+=TAILLEY; n+=monde[x0][y0]; } } n-=monde[x][y]; return n; }

Remarque : En C loprateur % correspond lopration modulo. Ainsi, a%b est le reste de la division entire de a par b. Pour calculer la gnration suivante, on doit utiliser un tableau auxiliaire :

112

// Met jour le damier avec la gnration suivante // monde est le damier // TAILLEX et TAILLEY les dimensions du damier void generation_suivante(void) { int x,y; char monde_aux[TAILLEX][TAILLEY]; // Calcul de la nouvelle gnration dans le tableau auxiliaire for(x=0;x<TAILLEX;x++) { for(y=0;y<TAILLEY;y++) { switch(nombre_voisins(x,y)) { case 2: // la cellule reste dans le mme tat monde_aux[x][y]=monde[x][y]; break; case 3: // la cellule nat monde_aux[x][y]=(char)1; break; default: // la cellule meurt dans les autres cas monde_aux[x][y]=(char)0; break; } } } // Recopie du tableau auxiliaire dans le tableau courant for(x=0;x<TAILLEX;x++) { for(y=0;y<TAILLEY;y++) { monde[x][y]=monde_aux[x][y]; } } }

13.5 Possibilits damlioration


Si vous nissez rapidement, vous pouvez amliorer le programme.

13.5.1 Contrle interactif


Lappel la fonction nodelay(stdscr,TRUE) de ncurses permet dutiliser la fonction getch() de faon non-bloquante. Un appel la fonction renverra ERR si aucune touche na t tape et le caractre entr dans le cas contraire. En combinant ces deux fonctions, vous pouvez permettre lutilisateur de voir voluer le jeu de la vie, sans quil ait frapper une touche, tout en lui laissant les possibilits suivantes (par exemple) : 113

taper q pour sortir ; taper r pour rinitialiser le jeu ; taper w ou x pour acclrer ou ralentir son droulement.

13.5.2 Afchage des coordonnes


Vous pouvez afcher les coordonnes des cases sur les bords du damier.

13.5.3 Chargement de formes prdnies


Malgr son apparente simplicit, le jeu de la vie recle de nombreuses surprises. En partant dun tableau alatoire, on peut difcilement les observer mme si lapparition dun planeur (voir lexemple du dbut) ou de formes priodiques ( la n) ne sont pas rares. Certaines personnes ont rpertories des centaines des formes aux proprits particulires : gnrateurs de planeurs (les lanceurs), portes logiques, formes priodiques de grande priode, formes stables... La possibilit dinitialiser le damier avec une forme particulire est donc intressante pour pouvoir observer ces phnomnes. On pourra donc permettre lutilisateur de lire ltat des cases dans un chier, an quil choisisse ltat initial du damier.

13.6 Exemples obtenus


On peut voir sur les gures suivantes des congurations obtenues :

Conguration alatoire de dpart...

114

Formations damalgames de cellules...

Conguration nale de motifs de priode 1 ou 2...

Apparition dun planeur...

...qui se balade.

115

13.7 Exemple de corrig


Le programmme suivant afche le damier, les coordonnes des cases, et permet lutilisateur dutiliser les touches r, q, w et x pour rinitialiser le damier, quitter, acclrer ou ralentir le jeu. programme66.c

#include <stdio.h> #include <stdlib.h> #include <ncurses.h> #define TAILLEX 75 #define TAILLEY 50 char monde[TAILLEX][TAILLEY]; int usecolors=0; /* Procdure de temporisation... */ void temporise (int t) { int j,i; for (j=0;j<t;j++) for(i=0;i<32000;i++) { } } /* procdure vidant le buffer clavier */ void vide_buffer(void) { while (getch()!=ERR); } /* Initialisation de ncurses et dfinition des couleurs */ void init_curses(void) { initscr(); if (has_colors()) { start_color(); init_pair(1,COLOR_WHITE,COLOR_BLUE); init_pair(2,COLOR_WHITE,COLOR_GREEN); init_pair(3,COLOR_RED,COLOR_BLACK); usecolors=1; } } /* Terminaison propre de ncurses */ void fin_curses(void) { endwin(); }

/* Affichage du damier */ void affiche(void) { int i,j,k; char str[5]; for (j=0;j<TAILLEY;j++) { for (i=0;i<TAILLEX;i++) { move(j,i); if (monde[i][j]) { if (usecolors) { wattrset(stdscr,COLOR_PAIR(1)); addch( ); wattrset(stdscr,COLOR_PAIR(0)); } else { addch(@); } } else { addch( ); } } } /* Affichage des coordonnes sur le bord droit */ if (usecolors) wattrset(stdscr,COLOR_PAIR(3)); for (j=0;j<TAILLEY;j++) { move(j,TAILLEX+1); printw("%03d",j%100); } /* Affichage des coordonnes sur le bord infrieur */ for (i=0;i<TAILLEX;i++) { sprintf(str,"%d",i); for (k=0;k<strlen(str);k++) { move(TAILLEY+k+1,i); addch(str[strlen(str)-1-k]); } } if (usecolors) wattrset(stdscr,COLOR_PAIR(0)); refresh(); }

116

// Renvoie le nombre de voisins // vivants de la cellule (x,y) // monde est le damier // TAILLEX et TAILLEY les dimensions // du damier int nombre_voisins(int x,int y) { int ofx,ofy; int x0,y0; int n=0; for (ofx=-1;ofx<=1;ofx++) { for (ofy=-1;ofy<=1;ofy++) { x0=x+ofx%TAILLEX; y0=y+ofy%TAILLEY; while (x0<0) x0+=TAILLEX; while (y0<0) y0+=TAILLEY; n+=monde[x0][y0]; } } n-=monde[x][y]; return n; } /* Rempli au hasard le damier perc % de cellules vides */ void damier_hasard(int perc) { int i,j; perc=perc%101; for (j=0;j<TAILLEY;j++) for (i=0;i<TAILLEX;i++) { if (rand()%101 > perc) monde[i][j]=1; else monde[i][j]=0; } }

/* Calcule la gnration suivante */ void generation_suivante(void) { int x,y; char monde_aux[TAILLEX][TAILLEY]; // Calcul de la nouvelle gnration // dans le tableau auxiliaire for(x=0;x<TAILLEX;x++) { for(y=0;y<TAILLEY;y++) { switch(nombre_voisins(x,y)) { // la cellule reste // dans le mme tat case 2: monde_aux[x][y]=monde[x][y]; break; // la cellule nat case 3: monde_aux[x][y]=(char)1; break; // la cellule meurt // dans les autres cas default: monde_aux[x][y]=(char)0; break; } } } // Recopie du tableau auxiliaire // dans le tableau courant for(x=0;x<TAILLEX;x++) { for(y=0;y<TAILLEY;y++) { monde[x][y]=monde_aux[x][y]; } } }

117

int main(void) { int temp=500; char c= ; init_curses(); noecho(); nodelay(stdscr,TRUE); damier_hasard(50); move(54,0); addstr("q-Quit r-Redraw \ w-Fast x-Slow"); refresh(); while(c!=q) { affiche(); generation_suivante(); c=getch(); vide_buffer(); switch(c) { case q: break; case r: damier_hasard(50); break; case w: temp-=10; if (temp<0) temp=0; break; case x: temp+=10; if (temp>10000) temp=10000; break; } temporise(temp); } fin_curses(); return (0); }

118

Annexe A

Code Ascii

119

120

121

Annexe B

Bibliothque Asciiart
B.1 Introduction
An de pouvoir raliser des exercices plus amusants et colors, nous avons regroup un ensemble de fonctions dans une bibliothque, pompeusement appele ASCIIART. Cette bibliothque permet pour linstant de modier les couleurs du terminal et de saisir des caractres la vole, avec ou sans echo. Il ne tient qu vous de lamliorer. Sachez cependant quil existe de trs bonnes bibliothques faisant entre autres tout ceci, comme le clbre ncurses, dont lutilisation complte dpasse lobjet de ce cours.

B.2 Utilisation de la bibliothque


Les fonctions sont dclares dans le chier asciiart.h. Vous devez donc linclure dans vos sources (#include "asciiart.h"). La fonction test_asciiart() permet de tester les diffrentes fonctions de la bibliothque. Celle-ci est fournie au format objet (.o), mais vous pouvez bien sr regarder le source. Pour compiler lexemple suivant : test_bibli.c #include "asciiart.h" int main(void) { test_asciiart(); return(0); } vous devez entrer : gcc -c test_bibli.c 122

puis : gcc -o test_bibli test_bibli.o asciiart.o et enn excuter : ./test_bibli

B.3 Fichier den-tte


lheure actuelle, le chier den-tte est le suivant : asciiart.h #ifndef ASCII_ART_H #define ASCII_ART_H /* Cet ensemble de fonctions permet dutiliser la saisie de caractres la console en mode non bufferis (ici appel mode immdiat) Il permet daccder diffrents paramtres du terminal comme la couleur */

// Saisit un caractre au vol. Sans echo char getch(void); // Saisit un caractre au vol. Avec echo char getche(void); // procdure permettant de tester les diffrentes focntionnalits void test_asciiart(void); // modifie la couleur daffichage void textcolor(int i); // 0<=i<=7 // passage (1) ou sotie (0) mode clignotement (exprimental...) void textblink(int val); // rinitialisation de la console void textreset(void); // Exemple dutilisation : //# include "asciiart.h" //int main(void) //{ //test_asciiart(); //return 0; //} #endif

123