You are on page 1of 124

Cours de C

Eric Berthomier

eric.berthomier@free.fr

Laurent Signac

signac@sic.sp2mi.univ-poitiers.fr

Table des matières
1 Premiers pas

7

1.1

Prologue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7

1.2

Exemple de programme

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7

1.3

Normalisation du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8

1.4

Petit mot sur ce qu'est une bibliothèque . . . . . . . . . . . . . . . . . . . . . . . .

9

1.5

Un exemple de chier bibliothèque

1.6

Les diérentes fonctions

. . . . . . . . . . . . . . . . . . . . . . . . . . .

10

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

1.7

Squelette de programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

1.8

Les blocs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

1.9

Les commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

1.10 Exercices d'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

2 Les variables (1e partie)

15

2.1

printf : fonction indispensable pour acher le contenu d'une variable . . . . . . . .

15

2.2

Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

2.3

Déclaration d'une variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

2.4

Application : exemple

16

2.5

Utilisation multiple du %

2.6

Exercices d'applications directes

2.7

Réutilisation d'une variable

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

1

2.8

Caractères spéciaux

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

2.9

Exercices à réaliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

3 Les variables (2e partie)

24

3.1

Exercice de mise en bouche

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

3.2

Déclaration des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

3.3

Saisie des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

25

4 Les conditions

32

4.1

Exercice de mise en bouche

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.2

Les conditions : Si Alors Sinon

4.3

Opérateurs logiques

32

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

4.4

Opérateurs logiques purs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

4.5

Vrai ou faux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

4.6

Combinaison

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

4.7

Astuce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

4.8

Les accolades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

4.9

Exercices

35

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 Mise au point

39

5.1

Prologue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

5.2

Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

5.3

Retour sur getchar() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

5.4

Boucle Faire ... Tant que (vrai) . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

40

5.5

Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

5.6

Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

2

1 Préambule . . . . . . . . . . . . . . . . . . . . 57 7. . . . . . . . 57 . . . . . . 46 6. . . . . . . . . . . .2 While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Void . . . . . . . . . . . . . . . . . .4 Exercice 3 : Et les Shadoks fêtèrent Noël. . . . . . . . . . . . . .2 Variables : pointeurs et valeurs 62 . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . 45 6. . . . . . .3 Exercices d'application . .3 Achage des boules de Noël 7. . . . . . . . . . . . . . . . . . . . . 64 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . .3 Et les Shadoks apprenaient que reprendre équivaut à apprendre . . . . . . . . . . 54 7. . . . . . . . . . . . . . . . . . . .4. . . . . . . . . . . . . .7 Au clan des Shadoks. . . . . . . . . . . .1 Les variables et la mémoire. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Pointeurs . . . . . . . . . 47 6.1 8. 56 7. . . 62 8. . voyelles. . . . . . . . . . . . . . 45 6. . . . . . . . . . . . . 64 8. . . . . . . 55 7. . . . . . . . . . . . . . . . . . . . . . . . 65 8. . . . . . . . . . 46 6. . . . . .4. . . . . 62 8. . . . . . . . . . . . . . . . . . chires premiers 48 toupper () . . . . 7 Les boucles 54 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8 Pointeurs et Fonctions 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4. . . .4 Fonction . . . . . . . . . . . . . . . . . .1. . . . . . . . . 64 Les fonctions . .1 Dénition générale .. . . . . 57 7. . . . . . . . . .3 Variables globales et locales . . . . . . . . . . . . .1.2. . . . . 65 3 . . . . . 63 8. . .2 Achage du tronc .1  Cône  du sapin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Notion de double boucle . .. . . . . . . . . . . .5 O tant que en emporte le Shadok . . . . . on trie. . . .2. 47 6. . .2 Syntaxe . . . . . . . . . . 57 7. . . . . . . . . . . . .6 Et les Shadoks continuaient à pomper pour obtenir le résultat . . . . . . . . . . . .5 Exercice 4 : Table Ascii . . . . . .1 Et les shadoks pédalèrent pendant 15 tours . . . . . .6 Et les shadocks pompaient 45 6. . .

. . . . . . . . . . . . . . . . . . . . . . 83 10. . . . . . . . . . . . . . . . . . . . 75 9. .2. . . . . . . . . . . . . . . . . . . . .8. . . . 71 9. . . . . . . . . . . . 73 9. . .3. . . . 78 9. . . . . . . . . . . . . . . .3 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 9. . . .7 Passage d'une chaîne de caractères en paramètres . . . . . . . .4 Longueur d'un chaîne . . . . . . . . . . . . . 67 8. . . . . .2.1 Boucle for .2.2 9. . .2. . . . . . .2. . . . . . .2 Création d'un autre chier . . . . .3. . . . . . 68 9 Tableaux & Chaînes de caractères 9. . . . . 72 Chaînes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 9. . . . . . . . . . . . . . . . 68 8. . . . . . . . . 80 10. . . . . . . . . . .2. . . . . . . . . . . . . . .5 Exercices .3 Achage d'une chaîne de caractères . . .6 gets : saisie d'une chaîne de caractères .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Écriture dans une chaîne de caractères . . . . . . . . 73 9. . . . . . . .4 Utilisation et modication de données dans les fonctions . . . . . 71 9. .2 Fonction de saisie (1ère partie) . . . . . . . . .2. . . . . . . . .3 Utilisation . . . . . . . . . . . . . . . . . Correction des exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 9. . . . . .8 Bugs en chaînes . . . . . . 77 9. . . . . . . . .2. . 79 10 Fichiers et Structures 10. . . . . . . . . . . . . . . . . .3. .6 Exercice 3 : . . . . . . . . . . . . . . . . . . . . . . .1 9.1 Bases sur les chiers 80 . . . .2. . . . . . . . . . . . . . . . . . . 73 9. . . . . . . . . 74 9. .1. . . . . . .5 Piège ! . . . . . .2. . 83 4 . . . . . . . . . . 72 9. . . . . . . . . . . . . . . . . . . . . . . . . .9 Exercices 75 . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Déclaration d'une chaîne de caractères . . . 75 9. . . . . . .1 Dénition . . . . . . .3 Tableaux 71 . . . . . . . . .2 Déclaration . . . . . . . . . . . . . . . . . . .3 Fonction de saisie (2ère partie) . . . . . . . . . . . . 71 9. . .

. .3.1 Déclaration . .4 Fichiers et Structures . . . . . . . 91 11. . . . . .3. . . . . . . .4 Quelques fonctions de saisie de Curses 92 . . . . . . . . 91 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Fonctions liées au couleurs : . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 11. . . . . . . . . . .1 Localisation du curseur . . . . . .4. . . . . . . . . . . . . . . . . . . . . . . . 98 11. . . . . . . . . .5 Fin et commencement . . . . . . . . . . . . . . 94 11. . . . . . . . . . . . . . . . . . . . . . . . . 95 11. . . . . 87 . . .3 Saisie formatée . . . . . . . .2 Quelques fonctions d'achage de Curses . . 88 10. . . .6. . . . . . . . . . . .1 Dénomination des couleurs : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 10. . . . . . . . . . . . . . . . . 91 11. . . . . . . . . . . . . . . . . . .6 Correction de l'exercice 11 Curses 90 11. .4 Achage d'une chaîne de caractères 92 . . . . . . . 86 10. . . 90 11. . . . . . . . . . . . . . . . . .2 Saisie d'une chaîne de caractère . . . . . . . . . . . . . . .4. . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 11. . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . 96 11. . . . . .2. .3 Eacement de la fenêtre . . . . . . . . . . . 11. . . . . . . . .2. . . . . . . . . .6. . . . . . . . . .4. . . . . . . . . . . . . . . . . . .1 Saisie d'un caractère . . . . . . . . . . . . . . . . . . . . . 94 11. 85 10. . . . . . . . . . . . . .3 1 utilisation . . . . . . . . . . .6 Les couleurs . . . . 98 11. . . . . . . . .3. . . . . . . . . . . .10. . . . .2 Achage de caractères . . . . . . . . . . . . . . 91 11. . . . . . . . . . . . 98 5 . . . . . . . . .2 Utilisation . . . . .1 Concepts de base . . . . . . . . . . . . . . . . . . . 92 re 11. . . . . . . . . .5 Achage formaté d'une chaîne de caractères .7 Les anciennes fonctions d'achage . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Taille d'une structure . 84 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . 11. . . . . . . .5 Achage de caractères spéciaux . . 92 11. . . . . . . . . .6 Boîtes . . . . . . . . . . . . . . . . . .

. . . .2 Ce qu'il faut faire . . . . . . . 102 12. . . . . . . . . . . . . . . . . . . . .3 Aide . . .2 Règles du jeu 109 . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 13. . . . . . . . . . . . . . . . .5. . . . 110 13.6 Exemples obtenus . . . . . . . . . .4. . . . . .2 Achage des coordonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Corrections de l'exercice avec Curses .4 Implémentation du jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . .12 Le Jeu des Allumettes 12. . . . . . . . . . . . . . . 114 13. . . . . . . . . . . . . . . .2 Algorithme du jeu de la vie . . . . 110 13. . 113 13.5. . . . . . .7 Exemple de corrigé . . . . . . . . . . 114 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 13 Le Jeu de la Vie 109 13. . . . . . . . . . . . . . . . .1 Rappels utiles sur ncurses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Structures de données utilisées . . . . . . . . . 109 13. . . . . . . . . . . . . . . . . . . . . . .1 Contrôle interactif . . . . . 100 12. 100 12. . . . . . . . . . . . .1 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Possibilités d'amélioration . . . . . .4. . . . . . .3 Damier torique . . . . . . . . . . 116 6 . . . 113 13. . . . . . . . . . . . . . . . . 111 13. . . 101 12. . . . . . . . . . . . . . . . . . . . . . . . . . . .4. . .4. . . . . . . . .4 Corrections de l'exercice sans Curses . .4 Dicultés . . . . . . . . . . . 110 13. . . . 114 13. . . . . . . . . . . . . . . . .3 Chargement de formes prédénies . 112 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Enoncé de l'exercice 100 . . . . . . . . . . . . . .

nous allons continuer dans le sale et compiler salement : En ligne de commande. Dans un premier temps. un puriste est passé derrière votre dos. ouvrez un chier nommé programme1. À l'aide de votre éditeur de texte favori.c 7 .c main () { puts ("Bonjour"). 1. getchar ().2 Exemple de programme Voici pour exemple un premier programme qui fonctionne malgré le fait qu'il ne soit pas normalisé. c'est normal. si vous entendez hurler.c (1e programme du cours) puis tapez le texte suivant : programme1. pleurer. il faut le compiler. Une fois le texte du programme frappé. c'est à dire en analyser la syntaxe. Mais nous sommes là pour apprendre et il faut bien commencer par quelque chose. Celui-ci ache le mot Bonjour à l'écran.Chapitre 1 Premiers pas 1. Ceci se fait avec le compilateur gcc. tapez : gcc c programme1.1 Prologue Ce cours est destiné à vous faire connaître le C sous Linux. vomir ou tout autre ignominie de ce genre. } À ce moment. crier.

h. Pourquoi me direzvous ? Eh bien rendons notre compilateur bavard en lançant la commande gcc c Wall programme1.. le code source représente le programme sous sa forme textuelle (en langage C). En général 0 signie une terminaison sans erreur. La valeur de retour permet à un programme ou à l'utilisateur de savoir si le programme que l'on exécute s'est correctement terminé.c:6: warning: implicit declaration of function `puts' prog_1_1. ceci va vous donner un chier nommé programme1. Nous allons donc normaliser ce programme. Le second point à corriger est l'absence de valeur de retour. le langage C n'est qu'un ensemble de bibliothèques à partir desquelles le compilateur trouve les fonctions et les applications qui lui permettent de créer un programme exécutable. Exactement ce que vous faîtes lorsque vous recherchez dans une encyclopédie pour réaliser un exposé. exécutez la commande suivante : gcc o programme1 programme1. Normalement ajouter une bibliothèque.c:9: warning: control reaches end of non-void function Peu compréhensible et c'est normal. il nous faut transformer le chier objet en un exécutable.o Il ne reste plus qu'à exécuter le programme : Et comme par magie. Pour cela. il sut d'ajouter programme.3 Normalisation du programme Bon. À sa base. en deux mots à éviter.o. En fait. Ce chier est nommé le chier objet. s'achera alors Code source : . nous avons fait dans le sale.. je l'ai dit précédemment./programme1 Bonjour et attendra que vous appuyez sur la touche Entrée.c. Certaines bibliothèque (les plus courantes) sont incluses dans des compilateurs ce qui permet à puts a besoin de la bibliothèque stdio.Si vous n'avez pas fait d'erreur.). l'option de compilation Wall permet de  déclencher la production de messages souli- gnant toute technique autorisée mais discutable . 1. Le chier que vous avez passé en paramètre au compilateur se nomme le chier source (source de tous les bonheurs de Linux . En lui rajoutant quelques lignes on obtient donc : 8 . An de pouvoir obtenir un chier exécutable. Pour #include <nom de la bibliothèque> en début de notre programme de se compiler. prog_1_1.c:5: warning: return-type defaults to `int' prog_1_1. Observez la bornée d'insulte.c: In function `main': prog_1_1.

c #include <stdio.obj  n'étend que la forme pré compilée du  . Attention : Dans le cas de void main(). À #include puts.4 Petit mot sur ce qu'est une bibliothèque À l'instar de l'étudiant qui recherche dans des livres.h  si ce mot y est déni. getchar (). /* Permet d'attendre la frappe d'une touche */ return (0).h. cette formulation à elle seule nécessiterait tout le cours de programmation (les 15 cours .c #include <stdio. il regarde dans chacun des  .h> void main () { puts ("Bonjour"). le  . Pour ne pas utiliser de valeur de retour. getchar ().c  le contenu du chapitre concerné. Pour être au plus pur. Le mot clé void peut se traduire par  ne contenant rien .. celui-ci émettra une erreur de syntaxe. pour être expliquée. on utilise return .o  ou  . Il trouve celui-ci dans la bibliothèque l'inverse. } La valeur de retour n'est pas obligatoire mais fortement conseillée. on peut dire que le  . 9 . Donc nous en resterons là pour la normalisation. et non return(0) . Exemple : Lorsque le compilateur C rencontre le mot déclaré par l'instruction stdio. il faudrait écrire : int main (int argc. return. 1. malgré tout. on utilise void main() à la place de int main().programme2.h> int main () { puts ("Bonjour").-)). char** argv) Mais. } La normalisation n'est pas nie. Le programme devient donc : programme3. s'il ne le trouve pas.h  représente l'index du livre et le  .c .

