Jusqu'ici, nous n'avions qu'un seul fichier source dans notre projet. Ce fichier source, je vous avais demandé de l'appeler main.c
Plusieurs fichiers par projet
Dans la pratique, vos programmes ne seront pas tous écrits dans ce même fichier main.c. Bien sûr, c'est
possible de le faire, mais ce n'est jamais très pratique de se balader dans un fichier de 10000 lignes (enfin personnellement je trouve

).
C'est pour cela qu'en général on crée plusieurs fichiers par projet.
Euh c'est quoi un projet ?
Non, vous avez pas déjà oublié ?

Bon allez je vous le réexplique, parce qu'il est important qu'on soit bien d'accord entre nous là
Un projet, c'est
l'ensemble des fichiers source de votre programme.
Pour le moment, nos projets n'étaient composés que d'un fichier source. Regardez dans votre IDE (généralement c'est sur la gauche) :
Comme vous pouvez le voir sur cette capture d'écran à gauche, ce projet n'était composé que d'un fichier main.c.
Laissez-moi maintenant vous montrer un vrai projet que vous ferez un peu plus loin dans le cours (un jeu de Sokoban) :
Comme vous le voyez, il y a plusieurs fichiers. Un vrai projet ressemblera à ça : vous verrez plusieurs fichiers dans la colonne de gauche.
Vous reconnaissez dans la liste le fichier main.c : c'est celui qui contient la fonction main. En général dans mes programmes, je ne mets que le main dans main.c (mais ce n'est pas du tout une obligation, chacun s'organise comme il veut !)
Mais pourquoi avoir créé plusieurs fichiers ? Et comment je sais combien de fichiers je dois créer pour mon projet ?
Ca c'est vous qui choisissez

En général, on regroupe dans un même fichier des fonctions par thème. Ainsi, dans le fichier editeur.c j'ai regroupé toutes les fonctions concernant l'éditeur de niveau, dans le fichier jeu.c j'ai regroupé toutes les fonctions concernant le jeu lui-même, etc.
Fichiers .h et .c
Comme vous le voyez, il y a 2 types de fichiers différents sur la capture d'écran que je vous ai montrée :
- Les .h : appelés fichiers headers. Ces fichiers contiennent les prototypes des fonctions.
- Les .c : les fichiers sources. Ces fichiers contiennent les fonctions elles-mêmes.
En général, on met donc rarement les prototypes dans les fichiers .c comme on l'a fait tout à l'heure dans le main.c (sauf si votre programme est tout petit).
Pour chaque fichier .c, il y a son équivalent .h qui contient les prototypes des fonctions.
Rejetez un oeil à ma capture d'écran :
- Il y a editeur.c (le code des fonctions) et editeur.h (les prototypes des fonctions)
- Il y a jeu.c et jeu.h
- etc.
Mais comment faire pour que l'ordinateur sache que les prototypes sont dans un autre fichier que le .c ?
Il faut
inclure le fichier .h grâce à une directive de préprocesseur.
Attention, préparez-vous à comprendre plein de trucs tout d'un coup
Comment inclure un fichier header ?
Vous savez le faire, vous l'avez déjà fait !
Regardez par exemple le début de mon fichier jeu.c :
Code : C | #include <stdlib.h>
#include <stdio.h>
#include "jeu.h"
void jouer(SDL_Surface* ecran)
{
// ...
|
L'inclusion se fait grâce à la directive de préprocesseur #include que vous connaissez bien maintenant

Regardez les premières lignes du code source ci-dessus :
Code : C | #include <stdlib.h>
#include <stdio.h>
#include "jeu.h" // On inclut jeu.h
|
On inclut 3 fichiers .h : stdio, stdlib et jeu.
Notez une différence : les fichiers que vous avez créés et placés dans le répertoire de votre projet doivent être inclus avec des guillemets ("jeu.h") tandis que les fichiers correspondants aux bibliothèques (qui sont installés, eux, dans le répertoire de votre IDE généralement) sont inclus entre chevrons (<stdio.h>).
Vous utiliserez donc :
- Les chevrons < > pour inclure un fichier se trouvant dans le répertoire "include" de votre IDE
- Les guillemets " " pour inclure un fichier se trouvant dans le répertoire de votre projet (à côté des .c généralement
)
La commande #include demande d'insérer le contenu du fichier dans le .c. C'est donc une commande qui dit "Insère ici le fichier jeu.h" par exemple.
Et dans le fichier jeu.h que trouve-t-on ?
On trouve juste les prototypes des fonctions du fichier jeu.c !
Code : C 1
2
3
4
5
6
7
8
9
10
11
12 | /*
jeu.h
-----
Par mateo21, pour Le Site du Zér0 (www.siteduzero.com)
Rôle : prototypes des fonctions du jeu.
*/
void jouer(SDL_Surface* ecran);
void deplacerJoueur(int carte[][NB_BLOCS_HAUTEUR], SDL_Rect *pos, int direction);
void deplacerCaisse(int *premiereCase, int *secondeCase);
|
Voilà comment fonctionne un vrai projet
Quel intérêt de mettre les prototypes dans des fichiers .h ?
La raison est en fait assez simple. Quand dans votre code vous faites
appel à une fonction, votre ordinateur doit déjà la connaître, savoir combien de paramètres elle prend etc. C'est à ça que sert un prototype : c'est le mode d'emploi de la fonction pour l'ordinateur.
Tout est une question d'ordre : si vous mettez vos prototypes dans des .h (headers) inclus
en haut des fichiers .c, votre ordinateur connaîtra le mode d'emploi de
toutes vos fonctions dès le début de la lecture du fichier.
En faisant cela, vous n'aurez ainsi pas à vous soucier de l'ordre dans lesquelles les fonctions se trouvent dans vos fichiers .c
Si vous faites un petit programme maintenant contenant 2-3 fonctions, vous vous rendrez compte que les prototypes semblent facultatifs (ça marche sans). Mais ça ne durera pas longtemps ! Dès que vous aurez un peu plus de fonctions, si vous ne mettez pas vos prototypes de fonctions dans des .h la compilation plantera lamentablement
Lorsque vous appelez une fonction située dans fonctions.c depuis le fichier main.c, vous aurez besoin d'inclure les prototypes de fonctions.c dans main.c. Il faudra donc mettre un #include "fonctions.h" en haut de main.c
Souvenez-vous de ceci : à chaque fois que vous faites appel à une fonction X dans un fichier, il faut que vous ayez inclus les prototypes de cette fonction dans votre fichier. Cela permet au compilateur de vérifier si vous l'avez correctement appelée.
Comment j'ajoute des fichiers .c et .h à mon projet ?
Ca dépend de l'IDE que vous utilisez, mais globalement la procédure est la même : Fichier / Nouveau / Fichier source.
Cela crée un nouveau fichier vide. Ce fichier n'est pas encore de type .c ou .h, il faut que vous l'enregistriez pour le dire. Enregistrez donc ce nouveau fichier (même s'il est encore vide !). On vous demandera alors quel nom vous voulez donner au fichier. C'est là que vous choisissez si c'est un .c ou un .h :
- Si vous l'appelez fichier.c, ce sera un .c
- Si vous l'appelez fichier.h, ce sera un .h
C'est aussi simple que cela

Enregistrez votre fichier dans le répertoire où se trouvent les autres fichiers de votre projet (le même dossier que main.c). Généralement,
vous enregistrerez tous vos fichiers dans le même répertoire, les .c comme les .h.
Le dossier du projet ressemble au final à ça :
Vous y voyez des .c et des .h ensemble.
Bref, maintenant votre fichier est enregistré, mais il n'est pas encore vraiment ajouté au projet !
Pour l'ajouter au projet, faites un clic droit dans la partie à gauche de l'écran (où il y a la liste des fichiers du projet) et choisissez "Add files" :
Une fenêtre s'ouvre et vous demande quels fichiers ajouter au projet. Sélectionnez le fichier que vous venez de créer, et c'est fait

Le fichier fait maintenant partie du projet et apparaît dans la liste à gauche !
Les includes des bibliothèques standard
Une question devrait vous trotter dans la tête...
Si on inclut les fichiers stdio.h et stdlib.h, c'est donc qu'ils existent quelque part et qu'on peut aller les chercher non ?
Oui bien sûr !
Ils sont installés normalement là où se trouve votre IDE. Dans mon cas sous Code::Blocks, je les trouve là :
C:\Program Files\CodeBlocks\MinGW\include
Il faut généralement chercher un dossier include.
Là-dedans, vous allez trouver plein plein de fichiers. Ce sont des headers (.h) des bibliothèques standard, c'est-à-dire des bibliothèques disponibles partout (que ce soit sous Windows, Mac, Linux...). Vous y retrouverez donc stdio.h et stdlib.h entre autres.
Vous pouvez les ouvrir si vous voulez, mais prévoyez une bassine à côté on sait jamais

En effet, c'est un peu compliqué et ça peut donner la nausée (il y a pas mal de choses qu'on n'a pas encore vues, notamment pas mal de directives de préprocesseur). Si vous cherchez bien, vous verrez que ce fichier est rempli de prototypes de fonctions standard, comme printf par exemple.
Ok, je sais maintenant où se trouvent les prototypes des fonctions standard. Mais je pourrai pas aussi voir le code source de ces fonctions ? Où sont les .c ?!
Ils n'existent pas

En fait, les fichiers .c sont déjà compilés (en code binaire, c'est-à-dire en code machine). Il est donc totalement impossible de les lire.
Vous pouvez retrouver les fichiers compilés dans un répertoire appelé "lib" généralement (pour "library"). Chez moi ils se trouvent dans :
C:\Program Files\CodeBlocks\MinGW\lib
Les fichiers compilés des bibliothèques ont l'extension .a sous Code::Blocks (qui utilise le compilateur appelé mingw), et ont l'extension .lib sous Visual C++ (qui utilise le compilateur Visual).
N'essayez pas de les lire c'est totalement pas comestible
Voilà vous savez maintenant un peu mieux comment ça fonctionne j'espère

Dans vos fichiers .c, vous incluez les .h des bibliothèques standard pour pouvoir utiliser des fonctions standard comme printf. Votre ordinateur a ainsi les prototypes sous les yeux et peut vérifier si vous appelez les fonctions correctement (si vous n'oubliez pas de paramètres par exemple).