to stdout. /* Write formatted output to S from argument list extern int vsprintf __P ((char *__restrict __s.h. */ extern int sprintf __P ((char *__restrict __s. /* Write formatted output to S from argument list extern int vfprintf __P ((FILE *__restrict __s. */ list ARG.6 Les diérentes fonctions puts : permet d'acher du texte suivi d'un retour à la ligne. __const char *__restrict __format.. . . ARG.7 Squelette de programme On peut dénir le squelette d'un programme C de la façon suivante : 10 .)).)).5 Un exemple de chier bibliothèque stdio. Vous trouverez ce chier dans le répertoire printf que /usr/include. un extrait de la bibliothèque déclaration de puts que second cours. __const char *__restrict __format.. /* Write formatted output to stdout. /* Commentaire*/ : permet de mettre un commentaire. 1. __const char *__restrict __format.. . getchar : permet d'attendre la frappe d'une touche suivie d'un retour chariot ou un retour chariot seul. Extrait du chier stdio. */ /* Write a string.. __const char *__restrict __format. */ extern int fprintf __P ((FILE *__restrict __stream. ARG. */ __format.. On y retrouve notamment la l'on voit dans ce cours et la déclaration de l'on verra dans le Vous trouverez ci-dessous..1.h : /* Write formatted output to STREAM. _G_va_list __arg)). /* Write formatted output to stdout from argument extern int vprintf __P ((__const char *__restrict _G_va_list __arg)). */ extern int printf __P ((__const char *__restrict __format. On trouvera aussi // qui permet de mettre le reste de la ligne en commentaire. _G_va_list __arg)). 1. */ extern int puts __P ((__const char *__s)). Notre programme ache bonjour et attend que l'on appuie sur une touche an que l'on puisse voir ce qu'il a écrit. followed by a newline.)). /* Write formatted output to S.

chapitre 2 } /* Corps du programme */ getchar().8 Les blocs La partie de programme située entre deux accolades est appelée un bloc. Puis retirer cette tabulation après l'accolade fermante du bloc. Les commentaires peuvent être placés à n'importe quel endroit dans le programme.9 Les commentaires Commenter signie qu'une personne ne connaissant pas le langage C doit pouvoir lire le programme et le comprendre. Ils commencent par /* et se terminent par */. /* Commentaire */ Vous trouverez aussi : // Le reste de la ligne est un commentaire 1. Les commentaires sont indispensables dans tout bon programme. Écrire un programme qui écrit au revoir./* Aucune erreur renvoyée */ 1. 2. Ainsi. Cette méthode permet de contrôler la fermeture des accolades et de leurs correspondances. Je conseille de prendre l'habitude de faire une tabulation après le retour à la ligne qui suit l'accolade.10 Exercices d'application 1./* Facultatif mais permet d'attendre l'appui d'une touche */ return (0)./* Déclaration des bibliothèques */ int main () { /* Déclaration des variables */ cf. 1. on obtient : { } Tabulation Tout le code est frappé à cette hauteur Retrait de la tabulation Tout le texte est maintenant frappé à cette hauteur. Écrire un programme qui : 11 .

 12 . Écrire un programme qui écrit : Hamlet says To be or not to be. Commentez le précédent programme. that is the question. /* Ecrit Cours de programmation à l'écran */ 4. Écrit  Salut toi. Par exemple : puts ("Cours de programmation" ) . appuie sur une touche s'il te plaît   Attend l'appui d'une touche  Écrit  Merci d'avoir appuyé sur une touche  3.

/* Affiche Au revoir */ getchar (). /* Affiche le message Salut toi.c #include <stdio. s'il te plaît */ getchar (). /* Affiche le message Merci d'avoir appuyé sur une touche */ } return (0). Commentez le précédent programme. appuie sur une touche s'il te plaît  2.Corrigés des exercices du chapitre 1 Ecrire un programme qui écrit au revoir. programme4.c #include <stdio.. Ecrit  Merci d'avoir appuyé sur une touche  programme5. . Ecrit  Salut toi. Déjà fait ! 13 . } Ecrire un programme qui : 1.. appuie sur une touche s'il te plaît"). Attend l'appui d'une touche 3. /* Attend la frappe d'une touche */ puts ("Merci d'avoir appuyé sur une touche").h> void main() { puts("Au revoir ").h> int main () { puts ("Salut toi.

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

Syntaxe : La syntaxe de printf est très complexe et pourrait à elle seule faire l'objet d'un cours. Écrire dans une variable ayant déjà une valeur revient à la modier. La manière la plus simple de donner une valeur à une variable est l'opérateur mathématique =.. /* Attendre l'appui d'une touche */ return (0).. beaucoup. beaucoup plus puissante. C'est vrai mais ce n'est pas susant.h> int main () { printf ("Coucou c'est moi\n"). Celle-ci est beaucoup. 15 .c #include <stdio. nous en verrons donc des applications au fur et à mesure des besoins. /* Affiche Coucou c'est moi à l'écran */ getchar().2 Variable Comme son nom l'indique une variable est quelque chose qui varie. La manière la plus facile de lire le contenu d'une variable est la fonction printf que l'on a aperçue précédemment. Une variable peut être considérée comme une boîte dans laquelle on met des données que l'on peut lire ou écrire.Chapitre 2 Les variables (1e partie) 2.1 printf : fonction indispensable pour acher le contenu d'une variable programme7. 2. } On pourrait dire que la fonction printf est la même que l'instruction puts vue précédemment mais il n'en est rien.

Une variable ne peut contenir qu'une seule chose à la fois. } Explications : 1. printf ("i vaut %d. : %c signie que l'on attend une valeur de type caractère.3 Déclaration d'une variable La déclaration d'une variable se fait simplement en écrivant : <son type> <son nom> . On met dans la variable 2. /* i vaut 65 */ car = 'E'. 16 . /* car: variable de type caractère */ i = 65. 2.\n". Si vous mettez une seconde donnée dans la variable.c #include <stdio.4 Application : exemple programme8. car la valeur de E. : %d signie que l'on attend une valeur entière. 4. /* Affiche la valeur de i */ printf ("car vaut %c.car). la précédente est eacée. printf ("car vaut %c \n".h> int main () { int i. \n permet de réaliser un retour chariot c'est à dire un retour à la ligne. Exemples de type de variables : char : caractère int : entier 2. le programme va donc remplacer le %d par la valeur de i. je dis donc la valeur de E et non E car c'est le code Ascii de E qui est sauvegardé dans cette variable. Note : En informatique. i) . car) . tout n'est que nombre. i). /* car vaut E */ printf ("i vaut %d. le programme va donc remplacer le %c par la valeur de car. 3.\n".\n". Nous reviendrons là dessus un peu plus tard. On met dans la variable i la valeur 65. /* Attendre l'appui d'une touche */ return (0). /* Affiche la valeur de car */ getchar(). /* i : variable de type entier */ char car.

2. car = 'E' . faîtes acher. car = '\ . %d est remplacé par la valeur numérique de i c'est à dire 65. i = 7 . En utilisant ce qui a été fait précédemment. donnera au nal pour valeur de car la valeur de 'h'.7 Réutilisation d'une variable On peut réutiliser une variable autant de fois que l'on veut. 2. 185 et 30.6 Exercices d'applications directes 1. car = 'h' . Pour déclarer un caractère avec la valeur ' (prononcée quote en informatique et non pas apostrophe Pour acher un (français)). Le %c est remplacé par la valeur alphanumérique (ASCII) de i c'est à dire A (cf. donnera au nal pour valeur de i la valeur 7.8 Caractères spéciaux Certains caractères utilisés par la fonction printf ( %  par exemple) ou même tout simplement pour déclarer une variable (' pour les caractères par exemple) obligent à utiliser le caractère de suxe \ pour pouvoir être achés. U. C. car = 'G' . o. nous donnera l'achage suivant : A. la précédente valeur étant eacée :   i = 3 . En utilisant ce qui a été fait précédemment. Exemple : % avec printf j'écrirai : printf("La réduction était de 20 \%") .i).i. O.2. i = 5 . 17 . on écrira : char car . 2. 82. i =65. 2. Le caractère 65 est Le Table Ascii en Annexe). faîtes acher les valeurs 70. Cette transformation lui est fourni dans la suite de l'instruction) en la transformant dans le type est appelé un cast.5 Utilisation multiple du % Le code  %x  signie que le compilateur C doit remplacer ce code par la valeur correspondante (qui x. Exemple : int i. u. printf ("Le caractère %d est %c". les caractères c.

on \". that is the question. utilise le ."  avec les " bien sûr. on ache à la suite.9 Exercices à réaliser 1. Coucou 17 2. Ecrire un programme qui écrit :  Hamlet says "To be or not to be. Rappel : caractère \ Pour pouvoir acher un caractère de syntaxe C. réaliser un programme qui réalise l'achage suivant : C O U Cou 1 2 3 456 C'est rigolo Rappel : Pour mettre une variable c égale à ' on écrit c='\ 3. Aide : Sans retour chariot. Pour obtenir un 18 ".2. on utilise donc ". Faire un programme qui réalise l'achage suivant en utilisant les variables. De la même façon. par exemple comme préxe à ce caractère.

%d. en utilisant ce qui a été fait précédemment.b). i=70. %d.\n".c #include <stdio. programme9. 185 et 30. c=30. les valeurs 70. 82.h> int main () { int i.Corrigés des exercices du chapitre 2 Faites acher.\n". .\n".i).c). printf ("i printf ("a printf ("b printf ("c getchar().a.a). 19 %d. %d.c. b=185. } vaut vaut vaut vaut return (0).b.\n". a=82.

Faites acher, en utilisant ce qui a été fait précédemment, les caractères 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 réalise l'achage :

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 réalise l'achage :

C
O
U
Cou
1
2
3
456
C'est rigolo

programme12.c
#include <stdio.h>

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();

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';

}

22

return (0);

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

Chapitre 3 Les variables (2e partie) Durant tout ce chapitre.  attend l'appui d'une touche .1 Exercice de mise en bouche Ecrire un programme qui :  écrit  Calculatrice :  et saute 2 lignes . 3.  écrit  Valeur de a :  et saute 1 ligne . de faire une malheureuse calculatrice. Attention : An de pouvoir utiliser la bibliothèque mathématique du C (#include il est nécessaire d'ajouter au moment de l'édition de liens -lm ce qui nous donne : <math. Pour plus de facilité. Pas à pas. mais complet et complexe dans sa programmation.  écrit  Valeur de b :  et saute 1 ligne . Celui-ci s'eectue de la façon suivante : 24 .  écrit  Valeur de a + b :  . gcc -o monprog monprog.  assignant à ces deux variables les valeurs 36 et 54 . Pour faire acher le résultat il est possible d'utiliser la fonction printf directement ou indirec- tement en utilisant une troisième variable.h>). nous aurons pour but simple.o -lm 3. nous allons utiliser un achage direct.  faisant acher le résultat de la somme de a + b (et non pas en faisant acher 90 !).2 Déclaration des variables Complétez le programme en :  déclarant 2 variables a et b de type int (entier) . nous allons maintenant réaliser notre petit programme de calculatrice.  attend l'appui d'une touche .

. bien sûr. il est nécessaire d'utiliser la fonction scanf. &a) . 25 s.B. Achez la valeur de résultats qu'auparavant. La fonction scanf s'utilise de la façon suivante : Saisie de la valeur a : scanf ("%d". Et là ça peut faire mal. %d est remplacé par la valeur de 3. Au début du programme. assignez à Exemple : a et à b la valeur 0. s avec la valeur de a + On devrait avoir les même . Une fois les valeurs de a et b saisies. il est possible d'initialiser une variable dans le même temps que sa déclaration.Mais ceci est une autre histoire. Pour saisir une variable. rien de plus simple. après leur déclaration.&a). /* Saisie de la valeur de a */ printf ("Valeur de a :\n"). Déclarer une troisième valeur de type ment b. Nous allons maintenant saisir les variables de a. Aïe aïe aïe. ajoutez à la n de la déclaration d'initialisation : Exemple : Evolution du logiciel : exercice = suivi de la valeur int i = 10 .. a+b. Appuyez sur la touche Enter (Entrée) après avoir tapé votre valeur.. initialisez Comme en mathématiques élémentaires.a+b) . s int (penser à l'initialiser à 0) que l'on nommera bête- comme somme.Le printf ("Valeur de a + b : %d". Pour aller plus rapidement. on reconnaît le %d pour la saisie d'un nombre entier. scanf ("%d". En fait &a signie  l'adresse mémoire de a scanf . La fonction l'emplacement mémoire (la petite boîte contenant la variable) de a. Si tout s'est bien passé. Le & devant le a signie écrire dans la variable a. la saisie de b a et b. vous avez maintenant entre les mains une super calculatrice qui réalise des additions ! N. va donc écrire dans Si l'on oublie le &.3 Saisie des variables Si une calculatrice se limitait à exécuter la somme de deux nombres xes. Pour cela.. Comme pour que l'on va Aïe. je mets ici le code pour la saisie reste à faire par vos soins à titre d'exercice. a = 0. très mal. à une autre adresse. on écrira chez quelqu'un d'autre. dur dur d'être informaticien. Pour exemple. printf. Il est conseillé d'initialiser les variables avant de les utiliser. J'ai envie de faire une super calculatrice et je me dis qu'en fait la simplicité qui a eu lieue tout à l'heure n'est pas forcément adaptée à l'évolution désirée. le boulier serait encore de mise.

b a a a a + b + c -b-c / b / c * b * c et c sont des La fonction Compléter les 4 programmes an de réaliser les opérations suivantes : nombres à virgules (float).Exercices d'application : Réalisez 2 petits programmes qui font :  la soustraction de 2 nombres . abs permet d'obtenir la valeur absolue d'un nombre entier. Ce petit morceau de programme saisit la valeur de a et la fait acher : float a. Le type float permet de déclarer float au lieu un nombre à virgule. getchar ().a). Ouah. scanf ("%f".  la multiplication de 2 nombres. Tester avec une division par 0 ! ! ! La solution à ce petit problème sera vu dans le cours sur les conditions (if). d'utilisation de ceil : S = ceil (a/b) .&a). Utiliser cette fonction pour calculer la valeur absolue de (a-b). printf ("\na vaut : %f". les 4 opérations ! ! ! Créer un quatrième programme qui réalise la division de deux nombres. Exemple d'utilisation de abs : S = abs (a-b) . Pour un achage plus agréable il est possible de façon suivante : Exemple : xer le nombre de chires après la virgule de la %. printf ("Saisie de a :"). ceil permet d'obtenir l'arrondi entier supérieur d'un nombre réel. Utiliser cette fonc/ b).[nombre de chiffres après la virgule]f printf ("%. Un nouveau type : les nombres à virgule ou ottants (float). La fonction tion pour calculer l'arrondi supérieur de (a Exemple 26 . Exercices à réaliser s = s = s = s = où a.2f". et pour acher le résultat. Transformez les 3 précédents programmes en utilisant le type du type int et %f Petite aide : pour saisir les valeurs de a et b.a) .

b=0. scanf("%d".h> #include <math. printf("Valeur de a : ").&b). printf("Valeur de b : "). /* Affichage de la différence */ } getchar ().h> int main () { int a. int d. /* Déclaration des variables */ /* Différence entre les 2 nombres */ a=0. scanf("%d".c #include <stdio. return (0). printf("\n").d). d=a-b. 27 .b.&a). printf("Valeur de a-b : %d\n". /* Initialisation des variables */ printf("Calculatrice :\n\n").Corrigés des exercices du chapitre 3 Soustraction de 2 nombres programme14.

printf("\n").h> #include <math. printf("Valeur de b : ").Multiplication de 2 nombres programme15. scanf("%d". scanf("%d".&b). m).b. m = a*b. /* Déclaration des variables */ /* Résultat de la multiplication */ /* Initialisation des variables */ printf("Calculatrice :\n\n"). int m. b=0. return (0).h> int main () { int a. /* Affichage de la multiplication */ } getchar (). a=0.c #include <stdio.&a). printf("Valeur de a*b : %d\n". printf("Valeur de a : "). 28 .

float m. /* Initialisation des variables */ printf("Calculatrice :\n\n").Transformez les 3 précédents programmes avec le type float Aucune diculté dans cet exercice. scanf("%f". je ne mettrai ici la correction que de la multiplication. Pour la soustraction : m = a .b. return (0).b.&a). printf ("Valeur de a+b : %f". m). printf("\n"). 29 .c #include <stdio. /* Affichage de la multiplication */ } getchar (). m). m). printf ("Valeur de a-b : %f". programme16. Pour l'addition : m = a + b. printf("Valeur de b : ").h> #include <math.&b). scanf("%f". les autres opérations se réalisent sur le même schéma. printf("Valeur de a*b : %f\n". /* Déclaration des variables */ /* Résultat de la multiplication */ a=0.h> int main () { float a. printf("Valeur de a : "). m = a*b. b=0.

b=0. scanf("%f". /* Déclaration des variables */ a=0.h> int main () { float a.h> #include <math. return (0).s).b.c.2f\n".&b). scanf("%f". scanf("%f". s=0.Calculer la somme a + b + c programme17. /* Saisie variables flottantes */ s = a+b+c. /* Affichage de la somme */ } getchar ().s.&a). printf("Saisie de b : ").c #include <stdio. printf("Saisie de c : "). c=0. 30 .&c). /* Calcul de la somme */ printf("Valeur de s : %. /* Initialisation des variables */ printf("Saisie de a : ").

Calculer la diérence

a - b - c

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

a * b * c

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

/* Calcul de la différence */
/* Affichage de la différence */

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

a / b / c

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

a - b

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

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

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

a + b

c=ceil(a/b);
printf("Valeur de c : %f\n",c);
Il aurait été possible d'utiliser

%d

/* Calcul de l'arrondi */
/* Affichage de l'arrondi */

du fait que l'arrondi est un nombre entier !

31

Chapitre 4

Les conditions
4.1 Exercice de mise en bouche
Ecrire un programme qui met en application le théorème de Pythagore pour calculer l'hypothénuse
d'un triangle rectangle.

Rappel :

Dans un triangle rectangle, l'hypothénuse (le plus grand côté) peut se calculer en ap-

plicant la formule suivante :
hypothénuse =

p2 2
a +b

où a et b sont les longueurs des côtés adjacents à l'angle droit.

Notes : 

La racine carrée s'obtient par l'utilisation de la fonction sqrt (valeur) contenue dans

la bibliothèque math.h. (#include
2 

peut s'obtenir par a*a.

a

Méthodologie :

<math.h>)

1. Rechercher les variables nécessaires et les déclarer dans le programme.

2. Faire saisir a au clavier.
3. Faire saisir b au clavier.
4. Eectuer l'opération de la racine carrée et acher le résultat.

Attention :

An de pouvoir utiliser la bibliothèque mathématique du C (#include

il est nécessaire d'ajouter au moment de l'édition de liens

-lm ce qui nous donne :

gcc -o monprog monprog.o -lm

4.2 Les conditions : Si Alors Sinon
if (condition vraie)
{
instructions 1
}
else
{
instructions 2
}
32

<math.h>),

si (condition vraie)
{
alors
faire instructions 1
}
sinon
{
faire instructions 2
}
Les conditions s'expriment avec des opérateurs logiques.

4.3 Opérateurs logiques
Ils servent à comparer deux nombres entre eux.

Libellé

Opérateur

Inférieur

<

Supérieur

>

Egal

==

Diérent

!=

Inférieur ou égal

<=

Supérieur ou égal

>=

4.4 Opérateurs logiques purs
Ce sont des opérateurs logiques permettant de combiner des expressions logiques.

Libellé

Opérateur

Et (and)

&&

Ou (or)

||

Non (not)

!

| se nomme en informatique un pipe (prononcer païpe).

4.5 Vrai ou faux
Vrai peut être assimilée à la valeur numérique
Faux peut être assimilée à la valeur numérique
L'opérateur Ou (||) correspond alors à une addition.
La valeur

1 ou à toute valeur non nulle.

La valeur

0.

Ou

Vrai

Faux

+

1

0

Vrai

Vrai

Vrai

1

2

1

Faux

Vrai

Faux

0

1

0

33

on en déduit que ce code signie que si (er != 0) /* si er différent de 0 */ { /* Alors faire quelque chose */ } 4. 34 . La seule condition d'utilisation d'un si (if) avec de telles combinaisons est de l'entourer de (). else printf ("car est différent de b.8 Les accolades Les accolades entourant les blocs d'instructions d'une condition peuvent être omises si le bloc n'est constitué que d'une seule instruction. Exemple : if ((car == 'a') || (car == 'A')) 4."). 4.").L'opérateur Et (&&) correspond alors à une multiplication Et Vrai Faux * 1 0 Vrai Vrai Faux 1 1 0 Faux Faux Faux 0 0 0 On notera que !Vrai = Faux et !Faux = Vrai. Exemple : if (car == 'b') printf ("car vaut b.6 Combinaison Toutes les opérations logiques peuvent se combiner entre elles.7 Astuce Vous verrez souvent ce type de code écrit : if (er) { /* Alors faire quelque chose */ } En appliquant ce qui a été vu précédemment.

4. On considèrera que le caractère saisi est en minuscule. Faites saisir une variable de type entier et indiquez à l'utilisateur si celle-ci est strictement positif ou strictement négatif ou nulle. 35 .9 Exercices 1. Aide : if (a>0) printf ("Valeur positive"). Faites saisir une variable de type caractère et indiquez à l'utilisateur si celle-ci est une voyelle ou une consonne. else printf ("Valeur négative"). 2.

/* base du triangle */ float b. programme18. /* valeur de l'hypoténuse (p pour Pythagore !) */ /* Initialisation des variables pour palier aux erreurs */ a = 0. /* Saisie de a */ printf ("Valeur de la base : ").&a).&b). 36 . } return (0). b = 0. /* Calcul par Pythagore */ p = sqrt (a*a + b*b). scanf ("%f". scanf ("%f". /* Saisie de b */ printf ("Valeur du côté : ").p). /* côté du triangle rectangle */ float p.c #include <stdio.2f\n".h> #include <math.h> int main () { float a. /* Attendre avant de sortir */ getchar (). /* Affichage du résultat */ printf ("L'hypoténuse mesure : %.Corrections des exercices du chapitre 4 Écrire un programme qui met en application le théorème de Pythagore.

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

} } getchar ().Tester si un caractère saisi au clavier est une consonne ou une voyelle. return (0).c #include <stdio.&car). programme20.\n"). /* 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.h> int main () { /* Valeur que l'on va saisir */ char car. 38 .\n"). /* Saisie du caractère a */ printf("Saisie du caractère : "). } else { printf("la variable car est une consonne. scanf("%c".

Ce cours sera donc constitué de 3 exercices de diculté croissante avec apprentissage d'une nouvelle fonction et d'un exercice complet de programmation. 5. 5. 39 .Chapitre 5 Mise au point 5.1 Prologue L'objet de ce cours est de réaliser un petit break dans l'apprentissage du C et de s'attacher à voir ce que l'on est capable de réaliser avec le peu de moyen que l'on a. Exemple : si (nbre_saisi<10) alors "plus petit" Reprendre l'exercice du chapitre 4 qui disait si un nombre est strictement positif. 2 utilisations peuvent être faites de getchar ().2 Exercice 1 Réaliser un programme qui saisisse un nombre et indique à l'utilisateur si celui-ci est plus grand ou plus petit qu'un autre nombre xé par le programme. la première est celle permettant d'attendre la frappe d'une touche sans se soucier de sa valeur. la seconde est celle permettant de lire un caractère au clavier.3 Retour sur getchar() La fonction getchar () permet d'attendre la frappe d'un caractère au clavier. strictement négatif ou nul. de le lire et de le renvoyer.

le retour chariot utilisé pour la saisie du caractère étant renvoyé et interprété nous donne un achage double. } return (0). car = getchar () . Attente getchar () . 40 . while. Malgré celà. traduisez par Faire . } while (!sortie). 2.Exemples : 1. int sortie. nous nous en contenterons.  || signie un ou logique (or). 5. Saisie d'un caractère char car . do { printf ("Tapez S pour sortir !\n"). Rappel :  Un nombre entier vaut la valeur logique vraie si celui-ci est diérent de 0. Tant que permet de réaliser une suite d'instructions tant qu'une condition ou un ensemble de conditions est rempli.c #include <stdio.h> int main () { char car. Remarque : Cette utilisation n'est pas très belle. Exemple : programme21.. getchar () eectue le même traitement :  Attendre la frappe d'une touche au clavier suivi d'un retour chariot (Entrée). Tant que (vrai) Do . A chaque fois..  Un nombre entier vaut la valeur logique faux si celui-ci est égal à 0. Dans le 1 er cas.4 Boucle Faire . /* On saisit un caractère */ car = getchar ().. au niveau de ce cours.... /* On le compare pour savoir si l'on peut sortir */ sortie = ((car == 's') || (car == 'S')).  Renvoyer le caractère frappé. ce caractère n'est simplement pas récupéré.

Attention : La saisie d'un nombre ne se fait pas par getchar mais par scanf (cf. Chapitre 3). Initialise un nombre entre 0 et 100 .h> int main() { int nb_alea. comprenez le. 41 . /* Nombre aléatoire */ srand (time (NULL)). 2.h> #include <time.5 Exercice 2 Tapez l'exemple précédent.c #include <stdio. } getchar (). programme22.6 Exercice 3 Voici un petit exemple de programme qui permet d'obtenir des nombres aléatoires entre 0 et 100. printf ("%d".nb_alea). srand (time (NULL)) permet d'initialiser le système aléatoire.h> #include <stdlib.5. rand () permet d'obtenir un nombre entre 0 et RAND_MAX. Tente de faire deviner ce nombre à l'utilisateur en lui indiquant s'il est plus petit ou plus grand. réalisez un petit jeu qui : 1. ((float) rand () / RAND_MAX) permet d'obtenir un nombre entre 0 et 1. aménagez le. 5. puis transformez le an que l'on sorte de la boucle uniquement lorsque l'utilisateur a tapé le nombre 10. return (0). En vous aidant de ce petit programme et de ce qui a été fait précédemment. /* Initialisation des nombres aléatoires */ /* Le nombre aléatoire est stocké dans une variable puis affiché */ nb_alea = (int) (((float) rand () / RAND_MAX) * 100). (float) rand () permet de dire au langage C que l'on désire réaliser des calculs avec des nombres à virgules (ottants). qui multiplié par 100 nous donne un nombre entre 0 et 100.

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

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

else { if (nb_hasard > votre_nb) /* il peut être aussi égal . 44 .h> #include <stdlib.programme25.h>/* pour les valeurs aléatoires */ #include <time.&votre_nb).c #include <stdio. */ printf ("\nVotre nombre est plus grand\n").. } } while (votre_nb != nb_hasard). nb_hasard = (int) (((float) rand () / RAND_MAX) * 100). int votre_nb = 0.h> int main () { int nb_hasard = 0. scanf("%d". } return (0).. /* Nombre entre 0 et 100 */ do { printf("Votre nombre : "). if (nb_hasard < votre_nb) printf ("\nMon nombre est plus petit\n"). srand (time (NULL)). printf ("Trouvé\n"). getchar ().

h" à notre programme (ce chier est livré avec la bibliothèque) .} 45 d'utiliser : .1 Préambule Du fait que la fonction getchar() attend l'appui de la touche bibliothèque créée pour le cours.. asciiart.. les bibliothèques du compilateur sont insérées via la bibliothèque> et les personnelles sont insérées via A noter que dans le cas d'une bibliothèque personnelle.o asciiart. Elle donne entre autres accès à la fonction Enter.o  linker le programme avec Vous pouvez utiliser cette fonction dans les exercices. L'explication en est simple. celle-ci doit se situer dans le même répertoire que le programme source (du moins on le considèrera dans le cadre de ce cours). .. Une fonction similaire (getche()) fait le même travail mais ache le caractère Entrée..Chapitre 6 Et les shadocks pompaient 6. chaque fois que vous souhaitez attendre l'ap- pui d'une touche.o : gcc -o mon_prog mon_prog.2 While De la même façon que do {. nous allons utiliser une ASCIIART et est détaillée en getch() qui permet la saisie d'un caractère sans attente de retour chariot. #include est diérent de celui utilisé précédemment. 6.. les <.> ont été #include <nom de #include "nom de la bibliothèque". On remarquera que le remplacés par des " ". il nous faut :  ajouter #include "asciiart. Pour l'utiliser. Cette bibliothèque se nomme annexe.} while(condition). il est possible while (condition == Vrai) {..

Si condition est fausse. compilez. on tombe alors dans un puîts. complétez avec les variables nécessaires. Si condition est toujours vraie. 46 qui transforme un ca- . comprenez : Faire Saisir une touche Tant Que (touche != S) et (touche != s) Exercice 2 Traduisez en langage C. } Attention : while (condition) .Exemple : char car = ' '. on passe alors immédiatement à la ligne/commande suivante. complétez avec les variables nécessaires. exécu- tez.h>) ractère minuscule en majuscule. 6. compilez.4 Fonction toupper () Le problème de la comparaison de la minuscule et de la majuscule de l'exercice 1 peut être contourné par l'utilisation de la fonction toupper (#include <ctype. while ((car != 's') && (car != 'S')) { car = getche ().3 Et les Shadoks apprenaient que reprendre équivaut à apprendre Exercice 1 Traduisez en langage C. exécu- tez. on revient à la même ligne. comprenez : Faire Saisir un nombre Tant Que (nombre != 10) Attention : La saisie d'un nombre ne se fait pas par la fonction scanf (reportez vous getch () mais par la fonction au chapitre correspondant pour plus de précisions). 6. signie que tant que condition est vrai.

car_min = 'a' car = toupper (car_min).La fonction toupper s'utilise de la façon suivante : int main () { char car. Un compteur est une variable numérique que l'on décrémente (-1) ou incrémente (+1) suivant nos besoins. 47 . } return (0).car). printf ("%c".6 Et les Shadoks continuaient à pomper pour obtenir le résultat Dans les exercices qui suivent.5 O tant que en emporte le Shadok Exercice 3 Ecrire le programme : Exercice 4 Ecrire le programme : Tant que je ne tape pas un nombre impair compris entre 1 et 10 je recommence la saisie d'un nombre Tant que je ne tape pas une voyelle je recommence la saisie d'une touche 6. 6. i--.*/ Dans les exemples précédents. i--.*/ revient à la même chose que i = i-1. Exemples : int i. char car_min. la notion de compteur intervient. i++. /* /* /* /* Incrémente le compteur i */ Décrémente le compteur i */ revient à la même chose que i=i+1. le nombre de caractères entrés peut donc être comptabilisé en ajoutant 1 à une variable à chaque fois qu'une touche est frappée. i++. Le programme précédent achera A.

7 Au clan des Shadoks. je recommence la saisie d'une touche Tant que je n'ai pas saisi 10 nombres. je recommence la saisie d'un nombre 6. voyelles. Exercice 8 Ecrire le programme : Tant que je n'ai pas saisi 10 chiffres premiers (1. 48 .7). je recommence la saisie d'un chiffre On prendra soin d'indiquer à l'utilisateur combien de chires premiers il lui reste à entrer. je recommence la saisie d'une touche On prendra soin d'indiquer à l'utilisateur combien de voyelles il lui reste à entrer.3. on trie.Exercice 5 Ecrire le programme : Exercice 6 Ecrire le programme : Tant que je n'ai pas saisi 10 caractères. chires premiers Exercice 7 Ecrire le programme : Tant que je n'ai pas saisi 10 voyelles.5.

Corrigés des exercices du chapitre 6 Exercice 1 programme26.h> #include "asciiarth" int main () { char car = 0.\n"). printf ("Tapez 10 pour arrêter .. return (0). } Exercice 2 programme27. &nbre).c #include <stdio..h> int main () { int nbre = 0.. return (0). do { scanf ("%d". printf ("Tapez S pour arrêter . } while ((car != 's') && (car != 'S')).c #include <stdio. } 49 . do { car = getch (). } while (nbre != 10)..\n").

} printf ("Tapez un chiffre impair pour arrêter .. 50 ..c #include <stdio.h> int main () { int nbre = 0.. &nbre). } printf ("Tapez un chiffre impair pour arrêter .c #include <stdio.. } return (0). while ((nbre != 1) && (nbre != 3) && (nbre != 5) && (nbre != 7) && (nbre != 9)) { scanf ("%d".\n"). ou bien : programme29.Exercice 3 programme28. while ((nbre < 0) || (nbre > 10) || (nbre%2==0)) { scanf ("%d".\n"). } return (0).h> int main () { int nbre = 0. &nbre).

51 .h> #include "asciiart. car = toupper (car). printf ("Tapez une voyelle pour arrêter .. } Exercice 5 programme31.Exercice 4 programme30.").c #include <stdio.. int nbre = 0. } while (nbre != 10).h> #include <ctype. printf ("Tapez 10 caractères pour arrêter .\n").h> #include "asciiart.h" int main () { char car = ' '. return (0).c #include <stdio.. while ((car != 'A') && (car != 'E') && (car != 'I') && (car != 'O') && (car != 'U') && (car != 'Y')) { car = getch (). nbre ++..h" int main () { char car = ' '. } return (0). do { } car = getch ().

&nbre).h> #include "asciiart. } return (0).nb_nbre).c #include <stdio. printf ("Tapez 10 nombres pour arrêter ... } while (nb_nbre != 10). int nb_nbre = 10."). do { car=getch(). 52 .. if (car=='A' || car=='E' || car=='I' || car=='O' || car=='U') { nb_nbre--.h> int main () { int nbre = 0. printf ("Tapez encore %d voyelles pour arrêter. nb_nbre ++. car=toupper(car).nb_nbre).Exercice 6 programme32..\n"..c #include <ctype. int nb_nbre = 0. } } while (nb_nbre != 0). } return (0).h" int main () { char car.. do { scanf ("%d".\n". Exercice 7 programme33. printf ("Tapez encore %d voyelles pour arrêter.

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

} Par souci de simplicité. i++) { instr. for for (i=point de départ. une variable de type entier (int par exemple)).1 Et les shadoks pédalèrent pendant 15 tours Pour faire eectuer un certain nombre de fois une tâche. } signie que l'on va exécuter instr pour i variant de 0 à 14 (<15) c'est à dire 15 fois. on utilise l'instruction suivante (avec i. 54 de la façon .Chapitre 7 Les boucles 7. i=i+pas) { instruction(s) répétée(s). nous dirons simplement que la formule suivante : for (i=0. i<15. i<point d'arrivée.

i). } printf ("Je me suis répétée.. Exemple : On peut utiliser cette fonctionnalité dans le programme précédent en remplaçant : for (i=0. i++) printf ("Je me répète pour i valant %d\n".c #include "asciiart.h> int main () { int i.2 Syntaxe De la même façon que le if. } 7. i<15. getch (). Exercice 1 couleur Aide : i  où Utilisez une boucle pour i i variant de 0 à 7 inclus pour acher :  Ceci est la est remplacé par sa valeur et où la phrase est écrite avec la couleur La fonction i.i). i<15. i++) { printf ("Je me répète pour i valant %d\n". i<15. printf ("Ceci est la couleur %d". } par for (i=0. 15 fois\n"). La fonction textreset()de la bibliothèque permet de remettre les valeurs par défaut (à employer avant de terminer un programme).i).. le for ne nécessite pas d'accolades si le nombre d'instructions à répéter est de 1. return (0).i).Exemple : programme35. 55 . textcolor(i) de notre bibliothèque asciiart change la couleur courante : textcolor (i). i++) { printf ("Je me répète pour i valant %d\n".h" #include <stdio. for (i=0.

. passe à la ligne... for (i=0. écrit deux étoiles. return (0).h> int main () { int i. } } Exercice 2 } getch (). On obtient donc : Pour i allant de . passe à la ligne... j vaut %d\n". } } Exemple : programme36. i vaut %d\n". En utilisant la double boucle. écrire un programme qui écrit une étoile..j).. for (j=3. à . { .i).... j>0.7... { . jusqu'à cinq étoiles an d'obtenir ceci : * ** *** **** ***** 56 . j--) { printf ("Je suis dans la boucle j. à .. int j.h" #include <stdio.3 Notion de double boucle Il est possible de remplacer les instructions par une boucle an de réaliser une double boucle. i++) { printf ("\nJe suis dans la boucle i. écrit trois étoiles.. Pour j allant de .c #include "asciiart. i<5.

4. o  Sur la ligne n i.3 Achage des boules de Noël On peut rajouter des boules des Noël dans le sapin en modiant le dessin du feuillage et en remplaçant aléatoirement certains caractères @ verts par un 57 O de couleur diérente. . on ache 9 espaces puis 1 étoile . Vous devriez obtenir ceci (en brun) : @@@ @@@ @@@ 7.1  Cône  du sapin À l'aide d'une double boucle.4. j<((2*i)-1). il nous faut maintenant dessiner le tronc. o  Sur la ligne n 2. on ache 8 espaces puis 3 étoiles . Ecrire la suite du programme en dessinant le tronc à l'aide du caractère @.2 Achage du tronc Pour poursuivre le sapin. Vous devriez obtenir ceci : * *** ***** ******* ********* *********** ************* *************** ***************** ******************* Aide : o 1.7.  Sur la ligne n On obtient donc par exemple pour l'achage des étoiles sur la ligne i : for (j=0. j++) { printf ("*"). } 7. on ache 10-i espaces puis 2*i-1 étoiles.4... o  Sur la ligne n 3. réalisez un cône pour dessiner le haut du sapin en vert sur 10 lignes. 7. on ache 7 espaces puis 5 étoiles .4 Exercice 3 : Et les Shadoks fêtèrent Noël.

printf("O"). i=rand()%10. Exemple : int i = 65. on écrit : printf ("%03d : %c". printf("@"). Ecrire un programme qui fait acher sur des lignes successives puis de façon propre. printf ("%03d : %c".Aide : On peut tirer un nombre aléatoire entre 0 et 9 ainsi (voir chapitre 5) : int i. code_ascii) . // affichera 065 : A 58 . On pourra donc remplacer la ligne qui trace un élément de feuillage : printf("@"). i). srand (time (NULL)). code_ascii. par : if (rand()%10==0) { textcolor(rand()%8).5 Exercice 4 : Table Ascii Les codes Ascii (i. } else { textcolor(2). par exemple un tableau sur 8 colonnes. les nombres qui représentent les caractères en informatique) vont de 0 à 255. } 7. i. les codes Ascii avec les caractères qui leur correspondent (On pourra commencer l'acher à partir du code 32). Aide : Pour faire acher le caractère associé à un code Ascii.e.

Corrigés des exercices du chapitre 7 Exercice 1 programme37. int j. i). } Exercice 2 programme38. } getch (). i++) { textcolor (i). j++) { printf ("*"). for (i=0. return(0).c #include <stdio.h> #include "asciiart. j<=i.c #include <stdio. } 59 . for (i=1.h> #include <stdlib. printf ("Ceci est la couleur %d\n".h> #include "asciiart.h" int main () { int i. } printf ("\n"). return(0). i++) { for (j=1.h> #include <stdlib. i<=7.h" int main () { int i. } getch (). i<=5.

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

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

Exemple de la vie courante : 62 . Une variable (par exemple char car) est en fait une petite zone mémoire ici de 1 octet que l'on s'alloue et où l'on va ranger les informations.1 Variables : pointeurs et valeurs 8. pour nous il utilise 4 octets c'est à dire 4 cases mémoire. Cependant.Chapitre 8 Pointeurs et Fonctions Peu d'exercices dans ce cours dans lequel l'important est de comprendre les nombreux exemples cités.car). Représentons-nous la mémoire comme une rue remplie de maisons. on parlera d'adresse mémoire. Le type int varie selon les compilateurs. Chaque type de variable utilise au moins 1 octet. 8. une adresse mémoire d'une case mémoire est unique mais rien ne vous empêche de vous tromper intentionnellement ou non de case mémoire. De la même façon. pour une case mémoire.1 Les variables et la mémoire. Nous avons vu précédemment qu'il était possible de voir le contenu d'une variable avec la fonction printf fonction et qu'il était possible de mettre une valeur dans une variable avec l'opérateur scanf.1. printf ("%c". Chaque case mémoire est représentée par une maison. L'adresse est unique pour chaque maison. Chaque maison porte un numéro. = ou la Exemple : char car = 'C'. son adresse postale. rien ne vous empêche de vous tromper intentionnellement ou non de maison.

l'adresse mémoire est accessible en faisant précéder la variable de l'opérateur &. Les pointeurs sont dénis par un type et se déclarent de la façon suivante : type* variable. int nbre = 12.e. On ajoute "l" devant le u u (%lu) et devant le x (%lx) an de faire acher un entier long (> 65536). &nbre). Les crochets ne sont là que pour des raisons d'esthétique.2 Pointeurs Pour utiliser les adresses mémoire des variables à la place des variables elles-mêmes. signie un nombre non signé. Le type permet simplement de savoir comment le compilateur C doit interpréter l'adresse mémoire lors de sa lecture. on utilise les pointeurs. l'utilisation d'une adresse mémoire. 63 . printf ("Adresse de nbre : %lu [%lx]". Le signe * indique l'utilisation d'un pointeur i.1. 8. Pour enregistrer une valeur dans une adresse mémoire on écrit : *variable = <valeur> *variable signie contenu de l'adresse mémoire. Nous en verrons des exemples lors de l'utilisation des chaînes de caractères.&car.Mr Leneuf adresse : 99. grand rue Exemple en C : char car adresse : 0x001F (soit 31 en décimal) 0x signie adresse hexadécimale (en base 16). &car).&nbre. ou type *variable. En langage C. Exemple : char car = 'C'. printf ("Adresse de car : %lu [%lx]".

Signie que je rentre chez M. A l'identique de notre fonction principale main (). 8. le caractère est : %c\n". ptr_car = &car .c #include <stdio.car).car). Il indique que l'adresse mémoire est invalide. Signie que l'on m'a donné l'adresse postale de M. car et que j'y dépose le caractère E. Explicitons cet exemple à l'aide de notre rue bordée de maison. /* ptr_car = adresse de car */ *ptr_car = 'E'. printf ("Avant.3 Exercices d'application Exercice 1 Réaliser un programme équivalent qui change la valeur en K. /* i.2.car) . faire ou modier quelque chose. *ptr_car = 'E' . printf ("%c". 8. 64 une fonction s'écrit de la façon suivante : . Exercice 2 Réaliser un programme équivalent qui change une valeur numérique (int) de 10 à 35.1.Exemple : programme42. on a modifié car */ } return (0). /* on modifie le contenu de l'adresse mémoire */ printf ("\nAprès le caractère est : %c\n".h> int main () { char car='C'. char* ptr_car = NULL.e. Un bloc de programme est mis sous la forme d'une 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 !). NULL signie l'adresse 0. Signie que l'on va lire le contenu de car pour l'acher. ptr_car = &car. car.2 Les fonctions 8.1 Dénition générale Une fonction est un petit bloc de programme qui à l'image d'une industrie va créer.

car).3 Variables globales et locales Les variables déclarées dans les fonctions sont dites locales. /* Fonction bête affichant un caractère */ void Affiche_car (char car) { printf ("%c". Il existe aussi les variables dites globales qui sont déclarées en dehors de toute fonction y compris le main (). } 8. Pour les modier ou les utiliser par une autre fonction.2 Void Le type void signie indéni. il est utilisé :  comme type de sortie pour les fonctions qui ne retournent aucun résultat. il est nécessaire de les passer en paramètres.  dans la déclaration de pointeurs sur des zones mémoires dont on ne connaît pas le type. Les variables globales sont modiables et accessibles par toutes les fonctions sans avoir besoin de les passer en paramètre. Il est de ce fait extrêmement dangereux d'utiliser des variables globales.2.2. Les variables locales ne sont modiables et accessibles que dans la fonction où elles sont déclarées.<type de sortie> <nom de la fonction> (<paramètres d'appels>) { Déclaration des variables internes à la fonction Corps de la fonction } Retour 8. 65 . Exemples : /* Pointeur sur une zone mémoire indéfinie */ void* m_ptr.

/* Déclaration variable locale */ } val_retour = val * val. val_retour). val est une variable globale. return (val_retour). void carre () { val_retour = val * val. 66 . int main () { int val_retour = 0. printf ("Le carré de 2 est %d\n". } return (0).h> int carre (int val) { int val_retour = 0. } int main () { val = 2. val_retour est dans les deux cas une variable locale. val_retour). Exemple de variable globale : programme44.c #include <stdio. printf ("Le carré de 2 est : %d\n". Bien qu'elles aient le même nom dans les fonctions main et carre. } return (0). /* Déclaration variable locale */ val_retour = carre (2). carre ().h> int val = 0. int val_retour = 0.Exemple de variable locale : programme43.c #include <stdio. les deux variables n'ont rien à voir entre elles.

Ces paramètres peuvent être modier à condition qu'ils soient passés par adresse c'est à dire que la fonction reçoive un pointeur.4 Utilisation et modication de données dans les fonctions L'appel d'une fonction peut s'eectuer à l'aide de paramètres.c #include <stdio.. 67 .h> void Affiche_Nombre (int no) { printf (``Le nombre est : %d\n''. 8. } int main () { Affiche_Nombre (12). Ces paramètres peuvent être utilisés en les déclarant dans les parenthèses. Exemple : programme45..no).2. } return (0).On constate que le programme devient rapidement illisible.

int* x. prenez garde . for (i = 0. utilisant ces deux fonctions. 8.6 Exercice 3 : Reprendre le programme du sapin de Noël du chapitre précédent et réaliser 2 fonctions : (int n) & Tronc (int n) Cone qui dessinne respectivement le cône du sapin sur n lignes et le tronc en position n (n blancs avant le tronc). Ceci est une faute courante. i++) { Avance_Position (&x). augmentera l'adresse de x (on va chez le voisin) et non la valeur.. } int main () { int i=0. pour cela il faut écrire : (*x)++.. 68 . *x++.h> void Avance_Position (int* x) { *x = *x + 2. les opérateurs unaires (avec une seule opérande) sur les pointeurs sont dangereux.c #include <stdio. } } return (0). int x=0.Exemple : programme46.x).x). printf ("Nouvelle position : %d\n".2.5 Piège ! Attention. i<5.2. printf ("Position de départ : %d\n". Ecrire un programme qui. dessinne un sapin sur n lignes. 8.

Exercice 2 programme48.val). printf ("Avant le nombre est : %d\n".val). 69 . char* ptr_car = NULL. int* ptr_val = NULL.c #include <stdio. *ptr_car = 'K'.car). ptr_val = &val.Corrigés des exercices du chapitre 8 Exercice 1 programme47.h> int main () { char car = 'C'. printf ("Après le caractère est : %c\n". } return (0).c #include <stdio.h> int main () { int val = 10.car). printf ("Avant le caractère est : %c\n". ptr_car = &car. printf ("Après le nombre est : %d\n". *ptr_val = 35. } return (0).

} 70 getch (). textcolor(2). for (i=1. j=0. /* Initialisation des nombres aléatoires */ srand (time (NULL)). . int main () { int nb_lig = 15. i++) { for (j=0. j=0. } for (j=1. } } printf ("@@@\n"). } } } textcolor (3). j<= (i*2-1).2).h> <stdlib. i<=n. } } printf ("\n"). printf("O").Exercice 3 programme49. cone (nb_lig). i<=n. j++) { if (rand()%10==0) { textcolor(rand()%8). i++) { printf (" "). return (0). textreset ().h> "asciiart. void tronc (int n) { int i=0. j<=3.h> <time. } else { textcolor(2).j<n-i. for (j=1. j++) { for (i=1.c #include #include #include #include <stdio. printf("*"). tronc (nb_lig .h" // Dessin du cône du sapin void cone (int n) { int i=0.j++) { printf(" ").

/* Déclaration d'un tableau de 10 nombres.1. Nous n'utiliserons dans un premier temps que les tableaux à une seule ligne. Celui-ci peut être constitué de plusieurs lignes et colonnes. 9.2 Déclaration Un tableau se déclare de la manière suivante : <type> <nom du tableau> [<taille du tableau>] . 71 .Chapitre 9 Tableaux & Chaînes de caractères 9. Exemple de tableau de caractères : Case 0 1 2 3 4 5 6 7 Contenu A B C D E F G H Les cases d'un tableau sont numérotées à partir de 0. /* Déclaration d'un tableau de 10 caractères */ int tab_int [10].1 Dénition Un tableau est un ensemble d'éléments consécutifs.1. Exemples : char tab_char [10]. */ Un tableau à plusieurs lignes se déclare de la façon suivante : <type> <nom du tableau> [<taille 1ère dimension 1>][<taille 2nde dimension>] .1 Tableaux 9.

tab_int [6] = 10.3 Utilisation On accède à un tableau en l'appelant par son nom et son numéro de case. Exemple : char m_chaine [20] . nous parlons ici du code Une chaîne s'écrit donc : chaîne + 0.*/ 9. 72 . Attention : /* /* /* /* tableau tableau Accès à Accès à de de la la 10 cases (0 à 9) d'entiers */ 10 cases (0 à 9) de caractères */ case 3 (la quatrième) de tab_char */ case 6 (la septième) de tab_int */ Le compilateur ne vérie pas que vous utilisez le tableau dans ses limites. Exemple : Caractère Code Ascii Case Ascii) qui est considéré lui aussi comme un caractère. C'est l'un des bugs le plus courant de l'informatique. vous écrivez chez le copain.2. /* représente un tableau d'entiers de 5 lignes * 5 colonnes.2 Chaînes de caractères Les chaînes de caractères sont des tableaux de caractères suivis d'un 0 binaire (ne pas confondre avec le caractère O. Il vous est donc possible d'écrire à l'extérieur de votre tableau donc chez le voisin.  Eric  s'écrit dans un tableau de E r i c 69 114 105 99 0 0 1 2 3 4 5 caractères de la façon suivante : 9. tab_char [3] = 'C'. 9.1.Exemple : int table [5] [5]. Attention. si vous dépassez la longueur de tableau. Exemple : int tab_int[10].1 Déclaration d'une chaîne de caractères Une chaîne de caractères se déclare sous la forme d'un tableau de caractères de longueur xe. permettra d'enregistrer des chaînes de 19 caractères maximum (20-1 pour le 0 de n de chaîne). comme signalé auparavant. int tab_char[10].

Achera :  La longueur de toto est 4  à l'écran. on pourra lui aecter une valeur de la façon suivante : sprintf (<variable de type chaîne de caractères>.3 Achage d'une chaîne de caractères Une chaîne de caractères s'ache grâce à la commande Exemple : printf et le format %s.2. Le 0 de n de chaîne n'est pas compté dans cette longueur.D'autre part.4 Longueur d'un chaîne La longueur d'une chaîne de caractères s'obtient par la fonction strlen."<valeur d'init.2 Écriture dans une chaîne de caractères La première méthode de déclaration ne permettant pas d'initialiser la chaîne."Eric") .  faîtes acher la chaîne de caractères ainsi obtenue (n'oubliez pas de rajouter le 0) . 9.2. strlen (ch)) . Exemple : char ch [] = "toto" . il est possible de déclarer une chaîne de caractères sans en spécier la longueur de départ de la façon suivante : char chaine [] = "Eric" . printf ("%s".5 Exercices En utilisant une boucle (for) :  remplissez un tableau de 10 caractères avec les lettres de l'alphabet en commençant par A (code Ascii 65) .chaine) . . "%s". ch. C'est pratique à condition de ne pas la réutiliser (on ne connaît sa taille que par son contenu).  faîtes acher chaque caractère du tableau sous la forme  Caractère n 73 o 0 : A . Eric0 (le 0 n'est là que pour vous rappeler que l'on a besoin du 0 pour terminer la chaîne). "%s". printf ("La longueur de %s est : %d". 9.2. 9. 9.>") .2. Exemple : remplira m_chaine par sprintf (m_chaine.

gets( line ). celui-ci n'est pas enregistré dans le tableau de caractères. 9. Tab_car [pos]). Pour faire acher un seul caractère.2. return (0). . Attention.Rappel : Je peux écrire tant le code Aide : Tab_car [i] = code_ascii . on utilisera la syntaxe suivante : int pos /* Position dans le tableau */ printf ("Caractère nÆ %d : %c". Exemple d'utilisation programme50.pos. sinon aïe aïe aïe */ printf( "\nLa chaîne de caractères saisie est : \n%s\n".6 gets : saisie d'une chaîne de caractères Description La fonction gets permet de saisir une chaîne de caractère validée par un retour chariot. printf ("Notons qu'il n'y a qu'un retour chariot. où code_ascii est un entier représen- Ascii du caractère désigné. on suppose qu'il ne frappera pas plus de 80 caractères.\n") . line ). } Exemple d'exécution : Saisissez une chaîne de caractère : Bonjour ! La chaîne de caractère saisie était : Bonjour ! Notons qu'il n'y a qu'un retour chariot (celui aché par la fonction 74 printf).c #include <stdio. La valeur 0 peut être assignée à un élément de tableau de la façon suivante : Tab_car [la bonne position] = 0 . /* La frappe de l'utilisateur sera enregistrée dans line.h> int main(void) { char line[81]. bien que cette chaîne nécessite d'être validée par un retour chariot. /* 81 : taille arbitraire supposée suffisante */ /* Une ligne écran = 80 caractères + 1 case pour le 0 de fin de chaîne */ printf( "Saisissez une chaîne de caractère :\n" ).

on pourrait écrire : ma_saisie (&chaine [0]) &chaine[0] représentant l'adresse mémoire de la première case mémoire du tableau.. Nous allons donc créer notre propre fonction de saisie.Faire ce qu'il faut.5 et mettez 12 caractères dans votre tableau de 10 cases. } On n'utilise pas ici le passage par adresse (&) car un tableau est en fait une adresse mémoire sur une suite d'octets. 9. return (0). On peut sans se tromper dire que le cas de dépassement de la taille d'un tableau est le bug le plus fréquent rencontré en programmation C alors prenez garde.2.9.9 Exercices Réaliser votre propre fonction de saisie de chaîne de caractères... mais on ne peut pas concilier sécurité et rapidité.2... return (). ma_saisie (ma_chaine). 9. } void main () { char ma_chaine [30]. Par contre. il est nécessaire de passer en paramètre une chaîne de caractères.2. donc une adresse. Il sut de s'imaginer qu'il est nécessaire d'eectuer un test à chaque assignation d'un élément du tableau ! ! !. C'est un peu compliqué mais il sut de se dire :  je passe un tableau donc un ensemble de cases mémoire.. Note : Ce problème n'existe pas sous Turbo Pascal.7 Passage d'une chaîne de caractères en paramètres Il est bien agréable de pouvoir utiliser cette fonction mais son ecacité est très limitée. Paramètres d'entrée : chaîne de caractères.. Pour cela. Ceci s'eectue de la façon suivante : int ma_saisie (char* chaine) { . donc je ne mets pas de &  ou bien  je transmets une case donc un élément d'un type comme un autre donc je mets le & pour obtenir son adresse .8 Bugs en chaînes Reprenez l'exercice 9.. nombre de caractères maximum à saisir 75 . Essayez avec 80 caractères. ce qui fait que le C est de loin plus rapide que Turbo Pascal.2.

printf("a") . on pourra faire : printf("\b"). achera un a plus tard.fflush(stdout) ache un a instantanément. printf("a") . Aide : Pour acher un caractère à l'écran instantanément. faut utiliser    Ajouter à votre fonction de saisie de caractères la gestion de la touches backspace permettant de corriger la saisie. lors de la réception d'un retour chariot . c'est le le caractère 127 est renvoyé. il fflush(stdout)./* Retour du curseur vers la gauche */ fflush(stdout). /* force l'exécution de l'affichage immédiatement */ 76 . qui vide le buer de la sortie standard : printf("a\n") . sans envoyer de retour chariot. sans retour chariot.Algorithme : Initialiser car à une valeur diérente de 10 (valeur du retour-chariot) tant que ((car est diérent d'un retour chariot (10) ) et (nombre de caractères saisis < nombre de caractères maximum)) faire car = saisie_car acher car à l'écran ajouter car dans le tableau mettre à jour la positions dans le tableau n tant que ajouter le 0 binaire de n de chaîne. Pour acher un caractère backspace. ainsi que la gestion du retour chariot nal (qui doit être supprimé). Aide : Lors de l'appui sur la touche backspace. ache un a puis un retour chariot .

/* Ajout du 0 de fin de chaine */ tableau [10] = 0.tableau). remplissez un tableau de 10 caractères avec les lettres de l'alphabet en commençant par A (code Ascii 65). return (0). Faîtes acher la chaîne de caractères ainsi obtenue (n'ou- bliez pas de rajouter le 0).h> #include "asciiart. int i=0.1 Boucle for En utilisant une boucle (for).3.tableau [i]).c #include <stdio. /* Attente de la saisie d'une touche */ getch (). i<10. /* Saut d'une autre ligne */ printf ("\n"). i<10. } /* Remplissage du tableau avec les caractères */ for (i=0. programme51.i. int main () { /* 10 caractères + 0 de fin de chaîne */ char tableau [11]. i++) tableau [i] = 65 + i.9.3 Correction des exercices 9. i++) { printf ("Caractère nÆ %d : %c\n". /* compteur */ /* Affichage de chacun des caractères */ for (i=0. } 77 . Faîtes acher chaque caractère du tableau sous la forme "Caractère o n 0 : A".h> #include <stdlib.h" /* Affichage de la chaîne */ printf ("Tableau : %s\n".

h" void saisie (char *chaine.c #include <stdio.h> #include "asciiart. } int main () { char chaine [11].h> #include <stdlib.2 Fonction de saisie (1ère partie) Réaliser votre propre fonction de saisie de chaîne de caractère.3. 78 .chaine). while ((car != 10) && (nb_car < max_car)) { /* Saisie d'un nouveau caractère */ car = getch(). } /* Affichage du résultat */ printf ("Votre saisie : %s\n". return(0). /* 10 : Laisser de la place pour le 0 binaire de fin de chaîne */ saisie (chaine.9. int max_car) { char car = ' '.car).10). char message [] = "Votre saisie : ". /* Attente pour visualisation */ getch (). printf("%c". programme52. /* Ajout du caractère dans le tableau */ chaine [nb_car] = car. printf ("%s\n". message). } chaine [nb_car] = 0. int nb_car = 0. /* Mise à jour de la position dans le tableau */ nb_car ++. fflush(stdout).

. message). } else { /* Ajout du caractère dans le tableau */ chaine [nb_car] = car.h" void saisie (char *chaine. en gérant les pressions sur la touche backspace et le retour chariot nal. /* Mise à jour de la position dans le tableau */ nb_car--. } if (chaine[nb_car-1]==10) nb_car--. char message [] = "Votre saisie : ". /* Mise à jour de la position dans le tableau */ nb_car ++. */ if (car==127) { printf("\b"). while ((car != 10) && (nb_car < max_car)) { car = getch().c #include <stdio. int max_car) { char car = ' '.chaine).9.3 Fonction de saisie (2ère partie) Réaliser votre propre fonction de saisie de chaîne de caractère. programme53.3. else printf("\n")./* Saisie d'un caractère */ /* Si la touche backspace a été préssée . printf ("Votre saisie : %s\n". printf ("%s\n".10). } fflush(stdout).. printf("%c". } 79 . /* 10 : Laisser de la place pour le 0 binaire de fin de chaîne */ saisie (chaine. chaine [nb_car] = 0.h> #include "asciiart. int nb_car = 0. /* Attente pour visualisation */ return(0). /* Affichage du résultat */ getch ().h> #include <stdlib. } int main () { char chaine [11].car).

txt. Prenez le temps de bien comprendre les exemples et n'hésitez pas à poser des questions .1 Bases sur les chiers Un chier représente tout ce qui est enregistré sur votre disque dur ou presque.-). Pour l'assimilation de la notion de structure. l'expérience sera le maître mot. en écriture ou les deux. on va dire tout ce qui porte un nom.Chapitre 10 Fichiers et Structures Dans ce chapitre qui ne comporte pour ainsi dire pas d'exercices. créez à l'aide de votre éditeur de texte favori un chier nommé test.h 80 . de lire ou d'écrire dans des chiers. Pour une étude plus prononcée des chiers. Voici un petit exemple de la lecture du chier test. Il est possible de créer. A noter. nous allons survoler des notions diciles. A noter que l'utilisation des chiers nécessite la bibliothèque unistd. il est nécessaire d'avoir une connaissance minimale du système Linux ou d'Unix. 10. An de ne rien endommager.txt dans lequel vous taperez un texte de louanges pour ce superbe cours (à votre libre ins- piration). que certains chiers par contre peuvent être protégés en lecture.

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 d'ouvrir 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 chaîne de caractère */
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 c'est terminé */
printf ("\n --- Fin ---\n");

}

getchar ();
return (0);

Analysons l'ensemble

81

/* Ouverture du fichier */
fd = open ("test.txt", O_RDONLY);
open permet d'ouvrir un chier, le second paramètre est son mode d'ouverture.
O_RDONLY signie ouverture en lecture seule. La fonction open renvoie un nombre négatif si l'ouLa fonction

verture du chier est un échec et un handle (poignée) sur le chier dans le cas contraire (positif ).

What is an handle ?

Un lien sur quelque chose. On appelle ceci une poignée car comme avec

un sac, vous le prenez par la poignée pour le porter.

/* Test si fichier ouvert */
if (fd < 0)
{
printf ("Impossible d'ouvrir le fichier\n");
getchar ();
return (-fd);
}
La fonction

read permet

de lire des octets (ici transformés en caractères (char)). Elle prend pour

paramètre le handle de chier, la zone de mémoire dans laquelle on va recevoir les données et
la taille maximale que l'on veut lire (attention au dépassement (cf. chapitres précédents)). Elle
renvoie un nombre négatif lorsqu'elle ne peut plus lire d'octets dans le chier, dans le cas contraire,
elle retourne le nombre de caractères lus.

/* Lecture de 80 octets maximum */
nb_car_lus = read (fd, ligne, 80);
if (nb_car_lus > 0)
...
On ache alors les données saisies en ajoutant un 0 de n de chaîne de caractèresce qui explique

char chaine [81].

A ne pas oublier, il faut fermer le chier après l'avoir ouvert !

/* Fermeture du fichier */
close (fd);
/* Ecrire que c'est terminé */
printf ("\n --- Fin ---\n");
getchar ();
return (0);
Très simple non !

82

10.2 Création d'un autre chier
Reprenez l'exemple précédent et modier le avec les éléments qui suivent :

programme55.c
int

fd2;

/* Création d'une copie */
fd2 = open ("copie.txt", O_CREAT | O_RDWR, 0777);
/* Test si fichier bien créer */
if (fd2 < 0)
{
printf ("Impossible de créer 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 données dans le programme précédent.

open, ici nous créons un chier, lors de la création ce chier
0777 (se référer à un cours de Linux pour le détail des
droits). De plus, il nous faut pouvoir écrire dans ce chier, nous ajoutons donc O_RDWR à l'option de
création (O_CREAT) an d'ouvrir le chier en mode Lecture/Ecriture (Reading/Writing).O_CREAT
Une petite modication sur la fonction

possède des droits qui sont donnés par

signie ouverture en lecture si le chier existe ou création dans le cas contraire (s'il n'existe pas).
La fonction

write permet d'écrire des octets sur le chier. Les paramètres 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 désirés, eh oui, personne ne vous a dit que votre chaîne
de départ était vide !

10.3 Structures
Une structure peut s'identier à une che de travail avec des zones à remplir. Ces structures sont
très pratiques pour arranger les données.

83

. Exemple : typedef struct { char nom [40].). int age. La macro typedef signie dénition d'un type. . Solution 2 : typedef struct { /* Définition de la structure */ } nom de la structure. } elt_fiche_nom.3. <nom de la structure> nom de la variable qui aura comme structure cette structure. Solution 1 : struct { /* Définition de la structure */ } nom de la variable qui aura comme forme cette structure.1 Déclaration 2 choix s'orent à nous. elt_fiche_nom une_seconde_fiche . de ce fait là un nouveau type de données (comme int. elt_fiche_nom une_fiche . 84 elt_fiche_nom se comporte comme .10. char prenom [20].. char.

2 Utilisation struct { char nom [40]. ma_fiche. Exemple : programme56.h> int main() { typedef struct { char nom [40]. sprintf (ma_fiche.c #include <stdio.nom. } getchar (). sprintf (ma_fiche.h> #include <stdlib."Eric"). fiche ma_fiche.3. ma_fiche. 85 . char prenom [20]."BERTHOMIER"). ma_fiche.age = 20. int age.age = 30. printf ("%s %s est âgé de %d". une_fiche.age).ma_fiche.sizeof (fiche)). char prenom [20].3. 10. fiche_nom une_seconde_fiche. return (0) . "%s". int age.prenom. "%s".h> #include <fcntl. fiche_nom une_fiche. printf ("Taille de la structure : %d\n".prenom.10.3 Taille d'une structure La taille d'une structure ou d'un type se détermine par la fonction sizeof.nom. } fiche_nom. } fiche.

0777). } printf ("Taille de la structure : %d\n\n".age = 48.age). int i. 86 .h> <fcntl.prenom.nom. int h_fic . char prenom [20].sizeof (fiche))."Eric"). write (h_fic. printf ("Fiche 2 : %s %s est âgé de %d\n". fiche ma_fiche.h> <stdlib.ma_fiche.nom. sprintf (ma_fiche.age = 30. O_CREAT | O_TRUNC | O_WRONLY.age). ma_fiche. char* argv[]) { typedef struct { char nom [40]."BERTHOMIER"). &ma_fiche. &ma_fiche. return (-h_fic).prenom. "%s".nom.prenom. ma_fiche.nom. /* Création du du fichier -> le vider s'il existait */ h_fic = open ("fiche. "%s". ma_fiche.c #include #include #include #include <stdio.10. ma_fiche. write (h_fic.h> int main(int argc.ma_fiche. sizeof (fiche)). ma_fiche. getchar (). ma_fiche. "%s". sprintf (ma_fiche. } fiche. sizeof (fiche))."P'TIT"). unsigned char age.4 Fichiers et Structures programme57. sprintf (ma_fiche.h> <unistd.prenom. "%s". printf ("Fiche 1 : %s %s est âgé de %d\n"."Luc"). sprintf (ma_fiche. /* Test si fichier ouvert */ if (h_fic < 0) { printf ("Impossible d'ouvrir le fichier").dat".

87 . ma_fiche.nom. sprintf (ma_fiche.*/ /* Lecture des éléments du fichier */ /* --------------------------------. ma_fiche. &ma_fiche.ma_fiche.prenom."JRR"). sizeof (fiche)).sprintf (ma_fiche. &ma_fiche. } for (i=0. 10. ma_fiche. i++) { /* Lecture de la fiche */ read (h_fic. O_RDONLY).prenom.age).prenom. printf ("Fiche 3 : %s %s est âgé de %d\n". write (h_fic."Tolkien"). return (-h_fic).nom.*/ /* Ouverture du fichier */ h_fic = open ("fiche. /* Fermeture du fichier */ close (h_fic). } getchar (). ma_fiche.age = 89.nom.dat". i<3.5 Fin et commencement Vous disposez maintenant d'à peu près toutes les connaissances nécessaires pour l'élaboration de petits programmes. getchar ().age). ma_fiche. i. "%s". return 0. } /* Affichage des données lues */ printf ("Fiche nÆ %d : %s %s est âgé de %d\n". /* Test si fichier bien ouvert */ if (h_fic < 0) { printf ("Impossible d'ouvrir le fichier"). ma_fiche. "%s". sizeof (fiche)). /* --------------------------------. /* Fermeture du fichier */ close (h_fic).

txt". if (fd < 0) { printf ("Impossible d'ouvrir le fichier\n"). } 88 . fd2 = 0. getchar (). O_CREAT | O_RDWR.6 Correction de l'exercice L'intégralité du programme de référence pour la Création d'un autre chier ne vous est pas donnée dans le cours. getchar (). return (-fd2). /* Ouverture du fichier */ fd = open ("test. return (-fd). } /* Création du fichier */ fd2 = open ("copie. la voici donc : #include <fcntl.h> int main () { int fd = 0.h> #include <unistd.h> #include <stdio. nb_car_lus = 0. 0777).txt". if (fd2 < 0) { printf ("Impossible d'ouvrir le fichier\n"). char ligne [81].10. O_RDONLY).

/* Ecriture dans le second fichier */ write (fd2.Fin ---\n").ligne). /* Fermeture du fichier */ close (fd). /* Ecrire que c'est terminé */ printf ("\n --. 89 . /* Fermeture du second fichier */ close (fd2). } getchar (). 80).do { /* Lecture de 80 octets maximum */ nb_car_lus = read (fd. return (0). if (nb_car_lus > 0) { /* Fin de chaîne de caractère */ ligne [nb_car_lus] = 0. nb_car_lus). ligne. /* Ecriture de ce qui a été lu */ printf ("%s". } } while (nb_car_lus > 0). ligne.

Curses nous fait le travail en nous proposant un large éventail de fonctions qui nous permettent de gérer l'écran. vitesse d'achage . On obtient donc le principe de fonctionnement suivant : Initialisation de la fenêtre {\tt initscr ()} Modification de la fenêtre Affichage des modifications {\tt refresh ()} Restauration de la fenêtre {\tt endwin ()} initscr () initialise Curses. An d'optimiser au maximum les programmes tous les achages sont buerisés. Il faut savoir que chaque console possède des caractéristiques qui lui sont propres (taille d'écran. Matt Welsh. une documentation très fournie et très complète est disponible sur le Web. Sven van der Meer. Tous ses renseignements sont enregistrés dans une structure nommée WINDOW. 11.  au cours "The Linux Programmer's Guide" de Sven Godt. Scott Burtkett.1 Concepts de base Curses est une bibliothèque qui ore des fonctionnalités de manipulation de l'écran. Pour plus de détails sur ces fonctions.). Un changement ne sera actif que lorsque la commande refresh () est appelée. les changements sont opérés dans l'image mémoire de la fenêtre (WINDOW). Inc. de ce fait il est très dicile de réaliser des applications portables (qui vont d'un système à un autre). il renseigne le type de terminal et les caractéristiques qui lui sont 90 ... En attendant que cette commande soit appelée. Le principe de fonctionnement de Curses est un tableau de nLignes et nColonnes contenant d'une part tous les caractères de fenêtre de traitement mais aussi toutes les carcactéristiques de ces caractères.Chapitre 11 Curses Ce cours est dédié à un joyeux luron nommé "Bernard" et mon oeil ! Ce cours a été réalisé grâce  au livre Programming with Curses de John Strang Editions O'Reilly & Associates.

11. Lors de la compilation. ce positionnement ne sera eectif qu'après l'appel de la fonction refresh.x) permet de positionner le curseur sur l'écran. reportez vous aux cours précédents si vous avez un trou de mémoire &-). Cette commande est facultative lors- qu'une demande de saisie est eectuée (scanw par exemple). Ceci permet de mettre n à toutes les modications opérées par Curses lors de son fonctionnement. nous n'avons rien vu et surtout rien fait. Tout ceci est bien beau mais pour l'instant. Bon maintenant passons en revue quelques fonctions 11.2. endwin () restaure le terminal dans son état initial. 91 . Le coin heut gauche de la fenêtre possède les coordonnées (0.1 Localisation du curseur move (y.2 Achage de caractères addch (char ch) ache un caractère à la position courante du curseur.3 Eacement de la fenêtre clear () eace la fenêtre en la remplissant de blancs.associées. Bien entendu.2. ajoutez -lcurses Je ne détaille pas plus. 1. Certains caractères spé- ciaux donnent les résultats suivants : \t \r \b \n Tabulation 8 caractères blancs Retour-Chariot Déplace le curseur sur la prochaine ligne Backspace Ecrit un blanc en arrière Eace le reste de la ligne et déplace le curseur au début de la prochaine ligne Beaucoup d'autres caractères permettent aussi l'achage de caractères spéciaux semi-graphique.h> 2. Avant de commencer à pianoter sur son joli clavier. Ajoutez #include <curses.2. il est nécessaire de savoir comment inclure la bibliothèque curses.0).2 Quelques fonctions d'achage de Curses 11. refresh () ache les modications opérées dans l'écran. nous en verrons un peu plus tard. 11.

Il est important de faire attention à ce que la chaîne ne dépasse pas la n de la ligne. '!'. win sera toujours stdscr traduisez standard screen. Exemple : !=======================! !box (stdscr.5 Achage formaté d'une chaîne de caractères printw (.11.. 11. nous n'utiliserons pas les possibilités de fenêtres multiples.2....2. à vous de voir et de tester ..2. de ce fait..4 Achage d'une chaîne de caractères addstr (char* ch) ache une chaîne de caractères.! !=======================! 11. Dans le cadre de ce cours. '='). vert dénit le caractère qui servira de bord vertical. horz dénit le caractère qui servira de bord horizontal.. Cette recommendation s'applique aussi aux fonctions de saisie que nous verrons par la suite. boîte de saisie .. boîte de dialogue.3 1reutilisation Voici un programme exemple qui résume ce que l'on vient de voir . enn.chaine). 92 ..7 Les anciennes fonctions d'achage Les anciennes fonctions d'achage sont tout simplement proscrites. 11.6 Boîtes Tout est plus beau dans une boîte.) est l'adaptation de printf pour l'achage formaté de chaîne de caractères. 11.2. char horz). char vert. Exemple : printw ("%s". pour se faire Curses nous ore la fonction box (WINDOW* win.

// Positionnement en 3. '|'.programme58.h> #include <curses.2).h> int main () { initscr (). // Application des changements getch ().2 addstr ("Quel superbe bibliothèque !"). pour que l'on puisse voir ! endwin (). // Initialisation de Curses box (stdscr. // Attente. // Dessin d'une boîte move (3.o -lcurses 93 . '-'). Compilation : gcc -c -Wall programme58.c gcc -o programme58 programme58. // Fin de Curses } return (0).c #include <stdio. // Affichage d'un message refresh ().

c #include <stdio. // Affichage des modifications getch ().2). // Initialisation de Curses box (stdscr.2). car).2 printw ("Caractère : %c". // Fin de Curses } return (0).h> int main () { char car. programme59. 94 . '-').4. // Positionnement en 4. // Positionnement en 3.h> #include <curses. // Saisie du caractère move (4. // Dessin d'une boîte move (3.4 Quelques fonctions de saisie de Curses 11.11. '|'. // Affiche le caractère saisi refresh ().1 Saisie d'un caractère getch permet de saisir un caractère.2 addstr ("Votre caractère : "). initscr (). // Demande la saisie d'un caractère car = getch (). // Attente pour voir le résultat endwin ().

// Fin de Curses } return (0). initscr (). 95 . programme60. // Affiche le caractère saisi refresh ().h> #include <curses. // Saisie de la chaîne move (4. chaine).2 printw ("Chaine : %s".2).4. // Dessin d'une boîte move (3. '-').2 addstr ("Votre chaîne de caractère : ").2). // Affichage des modifications getch (). '|'.2 Saisie d'une chaîne de caractère getstr (char* str) permet de saisir une chaîne de caractères. // Demande la saisie d'un caractère getstr (chaine). cette fonction demeure dangereuse (risque de dépassement de tableau).11. Au vue que l'on ne connaît jamais la taille de ce qui va être saisi par l'utilisateur.h> int main () { char chaine [256]. // Positionnement en 4. // Attente pour voir le résultat endwin (). // Initialisation de Curses box (stdscr.c #include <stdio. // Positionnement en 3.

// Attente pour voir le résultat endwin (). // Initialisation de Curses box (stdscr.&nbre). programme61.c #include <stdio.h> #include <curses. '-'). // Demande la saisie d'un caractère scanw ("%d".) est l'équivalent de scanf pour Curses.. // Affiche le nombre saisi refresh (). // Saisie du nombre move (4. // Positionnement en 3.2 printw ("Nombre : %d". // Affichage des modifications getch (). 96 .h> int main () { int nbre = 0. initscr (). // Positionnement en 4.2). // Dessin d'une boîte move (3.2)..11. nbre).4.3 Saisie formatée scanw (. '|'. // Fin de Curses } return (0).2 addstr ("Votre nombre : ").

5 Achage de caractères spéciaux Voici quelques caractères spéciaux que permet d'acher curses. tl ts tt ts tr ls rs lt rt ls rs bl bs bt bs br Caractère Position Valeur tl top left ACS_ULCORNER ts top side ACS_HLINE tr top right ACS_URCORNER ACS_VLINE ls left side rs right side ACS_VLINE bl bottom left ACS_LLCORNER bs bottom side ACS_HLINE br bottom right ACS_LRCORNER rt right tee ACS_RTEE lt left tee ACS_LTEE tt top tee ACS_TTEE bt bottom tee ACS_BTEE 97 .11.

6. 11. // Initialisation de Curses box (stdscr. de . fg.h> #include <curses. Le nombre de paires de couleurs maximal est COLOR_PAIRS . Cette fonction doit être appelée avant l'utilisation couleurs. ACS_HLINE).6. bg) permet de dénir la paire de couleur 98 pair sauf 0.  init_pair (pair. // Fin de Curses } return (0).1. // Attente pour voir le résultat endwin ().Exemple : programme62. une couleur de fond et une couleur de premier plan.2 Fonctions liées au couleurs :    has_colors () renvoie TRUE si le terminal supporte les couleurs. // Dessin d'une boîte refresh ().h> int main () { initscr (). // Affichage des modifications getch ().6 Les couleurs Les couleurs se dénissent par paires. 11. start_color () initialise les couleurs.c #include <stdio. la paire numéro 0 étant réservée pour le blanc sur fond noir). can_change_color () renvoie TRUE si le terminal permet de redénir les couleurs.1 Dénomination des couleurs : Couleur Dénition Noir COLOR_BLACK Rouge COLOR_RED Vert COLOR_GREEN Jaune COLOR_YELLOW Bleu COLOR_BLUE Magenta COLOR_MAGENTA Cyan COLOR_CYAN Blanc COLOR_WHITE 11. ACS_VLINE.

move (4. // Dessin d'une boîte move (3. ACS_HLINE). wattrset (win. box (stdscr. addstr ("Coucou c'est moi").e. // Fin de Curses } return (0). COLOR_PAIRS). // Affichage des modifications getch ().c #include <stdio. COLOR_PAIR(1)).h> #include <ncurses. printw ("Nombre de paires : %d". stdscr. COLOR_PAIR (pair)) permet d'utiliser la paire de couleur pair comme couleur d'écriture.3). ce sera toujours la fenêtre standard i. refresh (). COLOR_BLUE. COLOR_WHITE). // Attente pour voir le résultat endwin ().h> int main () { initscr (). // Initialisation de Curses start_color (). 99 . addstr ("Coucou c'est moi"). programme63. wattrset (stdscr.3). dans notre cas. win est la fenêtre concernée. init_pair (1. move (5. ACS_VLINE.3).

dessine le jeu dans son intégralité (toutes les allumettes). Qui commence (0 pour le joueur et 1 pour l'ordinateur). Pour se faire. sans utiliser Curses. tour à tour. essayer de réaliser l'exercice sans faire d'achage graphique. 12. Pour se faire. Puis. une prise maximale est désignée par le joueur. Le nombre maximal d'allumettes que l'on peut retirer. écrivez une fonction qui dessine une allumette et une qui. l'autre le vainqueur. La partie se termine lorsqu'il n y a plus d'allumettes sur la table. 3.Chapitre 12 Le Jeu des Allumettes Adaptée du livre de Jacques Deconchat : "102 Programmes Pour MO6. chaque parti donne le nombre d'allumettes qu'il prend. Le nombre d'allumettes disposées entre les deux joueur (de 10 à 60). l'ordinateur et vous. i. La personne ayant tirée la dernière allumette est le perdant. 2. on demande : 1. 100 . adaptez votre programme.2 Ce qu'il faut faire Lisez l'intégralité de l'énoncé !-). Dans un premier temps. Dans un second temps. Le but du jeu est de ne pas retirer la dernière allumette. TO8 et TO9+" 12.1 Enoncé de l'exercice Un certain nombre d'allumettes est disposé entre les deux partis. utilisant le dessin d'une allumette. En début de partie.e.

floor donne l'arrondi inférieur d'un nombre. La fonction retourne en sortie le nombre d'allumettes prises par l'ordinateur.h> <math. Exemple : prise = jeu_ordi (10.1.12. Nb_allum est le nombre d'allumettes sur la table (au moment du coup à jouer). t = ((float) (nb_allum-s)) / (prise_max + 1). float t = 0. int prise_max) { int prise = 0.3 Aide L'ordinateur répond grâce à la fonction décrite ci-dessous : int jeu_ordi (int nb_allum.h> oblige à linker avec -lm : gcc -o monprog monprog. while (t != floor (t)) { s--. s = prise_max + 1.3) . Une allumette sera dessinée de la façon suivante : 0 | |  La fonction floor nécessite -lm <math. } La fonction return (prise). int s = 0. Prise_max est le nombre maximum d'allumettes autorisé lors d'une prise. } prise = s . if (prise == 0) prise = 1.s)) / (prise_max + 1). t = ((float) (nb_allum .o la bibliothèque  L'utilisation de la bibliothèque 101 .

} return (prise). /*qui joue? 0=Nous --. } prise = s . s = prise_max + 1. Ils se veulent simplement clairs pour les débutants que vous êtes. programme64. /*nbre d'allumettes maxi au départ*/ int nb_allu_max=0. /*nbre d'allumettes prises par le joueur*/ int nb_allu_rest=0.s)) / (prise_max + 1). /*nbre d'allumettes restantes*/ printf ("Nombre d'allumettes disposées entre les deux joueurs (entre 10 et 60) : ").h> #include <stdlib. int s = 0. float t = 0. /*nbre d'allumettes maxi que l'on peut tirer au maxi*/ int qui=0. int prise_max) { int prise = 0.h> int jeu_ordi (int nb_allum. if (prise == 0) prise = 1. int main () { int nb_max_d=0.h> #include <math.12.&nb_max_d).1. 102 . while (t != floor (t)) { s--. t = ((float) (nb_allum .1=PC*/ int prise=0. t = ((float) (nb_allum-s)) / (prise_max + 1).c #include <stdio. scanf ("%d".4 Corrections de l'exercice sans Curses Ces programmes ne sont pas optimisés ni très beaux.

nb_allu_rest).prise. } qui=!qui. nb_allu_max). printf ("\nPrise de l'ordi : %d\n".do { printf ("\nNombre maximal d'allumettes que l'on peut retirer : ").&qui). if (nb_allu_max >= nb_max_d) printf ("Erreur !"). if ((prise > nb_allu_rest) || (prise > nb_allu_max)) { printf ("Erreur !\n"). } while ((qui != 0) && (qui != 1)). do { printf ("\nNombre d'allumettes restantes : %d". scanf ("%d". /* On répète la demande de prise tant que le nombre donné n'est pas correct */ do { printf ("\nQuel joueur commence? 0--> Joueur . } while (nb_allu_max >= nb_max_d). } while (nb_allu_rest >0).&prise). scanf ("%d". } } while ((prise > nb_allu_rest) || (prise > nb_allu_max)). 1--> Ordinateur : "). if (qui==0) { do { printf ("\nCombien d'allumettes souhaitez-vous piocher ? "). if ((qui != 0) && (qui != 1)) printf ("\nErreur").prise). 103 .&nb_allu_max). /* On répète la demande de prise tant que le nombre donné n'est pas correct */ } else { prise = jeu_ordi (nb_allu_rest . scanf ("%d". nb_allu_rest = nb_max_d. nb_allu_rest= nb_allu_rest .

104 .if (qui == 0) /* C'est à nous de jouer */ printf ("\nVous avez gagné!\n"). } return (0). else printf ("\nVous avez perdu!\n").

COLOR_PAIR (0)). s = prise_max + 1. } prise = s . emplacement).1. } return (prise).c #include #include #include #include <stdio. addch (ACS_VLINE).12. void dessine_allumette (int emplacement) { move (15. emplacement). float t = 0.s)) / (prise_max + 1). int prise_max) { int prise = 0. t = ((float) (nb_allum-s)) / (prise_max + 1). COLOR_PAIR (1)). 105 . int s = 0.5 Corrections de l'exercice avec Curses programme65. while (t != floor (t)) { s--. addch (ACS_VLINE). if (prise == 0) prise = 1. t = ((float) (nb_allum . } move (17. addch ('*').h> <math. wattrset (stdscr.h> int jeu_ordi (int nb_allum. // On repasse en couleur standard wattrset (stdscr.h> <curses.h> <stdlib. emplacement). move (16.

/*qui joue? 0=Nous --. do { move (1.1). // Définition de la couleur rouge sur fond noir * de l'allumette init_pair (1. for (allu = 0. /*nbre d'allumettes maxi au départ*/ int nb_allu_max=0. allu < nb_allumettes. int main () { int nb_max_d=0. scanw ("%d". box (stdscr.void dessine_jeu (int nb_allumettes) { int allu = 0. /*nbre d'allumettes restantes*/ initscr (). } } while ((nb_max_d < 10) || (nb_max_d > 60)). addstr ("Erreur !"). } } refresh (). refresh ().1=PC*/ int prise=0. /* On répète la demande du nombre d'allumettes */ /* tant que le nombre donné n'est pas correct */ 106 . allu ++) { dessine_allumette (5+allu). start_color (). ACS_HLINE). /*nbre d'allumettes prises par le joueur*/ int nb_allu_rest=0. ACS_VLINE. addstr ("Nombre d'allumettes disposées entre les deux joueurs (entre 10 et 60) : "). COLOR_BLACK). if ((nb_max_d > 60) || (nb_max_d < 10)) { move (2.&nb_max_d). COLOR_RED. /*nbre d'allumettes maxi que l'on peut tirer au maxi*/ int qui=0.1).

addstr ("Erreur").do { move (2. if (nb_allu_max >= nb_max_d) { move (3. do { // Ce n'est pas beau mais c'est efficace clear (). box (stdscr. ACS_HLINE). addstr ("Nombre maximal d'allumettes que l'on peut retirer : "). addstr ("Erreur !"). if ((qui != 0) && (qui != 1)) { move (4. refresh (). ACS_VLINE. } } while (nb_allu_max >= nb_max_d). nb_allu_rest = nb_max_d. addstr ("Quel joueur commence? 0--> Joueur .1).1). /* On répète la demande de prise */ /* tant que le nombre donné n'est pas correct */ do { move (3.1). scanw ("%d". 107 . dessine_jeu (nb_allu_rest).&qui). scanw ("%d". refresh (). 1--> Ordinateur : "). } } while ((qui != 0) && (qui != 1)).&nb_allu_max).1).

} return (0). nb_allu_max). } while (nb_allu_rest >0). addstr ("Combien d'allumettes souhaitez-vous piocher ? "). refresh (). endwin (). addstr ("Erreur !").&prise). move (5.prise.2). refresh ().if (qui==0) { do { move (2.5). /* On répète la demande de prise */ /* tant que le nombre donné n'est pas correct */ } else prise = jeu_ordi (nb_allu_rest . qui=!qui. scanw ("%d". getchar (). 108 .2). if (qui == 0) addstr ("Vous avez gagné !"). } } while ((prise > nb_allu_rest) || (prise > nb_allu_max)). nb_allu_rest= nb_allu_rest . else addstr ("Vous avez perdu !"). if ((prise > nb_allu_rest) || (prise > nb_allu_max)) { move (3.

chaque cellule peut naître. Le jeu de la vie est une application particulière cellulaires.  Une cellule ayant au moins 4 cellules voisines vivantes meurt d'étouement à la génération suivante. et en utilisant la librairie ncurses pour l'achage. Chaque case est occupée par une cellule qui peut être vivante ou morte. actuelle qui doit être pris en compte pour l'établissesuivante. Les cellules qui devront mourir à la génération suivante sont grisées : 109 . Très prolique en matière de jeux mathématiques. jeu de la vie de John 13. À chaque génération.Chapitre 13 Le Jeu de la Vie Le présent exercice consiste à implémenter une version sur damier torique du Conway. En premier lieu. Notons que c'est l'ensemble de la génération ment de l'état des cellules à la génération Voici un exemple de gure sur un petit damier.  Sur une case vide ayant exactement 3 voisins vivants. visant à modéliser d'une façon simple d'automates l'évolution d'organismes vivants. notons que sur un damier inni. Les règles données par J. mourir. 13. Conway sont les suivante :  Une cellule ayant exactement 2 ou 3 voisins vivants survit à la génération suivante. il décrivit en 1970 le jeu de la vie. en C.  Une cellule ayant au plus une cellule voisine vivante meurt d'isolement à la génération suivante. Les règles qui permettent de passer d'une génération à l'autre sont précises et ont été choisies avec soin pour que l'évolution des organismes soit intéressante et imprévisible. une cellule naîtra à la génération suivante.1 Historique John Conway était un mathématicien de l'Université de Cambridge. ou rester dans son état.2 Règles du jeu Le jeu de la vie évolue normalement sur un damier inni. chaque case a exactement 8 voisins.

Générations : 1 2 3 4 5 13.COLOR_BLACK).COLOR_WHITE. } Le bout de code précédent vérie que le terminal supporte l'utilisation de couleurs.COLOR_BLUE). initialise leur utilisation et déni les couleurs 1 et 3 comme étant du blanc sur bleu et rouge sur noir..  considérer l'abscence de voisin (au bord du tableau) comme une cellule vivante . Mais on ne peut pas représenter un tableau inni. nous utiliserons la librairie ncurses. et on dénit les couleurs ainsi : if (has_colors()) { start_color(). 13. Le voisinage des points est donc le suivant : 13.COLOR_RED.  jouer sur un damier torique. respecte mieux le jeu initial. On la prépare à l'utilisation des couleurs.3 Damier torique Représenter le damier par un tableau est la solution la plus simple.4 Implémentation du jeu Pour réaliser l'achage de notre jeu de la vie. On doit considérer que les bords droit et gauche du tableau sont reliés entre eux.4. ainsi que les bords supérieurs et inférieurs. init_pair(1. 110 . Plusieurs choix sont alors possibles :  considérer l'absence de voisin (au bord du tableau) comme une cellule morte . La troisième solution. init_pair(3.1 Rappels utiles sur ncurses On initialise la libraire proprement avec la fonction initscr() .

2 Algorithme du jeu de la vie On pourra reprendre l'algorithme suivant.COLOR_PAIR(1)).On utilise les couleurs et on ache un caractère à un endroit donné ainsi : /* Sélection du blanc sur fond bleu */ wattrset(stdscr. précédente) */ addch(' '). on quitte proprement la librairie par un appel à la fonction endwin() 13. qui décrit 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. un appel à la fonction refresh() .y) // met à jour le damier pour la génération suivante procedure prochaine_generation() // Affiche le damier procedure affiche(monde) procedure principale : init_curses() damier_hasard() répéter : affiche_damier() prochaine_generation() saisir un caractère au clavier jusqu'à ce que le caractère saisi soit 'q' fin_curses 111 . /* déplacement de la position courant ligne 10. /* Affichage d'un espace (donc un carré bleu avec la déf.y) du damier (utilisé // par la procédure prochaine_generation) fonction nombre_voisins(x. permet d'obtenir l'af- chage eectif.4.14). Enn. Les commandes d'achages terminées. colonne 14 */ move(10.

Même si il est généralement conseillé d'éviter de déclarer des variables globales.  le calcul de la génération suivante .4 Dicultés Si vous vous sentez susament en forme pour écrire le programme. } } n-=monde[x][y].ofx<=1. Pour calculer la génération suivante. int n=0.ofy. while (x0<0) x0+=TAILLEX.13.4.y) // monde est le damier // TAILLEX et TAILLEY les dimensions du damier int nombre_voisins(int x. ne vous en privez pas. Vous pourrez regarder cette section uniquement en cas de problème. Ainsi. on pourra dans cet exemple simple déclarer un tableau monde global. for (ofx=-1. on doit utiliser un tableau auxiliaire : 112 a%b est le reste de la . On pourra choisir de mettre la valeur 0 dans une case si la cellule est  morte  et la valeur 1 dans le cas contraire.ofy++) { x0=x+ofx%TAILLEX.3 Structures de données utilisées On pourra représenter le damier par un tableau de ainsi : char.y0. La première dicultée peut être traitée ainsi : // Renvoie le nombre de voisins vivants de la cellule (x. int x0. return n. while (y0<0) y0+=TAILLEY.4.ofy<=1. n+=monde[x0][y0]. } Remarque : En C l'opérateur division entière de a par b. % correspond à l'opération modulo. y0=y+ofy%TAILLEY. 13. Les principales dicultés sont :  le comptage du nombre de voisins sur damier torique .ofx++) { for (ofy=-1. Un damier de taille 30 sera donc déclaré char monde[30][30] .int y) { int ofx.

5.y<TAILLEY. } } } // Recopie du tableau auxiliaire dans le tableau courant for(x=0.x<TAILLEX.y++) { monde[x][y]=monde_aux[x][y].TRUE) de ncurses permet d'utiliser la fonction getch() de ERR si aucune touche n'a été tapée et le façon non-bloquante. char monde_aux[TAILLEX][TAILLEY].y. default: // la cellule meurt dans les autres cas monde_aux[x][y]=(char)0.5 Possibilités d'amélioration Si vous nissez rapidement.// Met à jour le damier avec la génération suivante // monde est le damier // TAILLEX et TAILLEY les dimensions du damier void generation_suivante(void) { int x. sans qu'il ait à frapper une touche. 13. vous pouvez améliorer le programme.x++) { for(y=0. } } } 13.y<TAILLEY.y++) { switch(nombre_voisins(x. vous pouvez permettre à l'utilisateur de voir évoluer le jeu de la vie. case 3: // la cellule naît monde_aux[x][y]=(char)1. tout en lui laissant les possibilités suivantes (par exemple) : 113 .y)) { case 2: // la cellule reste dans le même état monde_aux[x][y]=monde[x][y].x<TAILLEX. // Calcul de la nouvelle génération dans le tableau auxiliaire for(x=0. break. break. En combinant ces deux fonctions.x++) { for(y=0. break.1 Contrôle interactif L'appel à la fonction nodelay(stdscr. Un appel à la fonction renverra caractère entré dans le cas contraire.

En partant d'un tableau aléatoire. taper 'q' pour sortir . an qu'il choisisse l'état initial du damier.5.  formes périodiques de grande période.6 Exemples obtenus On peut voir sur les gures suivantes des congurations obtenues : Conguration aléatoire de départ.5.3 Chargement de formes prédénies Malgré son apparente simplicité. 13.  taper 'w' ou 'x' pour accélérer ou ralentir son déroulement. 13. 114 . 13.  formes stables. La possibilité d'initialiser le damier avec une forme particulière est donc intéressante pour pouvoir observer ces phénomènes.2 Achage des coordonnées Vous pouvez acher les coordonnées des cases sur les bords du damier.  taper 'r' pour réinitialiser le jeu . le jeu de la vie recèle de nombreuses surprises.. Certaines personnes ont répertoriées des centaines des formes aux propriétés particulières :  générateurs de planeurs (les lanceurs).. On pourra donc permettre à l'utilisateur de lire l'état des cases dans un chier.. on peut dicilement les observer même si l'apparition d'un planeur (voir l'exemple du début) ou de formes périodiques (à la n) ne sont pas rares..  portes logiques.

... 115 ... planeur. Apparition d'un Conguration nale de motifs de période 1 ou 2..Formations d'amalgames de cellules...qui se balade..

i++) { } } /* procédure vidant le buffer clavier */ void vide_buffer(void) { while (getch()!=ERR). } /* Affichage des coordonnées sur le bord inférieur */ for (i=0.k<strlen(str).j. } /* Affichage du damier */ void affiche(void) { int i.i<32000.j<t. printw("%03d".COLOR_BLACK). init_pair(2. } 116 . usecolors=1. if (monde[i][j]) { if (usecolors) { wattrset(stdscr. for (j=0. if (has_colors()) { start_color().7 Exemple de corrigé Le programmme suivant ache le damier. } /* Initialisation de ncurses et définition des couleurs */ void init_curses(void) { initscr().COLOR_PAIR(0)). } } else { addch(' ').k.h> #define TAILLEX 75 #define TAILLEY 50 char monde[TAILLEX][TAILLEY].j++) for(i=0. for (k=0. addch(' ').j++) { for (i=0. } } } /* Affichage des coordonnées sur le bord droit */ if (usecolors) wattrset(stdscr. /* Procédure de temporisation. w et x pour réinitialiser le damier. int usecolors=0.h> #include <ncurses. q. accélérer ou ralentir le jeu. for (j=0. } } if (usecolors) wattrset(stdscr.TAILLEX+1). les coordonnées des cases..i<TAILLEX. init_pair(3.COLOR_BLUE).COLOR_PAIR(3)). char str[5]. } else { addch('@').COLOR_WHITE. } } /* Terminaison propre de ncurses */ void fin_curses(void) { endwin(). refresh(). addch(str[strlen(str)-1-k]).COLOR_PAIR(0)). et permet à l'utilisateur d'utiliser les touches r.13.j<TAILLEY.i++) { move(j.h> #include <stdlib."%d".. quitter.j<TAILLEY.i<TAILLEX. programme66.j%100). for (j=0.i++) { sprintf(str.j++) { move(j.i.c #include <stdio.i). init_pair(1.i).COLOR_PAIR(1)). wattrset(stdscr.k++) { move(TAILLEY+k+1.COLOR_RED.COLOR_WHITE.i).COLOR_GREEN). */ void temporise (int t) { int j.

} /* Rempli au hasard le damier à perc % de cellules vides */ void damier_hasard(int perc) { int i.x++) { for(y=0. for (ofx=-1.y<TAILLEY. int n=0. // la cellule meurt // dans les autres cas default: monde_aux[x][y]=(char)0. for (j=0. } } } 117 .x<TAILLEX.i<TAILLEX.i++) { if (rand()%101 > perc) monde[i][j]=1. break.y.// Renvoie le nombre de voisins // vivants de la cellule (x.ofy<=1. return n. perc=perc%101.ofx++) { for (ofy=-1. while (y0<0) y0+=TAILLEY.ofx<=1. char monde_aux[TAILLEX][TAILLEY].j<TAILLEY. break.ofy++) { x0=x+ofx%TAILLEX. int x0.x++) { for(y=0. } } n-=monde[x][y].y<TAILLEY.x<TAILLEX.int y) { int ofx. y0=y+ofy%TAILLEY. else monde[i][j]=0. n+=monde[x0][y0]. // la cellule naît case 3: monde_aux[x][y]=(char)1. break.y++) { monde[x][y]=monde_aux[x][y]. // Calcul de la nouvelle génération // dans le tableau auxiliaire for(x=0.j++) for (i=0.y)) { // la cellule reste // dans le même état case 2: monde_aux[x][y]=monde[x][y].j.ofy.y++) { switch(nombre_voisins(x. } } } // Recopie du tableau auxiliaire // dans le tableau courant for(x=0. while (x0<0) x0+=TAILLEX. } } /* Calcule la génération suivante */ void generation_suivante(void) { int x.y) // monde est le damier // TAILLEX et TAILLEY les dimensions // du damier int nombre_voisins(int x.y0.

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

Annexe A Code Ascii 119 .

120 .

121 .

avec ou sans echo.c 122 .c #include "asciiart. Il ne tient qu'à vous de l'améliorer. pompeusement appelée ASCIIART. mais vous pouvez bien sûr Les fonctions sont déclarées dans le chier (#include "asciiart. Sachez cependant qu'il existe de le célèbre ncurses. Pour compiler l'exemple suivant : test_bibli.Annexe B Bibliothèque Asciiart B. dont très bonnes bibliothèques faisant entre autres tout ceci. comme l'utilisation complète dépasse l'objet de ce cours. } vous devez entrer : gcc -c test_bibli.1 Introduction An de pouvoir réaliser des exercices plus amusants et colorés. Cette bibliothèque permet pour l'instant de modier les couleurs du terminal et de saisir des caractères à la volée. Celle-ci est regarder le source. return(0). nous avons regroupé un ensemble de fonctions dans une bibliothèque.o). Vous devez donc l'inclure dans vos sources test_asciiart() permet de tester les diérentes foncfournie au format objet (.2 Utilisation de la bibliothèque asciiart. La fonction tions de la bibliothèque. B.h.h" int main(void) { test_asciiart().h").

// Exemple d'utilisation : //# include "asciiart. Avec echo char getche(void). //return 0..) void textblink(int val).. Sans echo char getch(void).o et enn exécuter : .h" //int main(void) //{ //test_asciiart()./test_bibli B. // modifie la couleur d'affichage void textcolor(int i). // réinitialisation de la console void textreset(void).o asciiart.h #ifndef ASCII_ART_H #define ASCII_ART_H /* Cet ensemble de fonctions permet d'utiliser la saisie de caractères à la console en mode non bufferisé (ici appelé mode immédiat) Il permet d'accéder à différents paramètres du terminal comme la couleur */ // Saisit un caractère au vol. // procédure permettant de tester les différentes focntionnalités void test_asciiart(void).3 Fichier d'en-tête À l'heure actuelle. //} #endif 123 .puis : gcc -o test_bibli test_bibli. le chier d'en-tête est le suivant : asciiart. // 0<=i<=7 // passage (1) ou sotie (0) mode clignotement (expérimental. // Saisit un caractère au vol.