0% ont trouvé ce document utile (0 vote)
3 vues41 pages

Poly

Le document présente une introduction au langage de programmation C, en expliquant son importance et son histoire. Il aborde les concepts fondamentaux tels que les variables, les fonctions, et les opérations d'entrée/sortie avec des exemples pratiques. Le texte souligne également la nécessité d'un compilateur et d'un débogueur pour le développement en C.

Transféré par

safia.habbi
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
3 vues41 pages

Poly

Le document présente une introduction au langage de programmation C, en expliquant son importance et son histoire. Il aborde les concepts fondamentaux tels que les variables, les fonctions, et les opérations d'entrée/sortie avec des exemples pratiques. Le texte souligne également la nécessité d'un compilateur et d'un débogueur pour le développement en C.

Transféré par

safia.habbi
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

David Hébert

Introduction au langage C
Table des matières
1 Introduction 3

2 Pour débuter : le printf 5

3 Les variables 7

4 Récupérer une saisie : le scanf 11

5 Opérations 13

6 Test 14

7 Les boucles 19

8 Les fonctions 21

9 Les pointeurs 25

10 Les tableaux 28

11 Lire et écrire dans des fichiers 31

12 Le #define 35

13 En-tête du programme : prototypes et structures 37

2
1 Introduction

Les programmes sont à la base de tout ce que nous faisons avec un ordinateur : ouvrir une page Web, un
traitement de texte, regarder une photo ou un film etc. Mais la machine bien que (très très) puissante n’est
pas intéligente du tout (en tout cas pour le moment) ; elle ne sait faire que ce qu’on lui dit de faire et c’est
tout. Comment communiquer avec elle ? Simplement en lui parlant dans son langage : le langage binaire. Le
langage binaire est une suite de 0 et de 1 (la machine est basée sur un système simple : le courant passe = 1
ou le courant ne passe pas = 0). Donc pour demander à la machine d’ouvrir une page Google on lui dirait :
01001111100101011101000101110010010...
et ça continue comme ça longtemps. Il faut beaucoup de temps pour parler en binaire ! Par chance il existe des
traducteurs de binaire, qui portent le nom de compilateur. On écrit dans un langage sophistiqué et le com-
pilateur le traduit en binaire pour qu’il puisse être comprit par la machine. Comment "écrire dans un langage
sophistiqué" ? Eh bien il existe beaucoup de tel langage que l’on appel d’ailleurs plus simplement langage de
programmation, voir par exemple http ://[Link]/wiki/Liste _des _langages _de _programmation
pour une liste exhaustive. Dans ce cour nous nous intéressons au langage de programmation le plus utilisé
dans le monde : le langage C .

(source http ://[Link]/ )


Le C est un langage de programmation dit de "bas niveau", c’est à dire que son langage est proche du
langage binaire (on aura quand même un peu plus de mot que 0 et 1) contrairement à d’autre langage (comme
le java par exemple) qui sont dit de "haut niveau".
A la fin des année 50 (1958 précisément) les premiers ordinateurs faisaient leur apparition accompagner du
premier langage de programmation : l’Algol (c’est le nom d’une étoile dont l’étymologie arabe signifie "la tête
de l’ogre", mais qui ici est simplement l’acronyme de "Algorithmic oriented language"). Puis, peu satisfait
de ses capacités, le laboratoire de mathématiques de l’université de Cambridge et l’unité d’informatique de
l’université de Londre créèrent dans le courant des années 60 le CPL (acronyme de Combined programming
language) qui était certes plus complet mais beaucoup plus complexe, beaucoup trop exigeant pour les
compilateurs de l’époque. Dans un soucis d’accessibilité Kenneth Lane Thompson (4 fevrier 1943 - ) le

3
transforme et aboutit à la création du BCPL (Basic CPL ou Bootstrap CPL) que l’on appela simplement le
langage B . Cherchant encore a rendre la programmation plus accessible le langage B évolua, dans les années
70, en un langage simplement nommé le Langage C dont le principale contributaire fut Dennis Macalistair
Ritchie1 (9 septembre 1941 - 8 octobre 2011).
Petite info commerciale : comme vous l’aurez compris, vous aurez besoin pour programmer en C d’un
compilateur (traducteur de binaire). Un autre outil (disons-le : indispensable) est le debugeur : il vous
indiquera où sont les erreurs et les dysfonctionnement de votre programme (et pourra même vous suggérer
des corrections).
Pour la petite histoire : le premier ordinateur contemporain est l’ENIAC (Electronic Numerical Integrator
Analyser and Computer) :

Un jour une sauterelle alla se coincer dans la mécanique de la machine et grilla (en grillant) quelques
composants provoquant un dysfonctionnement. On appela ce dysfonctionnement un bug (qui signifie insecte
en anglais) ; l’expression resta et aujourd’hui on parle de bug à chaque dysfonctionnement de la machine.
Comment obtenir un compilateur et un debugeur, bref un environnement de développement (appelé
IDE pour Integrated Development Environment) ? Par exemple Code::Blocks fonctionne sur windows et
linux et se trouve gratuitement (et légalement) sur le Web. Également "Visual C++" qui fonctionne unique-
ment sur windows et dont la version gratuite est "Visual C++ Express".

1 Sa contribution dans le monde informatique fut d’autant plus grande qu’il a égalemement inventé le système d’exploitation

UNIX : en 1967, il intègre les laboratoires Bell et travaille avec Kenneth Lane Thompson sur le système d’exploitation multi-
utilisateurs Multics (acronyme de Multiplexed information and computing service). Assez vite, jugeant Multics trop complexe
et volumineux, le duo décide de tout reprendre à zéro et d’inventer un autre système, avec une nouvelle philosophie : UNIX
(initialement appelé UNICS).

4
2 Pour débuter : le printf

Comme nous l’avons déjà fait remarquer : la machine est bête ! Elle ne fera que ce que vous lui com-
manderez. Si on veut lui dire d’écrire "Bonjour" dans la console par exemple il faut lui indiquer tout ce qu’il
y a à faire : ouvrir la console, mettre le curseur en haut à gauche, écrire le mot puis fermer la console.
Et c’est le travail du programmeur de lui indiquer toutes ces étapes. Heureusement d’autre ont avant nous
écris ces lignes de programmation et ont rangé ces données dans une bibliothèque que l’on peut invoquer.
Comment charger une bibliothèque ? En demandant à la machine de le faire (pardi) à l’aide de la commande
#include<biblioth\‘eque.h> (l’extension .h est pour header, c’est à dire à mettre en tête du document).
Il existe beaucoup de bibliothèque mais deux sont en générale indispensable au bon fonctionnement d’un pro-
gramme : la bibliothèque standard (les commandes de base y sont stockées) et la bibliothèque de gestion
des entrées/sorties standards. Elles sont respectivement nommées stdlib.h (standard library) et stdio.h
(standard input/output). Donc en général un programme en C commence par

1 #include<stdlib.h>
2 #include<stdio.h>

Ensuite il faut indiquer au programme quoi faire. Pour cela on fait appel à la fonction principale du
programme. Nous reparlerons plus en détail des fonctions, ce qu’il faut retenir pour l’instant c’est que pour
définir la fonction principale du programme on écrit :

3 int main() {
4
5 /* ici code */
6
7 return(0);
8 }

Note : tout ce qui est compris entre les symboles /* et */ sera ignoré par le compilateur. On s’en sert pour
mettre quelques commentaires pour détailler le programme.
Le return(0) veut dire que la fonction renverra 0. Cette valeur signifie que le programme c’est exécuté
sans encombre. Pour écrire dans l’output standard (la console) on utilise la fonction printf définie dans la
bibliothèque stdio.h. Pour afficher la chaine de caractère "Bonjour" on écrira

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 printf("Bonjour");
7
8 return(0);
9 }

Retenez bien cette règle :

Chaque ligne de commande doit impérativement finir par un point-virgule !

Que se passe t’il lorsqu’on compile ce programme ? Le compilateur, rappelons-le, est un traducteur en
binaire pour la machine. De manière un peu schématique : il va créer un fichier dans lequel il va traduire
ce qu’il lit ; appellons-le traduction_en_binaire. Mais il va aussi créer un autre fichier dans lequel il
va stocker tout ce qu’il sait ; on va l’appeler Memoire_du_compilateur. Il commence par lire la ligne 1 :
#include<stdlib.h>. Pour lui #include<stdlib.h> est un mot spécial qui lui dis "inclut la bibliothèque
stdlib.h", ce qu’il fait : il ouvre donc le fichier stdlib.h et lit ce qu’il s’y trouve ; ce que vous pouvez faire
aussi. D’ailleurs si vous le faites vous verrez que ce fichier contient des définitions de fonctions. Le compilateur
ne va pas traduire chacune de ces fonctions (on rappel que la machine est bête et qu’elle ne saurait pas quoi
en faire). Par contre il va mettre dans sa mémoire tout ce qu’elle contient ; schématiquement il va ranger

5
dans Memoire_du_compilateur la définition de chacune des fonctions qui s’y trouve. Une fois que c’est fait
il passe à la ligne 2 et applique le même procédé pour la bibliothèque stdio.h. Il passe ensuite à la ligne 3 et
lit un saut de ligne : il l’ignore ; en d’autre terme vous pouvez faire autant de saut de ligne que vous voudrez
le compilateur ne les verra pas (il est donc souhaitable de sauter à la ligne pour aérer le code autant que
faire ce peut). Il lit ensuite la ligne 4 et voit qu’il s’agit de la fonction principale du programme. La première
commande est printf. Il ne comprend pas ce mot et va donc chercher dans Memoire_du_compilateur s’il
elle existe, ce qui est le cas (elle est définie dans la bibliothèque stdio.h) il va donc traduire (c’est à dire écrire
en binaire dans traduction_en_binaire) tout ce que fait la fonction printf avec le paramètre "Bonjour".
Il continue ainsi jusqu’à la fin du programme. Il indique ensuite au debugeur que tout c’est bien passé et le
debugeur va créer un fichier exectutable par la machine à partir du code binaire traduction_en_binaire.
En exécutant ce programme on aura :
Bonjour
En réalité le mécanisme compilateur/debugeur est plus compliqué (il suffit de regarder tous les fichier qui
sont crées lors de la compilation ! ). Néanmoins vous pourrez trouver l’exécutable de votre programme dans
le répertoire debug qui a été créer.
Donc pour écrire dans l’output standard on utilise la fonction printf. On prendra garde que certain
caractères (accentués) ne s’affichent pas correctement. On notera également quelques caractères spéciaux :

\n Génère une nouvelle ligne (new line)


\t Tabulation horizontale
\v Tabulation verticale
\b Retour d’un caractère en arrière (backspace)
\r Un retour chariot (carriage return)
\f Un saut de page (form feed)
\a Un signal sonore (alarm)
\’ Affiche ’
\" Affiche "
\\ Affiche \

Un exemple

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 printf("Voici un bip : \a\n\n Voici \t des \t tabulations\n\n
7 Et voici un guillemet \" \n\nAurevoir");
8
9 return(0);
10 }

Voici un bip :

Voici des tabulations

Et voici un guillemet "

Aurevoir
Maintenant qu’on sait écrire, apprenons à lire. Pour cela on a besoin de variable.

6
3 Les variables

Qu’est-ce qu’une variable pour la machine ? Ç’est deux choses : une valeur et un "endroit" où est rangée
cette valeur. Cet "endroit" est la mémoire de la machine. Comme vous le savez peut-etre la machine possède
plusieurs mémoire : registres, mémoires cache, mémoire vive et disque dur. Toutes ces mémoires, sauf le disque
dur, s’effacent dès qu’il n’y a plus de courant dans la machine (c’est à dire quand on l’éteint). Les registres
sont des mémoires très petites mais directement posées dans le processeur et donc très rapide d’accès (les
plus rapide en fait). Les mémoires cache sont des mémoires entre registres et mémoires vive. Le disque dur
lui permet de stocker énormément d’information mais son accès est le plus lent. Nous travaillerons avec la
mémoire vive (en fait on a pas trop le choix ; c’est comme ça que fonctionne le langage C ).
Le langage de la machine est le binaire : une suite de 0 et de 1. Pour la mémoire un de ces nombres est
un bit (binary digit), mais compte tenu de la puissance des machines on les regroupe par 8(= 23 ) et on appel
cela un octet. Dans ces mémoires vive on peut stocker des octets et l’endroit de la mémoire ou sont stocker
ces octets est l’adresse.
Le langage C gère lui même le nombre d’octet à attribuer à une variable en fonction du type de la variable :
la variable est-elle un entier positif ou négatif, une lettre de l’alphabet, un nombre à virgule etc... Voici une
liste (non-exhaustive) de type de variable proposé par le langage C :
Type (signification) Taille (en octet) Plage de valeur
char (Caractère) 1 -128 à 127
unsigned char (Caractère non signé) 1 0 à 255
short int (Entier court) 2 -32 768 à 32 767
unsigned short int (Entier court non signé) 2 0 à 65 535
int (Entier) 4 -2 147 483 648 à 2 147 483 647
unsigned int (Entier non signé) 4 0 à 4 294 967 295
long int (Entier long) 4 -2 147 483 648 à 2 147 483 647
unsigned long int (Entier long non signé) 4 0 à 4 294 967 295
float (Nombre décimal) 4 −3.4 ∗ 10−38 à 3.4 ∗ 1038
double (Nombre décimal long) 8 −1.7 ∗ 10−308 à 1.7 ∗ 10308
long double (Nombre décimal très long) 10 −3.4 ∗ 10−4932 à 3.4 ∗ 104932
Comment utiliser les variables en C ? Tout d’abord il faut déclarer la variable, c’est à dire demander à la
machine de nous libérer et de nous réserver un certain nombre d’octet dans la mémoire vive ; Pour ce faire il
suffit simplement d’indiquer le type de la variable et son nom comme cela :

1 int n;

(surtout ne pas oublier le point virgule !). Que se passe t’il lorsque le programme arrive à cette ligne ?
Le programme indique à la machine que de l’espace mémoire est réclamée ! Puisqu’il s’agit d’un entier, le
programme réclame 4 octets2 . La machine s’exécute et alloue 4 octets dans la mémoire vive. La variable n
est donc créée. Comme on l’a dit une variable c’est une valeur et une adresse. Pour l’instant la variable n n’a
pas de valeur mais a une adresse puisqu’on a réserver une place dans la mémoire. Cette adresse est
&n
(le "et" commercial & suivit du nom de la variable). Cette adresse est un entier. Comment donner une valeur
à la variable ? Le symbole d’affectation de valeur est le =. On initialise alors la variable en écrivant alors
1 int n;
2 n=0;
On peut faire la déclaration et l’initialisation en même temps :
1 int n=0;
On peut déclarer plusieurs variables en même temps (séparées par une virgule) et les initialiser par la même
occasion :
2 En général (dans 99.999999999999% des cas) cela ne pose aucun problème. Cependant il peut arriver (par exemple si vous

travaillez avec une machine datant des années 50) qu’il n’y ai plus de place dans la mémoire vive ; cela provoquera alors une
erreur.

7
1 int i, j=0, k, l=-10;
2 j=1;
3 k=0;
Lorsque le programme lit la première ligne, les variables i, j, k et l sont créés. Les variables j et l sont
initialisées à 0 et -10 respectivement ; à la ligne 2, la variable j a sa valeur qui passe à 1 et la variable k est
initialiser à 0. A la fin de ces trois lignes, i n’est pas initialisée, j vaut 1, k vaut 0 et l vaut -10. Voici un
autre exemple :
1 unsigned long int n=0;
2 char c, d, Var, LettreA=’A’, LettreB ;
3 double x;
4
5 x=-173.144;
6 LettreB=’B’;
Pour les lettres : on met exactement un caractère entre apostrophes, pas entre guillemets. Pour les nombres
décimaux : on ne met pas de virgule mais le point pour séparer partie entière et partie décimale. En ce qui
concerne les noms des variables quelques règles sont a respecter :
• Le nom d’une variable doit commencer par une lettre majuscule ou une lettre minuscule ou underscore (_) ;
pas par un chiffre.
• Le nom d’une variable peut être aussi long que l’on souhaite mais ne doit contenir que des lettres majuscules,
minuscules ou des chiffres ou le symbole underscore ; pas d’autre symboles (comme \, %, é, à, & ...)
• Les mots suivants sont réservés : auto, break, case, char, const, continue, default, do, double,
else, enum, extern, float, for, goto, if, int, long, register, return, short, signed,
sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while.
Comme spécifié dans le tableau ci-dessus, les caractères sont en fait des nombres (compris entre 0 et 255).
Dans l’exemple précédent, on aurait put écrire
6 LettreB=66;
La correspondance entre valeur et caractère est synthétisé dans le tableau suivant. Les caractères sont appelés
les caractères ASCII (acronyme de American standard code for information interchange) dont on trouvera le
tableau à la fin de ce chapitre.
Comment faire pour afficher une variable ? Supposons que l’on a une variable x qui contient la valeur 66.
Si cette variable est un caractère on souhaite voir apparaître la lettre B, si cette variable est un entier, on
souhaite voir apparaître le nombre 66. Il faut donc spécifier le type de la variable à l’aide de spécificateur de
type. Voici une liste :
Type Spécificateur
char %c
unsigned char %c
short int %hi, %hd
unsigned short int %hu
int %i, %d
unsigned int %u
long int %li, %ld
unsigned long int %lu
float %f
double %lf
long double %Lf

Voici un exemple d’utilisation


1 #include<stdlib.h>
2 #include<stdio.h>
3

8
4 int main() {
5
6 int n=50;
7 char c=’A’;
8
9 printf("L’entier n a pour valeur %d", n);
10 printf("\n\n");
11 printf("Le caractere c est la lettre %c",c);
12 printf("\n\n");
13 printf("Je repete que l’entier n vaut %d
14 et que le caractere c est la lettre %c",n,c);
15
16 return(0);
17
18 }
L’entier n a pour valeur 50

Le caractere c est la lettre A

Je repete que l’entier n vaut 50 et que le caractere c est la lettre A


Les caractères étant vu comme des nombres, on peut les afficher en tant que tel. De même l’adresse d’une
variable est un entier que l’on peut afficher (on rappel que l’adresse de la variable x est l’entier &x).

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 double x=3.14;
7 char c;
8
9 c=’Z’;
10
11 printf("Le numero ASCII du caractere %c est %d",c,c);
12 printf("\n\n");
13 printf("La variable x a pour adresse %d
14 et vaut %lf mais la variable c qui
15 est le caractere %c a pour adresse
16 %d",&x,x,c,&c);
17
18 return(0);
19 }

Le numero ASCII du caractere Z est 90

La variable x a pour adresse 1636208 et vaut 3.140000 et la variable c qui est le


caractere Z a pour adresse 1638204
A propos de la précision : on utilise en générale le type double et long double pour les nombre décimaux.
Comme le montre l’exemple précédent, la précision est par défaut de 6 décimales en tronquant s’il y en a plus
ou en rajoutant des 0 (comme c’est le cas dans notre exemple). On peut régler cette précision en indiquant
le nombre de décimale que l’on souhaite voir apparaître comme illustrer dans l’exemple suivant :

1 #include<stdlib.h>
2 #include<stdio.h>
3

9
4 int main() {
5
6 double x=-3.1415926535897932384626;
7
8 printf("x = %.0lf\n",x);
9 printf("x = %.1lf\n",x);
10 printf("x = %.3lf\n",x);
11 printf("x = %.5lf\n",x);
12 printf("x = %.10lf\n",x);
13 printf("x = %.20lf\n",x);
14 printf("x = %.50lf\n",x);
15
16 return(0);
17 }

x=-3
x=-3.1
x=-3.142
x=-3.14159
x=-3.1415926536
x=-3.141592653589793100000
x=-3.141592653589793100000000000000000000000000000000000
Comme vous le constater, on ne peut mettre plus de 16 décimales et la machine tronque par excès ou
défauts les décimales.

10
4 Récupérer une saisie : le scanf

Pour récupérer une saisie il faut d’abord avoir une variable pour stocker la valeur. Illustrons cela a travers
un exemple : supposons que l’on souhaite que l’utilisateur entre son age. On déclare alors une variable age
qui contiendra la réponse
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int age;
7

Bien que cela ne soit pas nécessaire, on a l’usage d’initialiser toutes les variables d’un programme (cela est
surtout vrai pour les programme très lourd qui manipule beaucoup de variable mais prenons cette habitude
des le début).
8 age = 0;
Soyons polit et invitons l’utilisateur à entrer son age :
9 printf("Entrez votre age : ");
Pour saisir l’information on utilise la commande scanf il faut spécifier le type de la variable (entre guillemets)
et son adresse :
10 scanf("%d",&age);
En fin de compte on a le code suivant
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int age;
7
8 age=0;
9 printf("Entrez votre age : ");
10 scanf("%d",&age);
11 printf("\n\nVotre avez %d ans et votre age est enregistree a l’adresse %d",age,&age);
12
13 return(0);
14
15 }
Entrez votre age : 30

Vous avez 30 ans et votre age est enregistree a l’adresse 1638212


Bien sur on peut lire plusieurs informations en même temps

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int age, taille, poids;
7

11
8 age=0;
9 taille=0;
10 poids=0;
11 printf("Entrez votre age, votre taille et votre poids: ");
12 scanf("%d %d %d",&age,&taille,&poids);
13 printf("\n\nVotre age est %d ; votre taille est %d et l’adresse
14 de votre poids (qui est de %d kg) est %d.",age,taille,poids,&poids);
15
16 return(0);
17
18 }

Entrez votre age, votre taille et votre poids: 30 190 80

Votre age est 30 ; votre taille est 190 et l’adresse


de votre poids (qui est de 80 kg) est 1638204.

12
5 Opérations

Le langage C dispose de 5 opérations de base : l’addition (+), la soustraction (-), la multiplication (*), la
division (/) et le modulo3 (%). Elles s’utilisent de la manière suivante :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int i,j,k,l;
7 float x,y;
8
9 i=0;
10 j=1;
11 k=3*j+5;
12 l=5/2;
13 x=5/2;
14 y=5.0/2.0;
15
16 printf("Resultat : %d.\n",k);
17 printf("On peut faire des calculs directement dans le
18 printf : k-5 = %d\n",k-5);
19 printf("Pour la division il faut faire attention !
20 Par exemple 5/2 = %d\n",l);
21 printf("Dans ce cas : 5/2 = %f... ah bon? et si on met
22 des points : 5.0/2.0=%f\n",x,y);
23 printf("La division euclidienne de 529 par 17 est :
24 529=%d*17+%d",529/17,529%17);
25
26 return(0);
27 }

Resultat : 8
On peut faire des calculs directement dans le printf : k-5 = 3
Pour la division il faut faire attention ! Par exemple 5/2 = 2
Dans ce cas : 5/2 = 2.000000... ah bon? et si on met des points : 5.0/2.0=2.500000
La division euclidienne de 529 par 17 est : 529 = 31*17+2
Pour effectuer des opérations un peu plus sophistiquées (racine carré, logarithme, cosinus etc) il existe la
bibliothèque math.h.

3 Le modulo donne le reste d’une division euclidienne

13
6 Test

Une règle d’or pour la machine :


0= FAUX 1=VRAI
Comment faire pour tester une variable ? On utilise les symboles suivants
Symbole Signification
== Est égal à
> Est supérieur à
< Est inférieur à
>= Est supérieur ou égal à
<= Est inférieur ou égal à
!= Est différent de

Par exemple :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int test1, test2, test3;
7
8 test1 = 1<=1;
9 test2 = 1<1;
10 test3 = 1==1;
11
12 printf("Les resultats des tests sont : \n\n\t Test 1 = %d
13 \n\n\t Test 2 = %d \n\n\t Test 3 = %d",test1,test2,test3);
14
15 return(0);
16 }

Les resultats des tests sont :

Test 1 = 1
Test 2 = 0
Test 3 = 1

La commande if : On fait un test, s’il est vrai on effectue les commandes passées en paramètre :

if (test) {
/* ligne de commandes si le test est vrai */
}
(attention pas de point virgule à la fin de l’incollade). Par exemple :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 char cara;
7

14
8 printf("Tapez une lettre de l’alphabet : ");
9 scanf("%c",&cara);
10
11 if(cara==’A’){
12 printf("\n\nVous avez tape la premiere lettre de l’alphabet !");
13 }
14 if(cara==’Z’){
15 printf("\n\nVous avez tape la derniere lettre de l’alphabet !");
16 }
17
18 return(0);
19 }

Tapez une lettre de l’alphabet : A

Vous avez tape la premiere lettre de l’alphabet !


On peut imbriquer ces structures :
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 char cara;
7
8 printf("Tapez une lettre de l’alphabet : ");
9 scanf("%c",&cara);
10
11 if(cara==’A’){
12 printf("\n\nVous avez tape la premiere lettre de l’alphabet !
13 Recommencer s’il vous plait : ");
14 scanf("%c",&cara);
15
16 if(cara==’Z’){
17 printf("\n\nIncroyable ! vous avez tape la derniere lettre
18 de l’alphabet !");
19 }
20 }
21
22 return(0);
23 }
Tapez une lettre de l’alphabet : A

Vous avez tape la premiere lettre de l’alphabet ! Recommencer s’il vous plait : A
Si le test est faux on peut également demander a exécuter certaines commandes à l’aide du else
if (test) {
/* lignes de commandes si le test est vrai */
}
else{
/* lignes de commandes si le test est faux */
}
Par exemple :

1 #include<stdlib.h>

15
2 #include<stdio.h>
3
4 int main() {
5
6 char cara;
7
8 printf("Tapez une lettre de l’alphabet : ");
9 scanf("%c",&cara);
10
11 if(cara==’A’){
12 printf("\n\nVous avez tape la premiere lettre de l’alphabet !");
13 }
14 else{
15 printf("\n\nCe n’est pas la premiere lettre de l’alphabet !");
16 }
17
18 return(0);
19 }
Tapez une lettre de l’alphabet : B

Ce n’est pas la premiere lettre de l’alphabet !


Bien sur on peut imbriquer les if de la manière suivante :
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 char cara;
7
8 printf("Tapez une lettre de l’alphabet : ");
9 scanf("%c",&cara);
10
11 if(cara==’A’){
12 printf("\n\nVous avez tape la premiere lettre de l’alphabet !");
13 }
14 else if (cara==’Z’){
15 printf("\n\nVous avez tape la derniere lettre de l’alphabet !");
16 }
17 else {
18 printf("\n\nCe n’est ni la premiere ni la derniere lettre de l’alphabet !");
19 }
20
21 return(0);
22 }
Tapez une lettre de l’alphabet : B

Ce n’est ni la premiere ni la derniere lettre de l’alphabet !

Les connecteurs logiques : Le Langage C permet d’utiliser le langage de la logique


Symbole Signification
&& ET
|| OU
! NON

16
Par exemple :
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int n;
7 char c;
8
9 printf("Entrer une lettre de l’alphabet et un entier : ");
10 scanf("%c %d",&c,&n);
11
12 if((c==’A’)&&(n==0)) {
13 printf("\nC’est la premiere lettre de l’alphabet et c’est nul !");
14 }
15 else if ((!(n==0))||(c==’Z’)) {
16 printf("\nSoit c’est Z soit c’est non nul !");
17 }
18
19 return(0);
20 }
Entrer une lettre de l’alphabet et un entier : B 2
Soit c’est Z soit c’est non nul !

La commande switch : Lorsque l’on veut tester la valeur d’une variable au lieu d’imbriquer les if les un
dans les autres on peut utiliser la commande switch.

switch (variable){
case valeur1:
*/ lignes de commandes si variable=valeur1 */
break;
case valeur2:
/* lignes de commandes si variable=valeur2 */
break;
case valeur3:
/* lignes de commandes si variable=valeur3 */
break;
.
.
.
case valeurn:
/* lignes de commandes si variable=valeurn */
break;
default:
/* lignes de commandes sinon */
break;
}

La commande switch ne permet que de tester si la variable en paramètre est égale a une valeur (pas
d’autre test du type supérieur ou inférieur). A propos de la commande break : cette commande indique au
programme qu’il faut aller tout à la fin du switch lorsqu’elle est lu. Si on l’omet le programme continue à lire
la suite (donc jusqu’au default). Voici un exemple (dans le cas ’Y’ on a omit le break) :

1 #include<stdlib.h>
2 #include<stdio.h>

17
3
4 int main() {
5
6 char cara;
7
8 printf("Tapez une lettre de l’alphabet : ");
9 scanf("%c",&cara);
10
11 switch (cara) {
12 case ’A’:
13 printf("\nC’est la premiere lettre de l’alphabet !");
14 break;
15 case ’B’:
16 printf("\nC’est la deuxieme lettre de l’alphabet !");
17 break;
18 case ’Y’:
19 printf("\nC’est l’avant-derniere lettre de l’alphabet !");
20 case ’Z’:
21 printf("\nC’est la derniere lettre de l’alphabet !");
22 break;
23 default:
24 printf("\nCe n’est ni A, ni B, ni Y, ni Z.");
25 break;
26 }
27
28 return(0);
29 }

Tapez une lettre de l’alphabet : A


C’est la premiere lettre de l’alphabet !
Tapez une lettre de l’alphabet : Y
C’est l’avant-derniere lettre de l’alphabet !
C’est la derniere lettre de l’alphabet !

18
7 Les boucles

Les boucles sont des commandes qui permettent d’éfféctuer des commandes tanqu’une certaine condition
n’est pas satisfaite. Le langage C nous offre trois type de boucles :

Le for : On l’utilise avec une variable de type entière

for(initialisation; test ; pas){


/* lignes de commandes a exécuter tant que le test est vrai */
}

Par exemple :
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int i;
7
8 for(i=0;i!=10;i=i+1){
9 printf("HA ! ");
10 }
11
12 return(0);
13 }

HA ! HA ! HA ! HA ! HA ! HA ! HA ! HA ! HA ! HA !

Le while : On exécute la commande tant que le test est vrai.


while(test){
/* lignes de commandes a exécuter tant que le test est vrai */
}

Par exemple :
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int n=1;
7
8 while(n!=0){
9 printf("N’entrez surtout pas 0 : ");
10 scanf("%d",&n);
11 }
12
13 printf("0 c’est nul !");
14
15 return(0);
16 }

19
N’entrez surtout pas 0 : 1
N’entrez surtout pas 0 : 651511
N’entrez surtout pas 0 : 9845
N’entrez surtout pas 0 : -4
N’entrez surtout pas 0 : 0
0 c’est nul !

Le do...while : Dans le cas du while on peut ne jamais rentrer dans la boucle (si le test est faux dès
le départ), tandis que dans le do...while on rentrera dans la boucle au moins une fois : on fais d’abord la
liste des instruction puis ensuite on fait le test.

do{
/* lignes de commandes a exécuter tant que le test est vrai
sauf au premier tour ou ces lignes seront quoi qu’il en soit exécutées */
}while(test);
Surtout ne pas oublier le point virgule à la fin du while !

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int n=1;
7
8 do{
9 printf("Entrez un nombre positif : ");
10 scanf("%d",&n);
11 }while(n>=0);
12
13 printf("Pourquoi un negatif ?");
14
15 return(0);
16 }
Entrez un nombre positif : 0
Entrez un nombre positif : 21458
Entrez un nombre positif : 6512
Entrez un nombre positif : -15
Pourquoi un negatif ?

20
8 Les fonctions

Comme en mathématiques, une fonction porte un nom, prend des paramètres et donne un résultat. Le
schéma générale d’une fonction est le suivant :

type_de_la_sortie nom (type1 parametre1, type2 parametre2, ...) {

/* Lignes de commandes */

Le nom d’une fonction doit obéir aux même règle que le nom des variables.
On définis les fonctions avant la fonction principale (la fonction main). Voici un exemple :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int partie_entiere (double x) {
5
6 int n=0;
7
8 n=x; /* On force le reel x a aller dans une variable de
9 type entiere ; ceci a pour conséquence de tronquer
10 le reel et de ne garder que sa partie entiere.
11 Ceci s’appel un cast. Une façon plus propre de
12 rédiger est
13 n= (int) x
14 */
15 return(n);
16
17 }
18
19 int main() {
20
21 double x = 0;
22 int n=0;
23
24 printf("Entrez un nombre reel : ");
25 scanf("%lf",&x);
26
27 n=partie_entiere(x);
28 printf("La partie entiere de %lf est %d", x,n);
29
30 return(0);
31
32 }

Entrer un nombre reel : 0.318309886


La partie entiere de 0.318310 est 0
Que se passe t’il lorsqu’on compile ce programme : tout d’abord le compilateur va charger dans sa
mémoire les fonctions définies dans stdlib.h et stdio.h puis il va faire la même chose avec la fonction
partie_entiere. Puis quand il va lire le main il va se passer les choses suivantes :
1. Le compilateur demande de l’espace en mémoire pour une variable de type double ; on l’appel x et
on lui donne la valeur 0. On se rappel que pour la machine une variable c’est une valeur, ici 0, et une
adresse, ici &x.

21
2. Même chose avec une variable de type entiere.
3. Le compilateur lit printf ; il s’agit d’une fonction définie dans la bibliothèque stdio.h, il va donc
chercher sa définition et remplace printf("Entrez un nombre reel : ") par cette définition avec
le paramètre "Entrez un nombre reel : "
4. Même chose avec le scanf. Maintenant la variable x vaut 0.318309886.
5. Le compilateur lit partie_entiere ; il s’agit d’une fonction qu’il connaˆpuisqu’il la lut avant d’exé-
cuter le main (c’est pour cela qu’il fat définir les fonction avant le main). Il va donc remplacer
partie_entiere par sa définition avec comme paramètre la valeur de la variable x.
6. Il exécute donc partie_entiere :
(a) Tout d’abord le x de la fonction principale et le x de la fonction partie_entiere ne sont pas les
même ! Elles ont en effet la même valeur et le même nom mais n’ont pas la même adresse !
(b) Le compilateur demande de l’espace pour une variable de type entière qui s’appelle n. Mais il ne
s’agit pas du même n de la fonction principale (ce n’est pas la même adresse).
(c) On met la variable de type réelle dans la variable de type entière ce qui a pour conséquence de
tronqué le réel.
(d) On donne la valeur retour qui est l’entier n ; mais juste sa valeur pas la variable (c’est à dire qu’on
ne transmet pas l’adresse de la variable). Une fois que la fonction lit le return on revient au main.
En particulier tout ce qui peux être mis après le return ne sera pas lut ! De plus le compilateur
va signaler à la machine que la fonction est fini ; en particulier tout ce que la fonction utilisait est
effacer (dans notre cas, la machine va "libérer" la variable n de cette fonction).
7. Le résultat, qui est 0, est stockée dans la variable n (mais la variable n de la fonction main).
8. On affiche le résultat
Ce qu’il faut retenir c’est que les variables définies dans une fonction sont locales à cette fonction et
n’existent pas ailleurs dans le programme (même si une autre variable quelque part porte le même nom ;
le nom d’une variable est seulement utile pour le programmeur seul l’adresse et la valeur comptent pour la
machine).
Bien sur une fonction peut avoir plusieurs paramètres :
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int addition (int n1, int n2, int n3){
5
6 int res =0;
7 res=n1+n2+n3;
8
9 return(res);
10 }
11
12 int main() {
13
14 int a,b,c;
15
16 printf("Entrez trois entiers : ");
17 scanf("%d %d %d",&a, &b, &c);
18
19 printf("La somme de ces entiers est : %d", addition(a,b,c));
20
21 return(0);
22 }
Entrez trois entiers : 1 2 3
La somme de ces entiers est : 6
Une fonction peut ne prendre aucun paramètre

22
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int menu (){
5
6 int choix=0;
7
8 printf("\t\tMenu\n\n");
9 printf("\[Link]\n");
10 printf("\[Link]\n");
11 printf("\[Link]\n");
12 printf("\nVotre choix : ");
13 scanf("%d",&choix);
14
15 return(choix);
16 }
17
18 int main() {
19
20 switch(menu()){
21 case 1 :
22 printf("Beurk des escargots!\n");
23 break;
24 case 2 :
25 printf("Beurk des epinards!\n");
26 break;
27 case 3 :
28 printf("Beurk des huitres!\n");
29 break;
30 default :
31 printf("Peut-etre qu’une part de pizza vous conviendrais ?\n");
32 }
33
34 return(0);
35 }
Menu

1. Escargots
2. Epinards
3. Huitres

Votre choix : 4
Peut-etre qu’une part de pizza vous conviendrais ?
Une fonction peut ne renvoyer aucune valeur ; on parle dans ce cas de procédure. Dans cet unique cas
on peut omettre le return mais il faut spécifier qu’il n’y a pas de valeur retour en indiquant que le type du
résultat est vide : void

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 void bonjour (int n){
5
6 printf("Bonjour ! Le triple du nombre est %d\n", 3*n);
7 }
8

23
9 int main() {
10
11 int n=0;
12
13 printf("Entrez un entier et vous aurez une surprise : ");
14 scanf("%d",&n);
15
16 bonjour(n);
17
18 return(0);
19 }

Entrez un entier et vous aurez une surprise : 6


Bonjour ! Le triple du nombre est 18
Enfin il faut savoir qu’une fonction peut faire appel à elle même ; dans ce cas on parle de fonction récursive.

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int factoriel (int n){
5
6 if (n<=1) {
7 return(1);
8 }
9 else {
10 return(n*factoriel(n-1));
11 }
12 }
13
14 int main() {
15
16 int n=0;
17
18 printf("Entrez un entier : ");
19 scanf("%d",&n);
20 printf("%d! = %d\n",n,factoriel(n));
21
22 return(0);
23 }

Entrez un entier : 4
4!=24

24
9 Les pointeurs

Imaginons que l’on souhaite écrire une fonction qui prend en paramètre un entier n et qui transforme,
c’est à dire écrase sa valeur, cet entier en 3*n+1 si n est impaire et n/2 si n est paire. On écrirait :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 void fonct(int n){
5
6 if (n%2==0) {
7 n=n/2;
8 }
9 else {
10 n=3*n+1;
11 }
12 }
13
14 int main() {
15
16 int n=0;
17
18 printf("Entrez un entier : ");
19 scanf("%d",&n);
20
21 fonct(n);
22 printf("La nouvelle valeur de n est : %d\n",n);
23
24 return(0);
25 }

Mais si on exécute :
Entrer un entier : 6
La nouvelle valeur de n est : 6
Que ç’est-il passé ? Lorsque l’on a fait appel à la fonction fonct une nouvelle variable n a été crée interne à
cette fonction, locale à cette fonction. Les modifications apporter à cette variable seront interne à la fonction
et le n de la fonction main ne sera pas modifié ! On rappel que pour la machine une variable c’est une valeur
et une adresse. Donc pour que la fonction modifie la même variable il faut lui indiquer son adresse. Pour cela
on utilise une nouvelle classe de type : les pointeurs. Ce sont des variables dont les valeurs sont des adresses
(qui pointe vers une autre variable). On les déclare en ajoutant une étoile au nom de la variable :

int *n;

Cette commande signifie que la variable n contiendra une adresse d’une variable de type entière. Comme
nous l’avons signalé on a généralement tendance à initialiser les variables. Pour initialiser vers une variable de
type pointeur on utilise le mot NULL : c’est une adresse de défaut.

int *n;
n=NULL;

ou

int *n=NULL;

Un pointeur pointe donc vers une variable. Ce que l’on a de plus avec les pointeurs c’est que l’on peut
avoir accès à la valeur de cette variable. Voyons cela sur un exemple :

25
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main(){
5
6 int n_1, n_2=0, *m=NULL;
7
8 n_1=23;
9 m=&n_1;
10 n_2=*m;
11
12 printf("La valeur de n_1 = %d\n",n_1);
13 printf("L’adresse de n_1 = %d\n",&n_1);
14 printf("La valeur de n_2 = %d\n",n_2);
15 printf("L’adresse de n_2 = %d\n",&n_2);
16 printf("La valeur de m = %d\n",m);
17 printf("L’adresse de m = %d\n",&m);
18 printf("La valeur pointee par m = %d\n",*m);
19
20 return(0);
21 }

La valeur de n_1 = 23
L’adresse de n_1 = 1638212
La valeur de n_2 = 23
L’adresse de n_2 = 1638208
La valeur de m = 1638212
L’adresse de m = 1638204
La valeur pointee par m = 23
Ainsi les pointeurs permettent de récupérer l’adresse des variables ainsi que leur valeur. On peut donc
modifier une variable dans une fonction à l’aide des pointeurs ; reprenons notre exemple du début :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 void fonct(int *n){
5
6 if (*n%2==0) {
7 *n=*n/2;
8 }
9 else {
10 *n=3*(*n)+1;
11 }
12 }
13
14 int main() {
15
16 int n=0;
17
18 printf("Entrez un entier : ");
19 scanf("%d",&n);
20
21 fonct(&n); /* il ne faut pas oublié de passer une adresse en paramètre ! */
22 printf("La nouvelle valeur de n est : %d\n",n);
23
24 return(0);

26
25 }

Entrer un entier : 6
La nouvelle valeur de n est : 3
Bien sur les pointeurs peuvent êtres des valeurs de retour pour des fonctions :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int* adresse(int n){
5
6 return(&n);
7 }
8
9 int main() {
10
11 int n=0;
12
13 printf("Entrez un entier : ");
14 scanf("%d",&n);
15
16 printf("L’adresse locale de cet entier dans la fonction \"adresse\" est : %d\n
17 Mais sa vrai adresse est %d\n",adresse(n),&n);
18
19 return(0);
20 }

Entrer un entier : 23
L’adresse locale de cet entier dans la fonction "adresse" est : 1638128
Mais sa vrai adresse est 1638212

27
10 Les tableaux

Les tableaux permettent de déclarer plusieurs variable de même type en même temps. Par exemple pour
avoir dix variables de type entières on écrit :

int tableau[10];

Cette ligne va créer dix variables : tableau[0], tableau[1], ... tableau[8], tableau[9]. Attention :
l’indice d’un tableau de taille n commence à 0 et fini donc à n-1. Dans notre exemple la variable tableau[10]
n’existe pas ! Les adresses des variables tableau[0], tableau[1] etc sont contiguës (c’est à dire qu’elle se
suivent) :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 int tableau[10], i;
7
8 for(i=0; i<10 ; i=i+1){
9 printf("L’adresse de tableau[%d] est %d\n",i,&tableau[i]);
10 }
11
12 return(0);
13
14 }

L’adresse de tableau[0] est 1638176


L’adresse de tableau[1] est 1638180
L’adresse de tableau[2] est 1638184
L’adresse de tableau[3] est 1638188
L’adresse de tableau[4] est 1638192
L’adresse de tableau[5] est 1638186
L’adresse de tableau[6] est 1638200
L’adresse de tableau[7] est 1638204
L’adresse de tableau[8] est 1638208
L’adresse de tableau[9] est 1638212
Le type int vaut 4 octets c’est pour cela que les adresses vont de 4 en 4 et c’est en ce sens qu’elles se
suivent. En fait en déclarant

int tableau[10];

on définit un pointeur sur entier tableau. Ainsi tableau représente l’adresse de tableau[0]. En d’autre
terme &tableau[0] est la même chose que tableau. De même tableau[0] est la même chose que
*tableau. Puisque les adresses sont contiguës, il suffit de faire +1 pour obtenir tableau[1] : &tableau[1]
est la même chose que tableau+1 et tableau[1] est la même chose que *(tableau+1) etc.
Pour initialiser un tableau on peut faire une boucle. On peut aussi utiliser le raccourcis suivant :

int tableau[10]={2,4,6,8,10,12,14,16,18,20};

Ainsi tableau[0] vaudra 2, tableau[1] vaudra 4, tableau[3] vaudra 8 etc. La commande

int tableau[10]={2,4};

initialisera tableau[0] à 2 et tableau[1] à 4 et toutes les autres variables tableau à 0. Ainsi si l’on
veut initialiser toutes les variables à zéros, on écrira

28
int tableau[10]={0};
Cette vision contiguë des variables permet entre autre de former des chaînes de caractère.
char phrase[100];

phrase[0]=’S’;
phrase[1]=’a’;
phrase[2]=’l’;
phrase[3]=’u’;
phrase[4]=’t’;
phrase[5]=’ ’;
phrase[6]=’!’;
Cependant pour les chaîne de caractère il faut prendre une précaution supplémentaire : comme dans
l’exemple précédent le tableau phrase contient dans les sept premières case la phrase Salut ! ; les 93 autres
case n’ont pas été initialiser. Mais cela ne signifie pas qu’elle ne contiennes aucune valeur. Au contraire elle
contienne une certaine valeur, un certain caractère qui correspond à "des restes" d’ancien calculs. Il faut donc
être capable de dire à la machine que seul les 7 premières case interressent et qu’après cela ne compte pas
(pour l’instant en tout cas). On rajoute donc un caractère qui signale à la machine que c’est la fin de la phrase.
Il s’agit du caractère de fin de chaîne ; on l’écris \0. Ainsi un tableau de 10 caractères ne pourra compter
que 9 caractères réel puisque un sera réservé pour le caractère de fin de chaîne. Dans l’exemple précédent, il
faut rajouter :
phrase[7]=’\0’;
Si l’on souhaite afficher cette phrase on écrirais une boucle de la forme
int i=0;

while(phrase[i]!\=’\0’){
printf("%c",phrase[i]);
i=i+1;
}
Il existe en C un type chaîne de caractère (= tableau de caractère) : le type string dont le spécificateur
de type est %s. Ainsi la boucle précédente se raccourci en :
printf("%s",phrase);
De même avec la lecture ; on écrit
scanf("%s",&phrase);
Voici un exemple
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 char nom[100], animal[100];
7
8 printf("Entrez votre nom : ");
9 scanf("%s",&nom);
10 printf("Quel est votre animal prefere : ");
11 scanf("%s",&animal);
12 printf("L’animal prefere de %s est %s",nom, animal);
13
14 return(0);
15 }

29
Entrez votre nom : David
Quel est votre animal prefere : une araign\’ee
L’animal prefere de David est une
On constate sur l’exemple que le type string s’arrête de lire dès qu’il vois un espace.
Pour initialiser les chaînes de caractères on utilise les guillemets ; de plus le caractère de fin de chaîne \0
est mis automatiquement. Ainsi

char phrase[100];

phrase[0]=’S’;
phrase[1]=’a’;
phrase[2]=’l’;
phrase[3]=’u’;
phrase[4]=’t’;
phrase[5]=’ ’;
phrase[6]=’!’;
phrase[7]=’\0’;

peut plus simplement s’écrire

char phrase[100]="Salut !";

On peut même écrire

char phrase[]="Salut !";

ou

char *phrase="Salut !";

Dans ces deux derniers cas phrase est un tableau de caractère dont la taille est calculée en fonction de
la phrase d’initialisation choisie.
Une dernière chose sur les tableaux : on ne peut pas mettre de paramètre pour la taille du tableau !

int taille=10
int tableau[taille];

provoquera une erreur.


On retiendra également qu’un tableau est un pointeur donc pour le passer en paramètre ou sortie de
fonction on le déclarera en tant que tel.

30
11 Lire et écrire dans des fichiers

Pur ouvrir (et/ou créer) un fichier on utilise la fonction fopen. Cette fonction prend deux paramètres :
le nom du fichier et le mode d’ouverture. Cette fonction retourne une valeur de type pointeur sur FILE. Ce
qu’il faut retenir c’est que cette valeur de retour sera NULL lorsqu’il y aura une erreur à l’ouverture du fichier
(par exemple ouvrir un fichier qui n’existe pas).
Les différents mode d’ouverture sont les suivants :
r. Lecture seule.
w. Écriture seule. Si le fichier n’existe pas il sera crée.
a. Lecture et écriture. Si le fichier n’existe pas il sera crée. A l’ouverture on se place à la fin du document.
r+. Lecture et écriture.
w+. Lecture et écriture. Le contenu du fichier est supprimé et s’il n’existe pas il sera crée.
a+. Lecture et écriture. Si le fichier n’existe pas il sera crée. A l’ouverture on se place à la fin du document.
Par exemple :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 FILE *fichier=NULL;
7
8 fichier = fopen("[Link]","a+");
9
10 return(0);
11 }

On peut, (et dans la pratique on doit) tester que l’opération d’ouverture c’est bien passé :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 FILE *fichier=NULL;
7
8 fichier = fopen("[Link]","a+");
9
10 if(fichier==NULL) {
11 printf("PROBLEME A L’OUVERTURE\n\n");
12 }
13 else {
14 printf("Bravo ! L’ouverture/creation du fichier c’est bien passe.\n\n");
15 }
16
17 return(0);
18 }

Pour fermer le fichier on utilise la fonction fclose avec pour paramètre le pointeur sur FILE (cette
fonction renverra 0 lorsque la fermeture se passe sans problème ; on teste rarement le succès d’une fermeture).

1 #include<stdlib.h>
2 #include<stdio.h>
3

31
4 int main() {
5
6 FILE *fichier=NULL;
7
8 fichier = fopen("[Link]","a+");
9
10 if(fichier==NULL) {
11 printf("PROBLEME A L’OUVERTURE\n\n");
12 }
13 else {
14 printf("Bravo ! L’ouverture/creation du fichier c’est bien passe.\n\n
15 Maintenant on le ferme.");
16 fclose(fichier);
17 }
18
19 return(0);
20 }

Pour écrire un caractère on utilise la fonction fputc. Pour écrire plusieurs caractère on utilise fputs ou
fprintf de la manière suivante :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main() {
5
6 FILE *fichier=NULL;
7
8 fichier = fopen("[Link]","w");
9
10 if(fichier==NULL) {
11 printf("PROBLEME A L’OUVERTURE\n\n");
12 }
13 else {
14 printf("Bravo ! L’ouverture/creation du fichier c’est bien passe.\n
15 Maintenant on \’ecris un caractere\n");
16 fputc(’A’,fichier);
17 printf("Puis on ecris une chaine de caractere\n");
18 fputs( "Salut \c ca marche ?",fichier);
19 printf("Puis une derniere petite phrase avec un parametre\n");
20 fprintf(fichier,"L’adresse de ’fichier’ est %d",fichier);
21 printf("Puis on ferme le fichier");
22 fclose(fichier);
23 }
24
25 return(0);
26 }

Dans [Link]

ASalut ça marche ?L’adresse de ’fichier’ est 4344488

Pour lire un caractère on utilise la fonction fgetc. Par défaut on commence toujours par le début du
fichier, et l’appel une première fois de la fonction fgetc lira le premier caractère au début du fichier. Si on
appel une seconde fois cette fonction, on lira le second caractère jusqu’à ce que la fonction fgetc renvoie
une erreur. Cette erreur est la valeur retour EOF (pour End of file) de type chaine de caractère. Pour lire tous
les caractères d’un fichier, et les afficher dans la console, on ferais par exemple :

32
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main () {
5
6 char c;
7 FILE *fichier=NULL;
8
9 fichier=fopen("[Link]","r");
10
11 if(fichier != NULL) {
12 c=fgetc(fichier);
13 while(c!=EOF) {
14 printf("%c",c);
15 c=fgetc(fichier);
16 }
17 fclose(fichier);
18 }
19
20 return(0);
21 }

Pour lire des chaînes de caractère on utilise la fonction fgets. Cette fonction prend trois paramètres : la
variable ou il faut stocker ce qu’on a lu, le nombre de caractère maximale qu’il faut lire et le fichier qu’il faut
lire. A savoir : la fonction fgets s’arrête de lire le fichier lorsqu’on a atteint le nombre de caractère maximale
à lire ou si un saut de ligne est lu. Cette fonction renverra NULL si la lecture a échoué (si le fichier est vide
par exemple).

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main () {
5
6 char texte[100]="";
7 FILE *fichier=NULL;
8
9 fichier=fopen("[Link]","r");
10
11 if(fichier != NULL) {
12
13 fgets(texte,100,fichier);
14 printf("On a lu : \n%s",texte);
15
16 fclose(fichier);
17 }
18
19 return(0);
20 }

Comment faire si on veux revenir au début du fichier, ou relire une partie du document ? On dispose de 2
fonctions pour nous aider :
ftell : prend comme paramètre le FILE* et donne comme valeur retour l’entier signalant la position dans
le fichier pointé par le FILE. Le premier caractère du document étant 1. Exemple :
1 #include<stdlib.h>
2 #include<stdio.h>
3

33
4 int main () {
5
6 FILE *fichier=NULL;
7
8 fichier=fopen("[Link]","r+");
9
10 if(fichier != NULL) {
11
12 printf("A la position %d il y a le caractere %c\n",ftell(fichier),fgetc(fichier));
13 printf("A la position %d il y a le caractere %c\n",ftell(fichier),fgetc(fichier));
14 printf("A la position %d il y a le caractere %c\n",ftell(fichier),fgetc(fichier));
15 printf("A la position %d il y a le caractere %c\n",ftell(fichier),fgetc(fichier));
16 printf("A la position %d il y a le caractere %c\n",ftell(fichier),fgetc(fichier));
17
18 fclose(fichier);
19 }
20
21 return(0);
22 }
fseek : prend comme paramètre le FILE* ainsi que deux entiers n1 et n2 : le paramètre n1 indique le
nombre de caractère dont on va se déplacer et le caractère n2 indique d’où commence ce déplacement.
Quelque mot clef :
SEEK_CUR donne la position actuelle.
SEEK_END indique la fin du fichier.
Par exemple
1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int main () {
5
6 FILE *fichier=NULL;
7
8 fichier=fopen("[Link]","r+");
9
10 if(fichier != NULL) {
11
12 fseek(fichier,0,3); /*on se place sur le troisième caractère*/
13 printf("A la position %d il y a le caractere %c\n",
14 ftell(fichier),fgetc(fichier));
15
16 fseek(fichier,0,1); /*on se place sur le premier caractère*/
17 printf("A la premiere position il y a le caractere %c\n",
18 fgetc(fichier));
19
20 fseek(fichier,-1,SEEK_END); /*on se place à l’avant derniere position*/
21 printf("L’avant dernier caractere est %c a la position %d\n",
22 fgetc(fichier),ftell(fichier));
23
24 fclose(fichier);
25 }
26
27 return(0);
28 }

34
12 Le #define

Commençons par parler des directives préprocesseur : le préprocesseur est un programme qui s’exécute
juste avant la compilation ; on parle d’ailleurs de pré-compilation. C’est une phase pendant laquelle le pré-
processeur va ajouter, supprimer, remplacer certaines chaînes de texte dans le programme selon des directives
à interpréter. Ces directives de préprocesseur ont la caractéristique suivante : elles commencent toujours par
le symbole #. Celle que nous connaissons c’est la directive #include qui va recopier au début du programme
tout ce que contient la bibliothèque passée en paramètre.
Une autre directive préprocesseur très utile est le #define. Comme toute directive préprocesseur, on le
place au début du programme :

#define TAILLE_MAX_MOT 1000

Lorsque le pré-compilateur va lire cette ligne, il va rechercher dans tout le programme la chaine de caractère
TAILLE_MAX_MOT et il va la remplacer par la valeur 1000. L’un des interet majeur de cette commande est
que l’on peut l’utiliser pour définir la taille de tableau :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 #define TAILLE 100
5
6 int main () {
7
8 char mot[TAILLE]="";
9
10 /* blabla */
11
12 return(0);
13 }

A noter qu’il ne s’agit pas d’une commande mais d’une directive, en d’autre terme : il n’y a pas de point-
virgule à la fin du #define. Ce qu’il faut retenir c’est que le #define Expression1 Expression2 va
remplacer Expression1 par Expression2 ; il agit comme une chercher/remplacer. On peut même mettre
des expressions plus technique, comme par exemple :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 #define Operation 1+3*2
5 #define Bonjour printf("Hello !\n");
6
7 int main(){
8
9 Bonjour
10
11 printf("Le resultat est : %d\n",Operation);
12 printf("Le double de ce nombre est : %d\n",2*Operation);
13 printf("Qui est different de : %d\n",Operation*2);
14 printf("Lui meme different de : %d",2*(Operation));
15
16 return(0);
17 }

35
Hello !
Le resultat est 7
Le double de ce nombre est 8
Qui est different de 13
Lui meme different de 14
Ici on a mis un point virgule à la fin du second #define car le mot Bonjour est remplacé par la commande
(qui finit nécessairement par un point-virgule) printf("Bonjour !\n");.
On peut se servir du #define comme d’une fonction. On parle alors de MACRO.

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 #define Majeur(age) if(age>=18){ \
5 printf("Vous etes majeur : allez voter !"); \
6 } \
7 else { \
8 printf("Desole. Vous regarderez les elections a la TV.")\
9 } \
10
11 #define Bonjour() printf("Hello ! Entrez votre age : \n")
12
13 int main(){
14
15 int age;
16
17 Bonjour();
18 scanf("%d",&age);
19 Majeur(age)
20
21 return(0);
22 }

Noter l’antislash permettant de sauter une ligne dans l’expression du #define. On également put mettre
plusieurs paramètres.

36
13 En-tête du programme : prototypes et structures

Les prototypes. Comme nous l’avons vu, il faut déclarer les fonctions avant la fonction principale main. La
raison est purement logique : si on fait appel à une fonction que le compilateur ne connaˆpas, c’est à dire qu’il
n’a pas encore lu, il ne sera pas quoi faire. Jusqu’ici nous avons manipulé des exemples pas trop technique,
mais le langage C peut être utilisé pour faire des programmes vraiment compliqués (mais très jolie comme la
programmation de jeu comme Zelda, Final Fantasy...) qui nécessitent un nombre considérable de fonctions
qui peuvent faire appelles à d’autres fonctions qui font elles même appelles à des fonctions etc. Et dans de
tel cas on n’échappe pas à la règle : il faut d’abord définir avant d’utiliser ! Il faut donc ordonner les fonctions
dans un ordre bien précis. Comme on le devine cela peut s’avérer (très) difficile. Les prototypes permettent
de palier à cette difficulté. On indique au compilateur que quelque part dans le programme telle fonction est
définie et que s’il ne l’a pas encore lu, il suffit d’aller voir plus loin. On fait comme ceci

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int quadruple(int);
5 int triple(int);
6 int doublee(int);
7 int prod(int, int);
8
9 int main (){
10
11 int n=0;
12
13 printf("Entrez un entier : ")
14 scanf("%d",&n);
15 printf("Le double de %d est %d, son triple est %d et son quadruple est %d",
16 n,doublee(n), triple(n), quadruple(n));
17 }
18
19 int quadruple(int x){
20 return(doublee(doublee(x)));
21 }
22 int triple(int y){
23 return(prod(3,y));
24 }
25 int doublee(int z){
26 return(z+z);
27 }
28 int prod(int a, int b){
29 return(a*b);
30 }

Variables globales. Comme nous l’avons déjà vus, les variables définies dans une fonction ne "vivent" que
dans cette fonction. On dis qu’elles sont locales à la fonction. A cela s’oppose bien sur les variables dites
globales. Il suffit de les définir comme des prototypes. Voici un exemple

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 int var_global=0;
5
6 int carre1(int n);

37
7 void carre2(void);
8
9 int main() {
10
11 printf("Entrez un entier : ");
12 scanf("%d",&var_global);
13
14 printf("%d au carre = %d, mais var_global vaut toujours %d\n",
15 var_global,carre1(var_global), var_global);
16 carre2();
17 printf("Maintenant var_global vaut %d",var_global);
18
19 return(0);
20 }
21
22 int carre1(int n){
23 return(n*n);
24 }
25 void carre2(){
26 var_global=var_global*var_global;
27 }

Entrez un entier : 4
4 au carre = 16, mais var_global vaut toujours 4
Maintenant var_global vaut 16

Structures et enumerations. Le langage C permet de créer ses propres type de variables. On peut en
construire de deux façons : les structures et les énumérations.
Pour les énumérations sont des listes de valeurs possible pour une variable. On définit ces types avant le
main (c’est à dire avant de les utiliser) de cette manière

enum nom_du_type {
valeur1, valeur2, valeur3, ..., valeurn
};

Attention : ne pas oublier le point virgule à la fin.


Dans le main, lorsque l’on veut une variable de ce nouveau type, on écris simplement

enum nom_du_type nom_variable;

Voici un exemple :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 enum couleur {
5 RED, GREEN, BLUE
6 };
7
8 int main(){
9
10 enum couleur x=RED;
11
12 switch(x){
13 case(RED) :
14 printf("La couleur est rouge");

38
15 break ;
16 case(GREEN) :
17 printf("La couleur est rouge");
18 break ;
19 case(BLUE) :
20 printf("La couleur est rouge");
21 break ;
22 default :
23 printf("Jamais vu une telle couleur");
24 }
25
26 return(0);
27 }

En fait lorsque l’on fait un enum, la machine va associer à chaque valeur un entier. Ainsi dans l’exemple
précédent, RED correspond au nombre 0, GREEN au nombre 1 et BLUE au nombre 2. On peut également
indiquer la valeur à donner à chaque éléments en faisant par exemple

4 enum couleur {
5 RED=-1, GREEN=0, BLUE=1
6 };

On peut simplifier le enum couleur x=RED; dans le main. En effet on a crée un nouveau type que l’on a
appelé couleur. On aimerais écrire simplement couleur x=RED; sans avoir à préciser qu’il s’agit d’un enum.
Pour cela on utilise la commande typedef pour indiquer à la machine que l’on définis un nouveau type.
On rajouterai donc à la ligne 3 la commande typedef enum couleur couleur;. La commande typedef
permet de renommer les types. Pour s’amuser (sic !), on pourrait mettre par exemple : typedef int entier;
pour renommer les int en entier.
Voyons à présent les structures. Elles permettent de définir des types composés de sous-types.

struct nom_du_type {
type1 variable1;
type2 variable2;
.
.
.
typen variablen;
};

Comme pour enum, ne pas oublier le point-virgule après l’incollade fermante ; de même la déclaration d’une
telle variable dans le main se fait par

struct nom_du_type nom_variable;

Pour faire appel à un champ de la variable souhaité, on utilise le point : nom_variable.variable1. Un


exemple s’impose :

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 typedef struct point_du_plan POINT;
5 struct point_du_plan {
6 double x;
7 double y;
8 };
9
10 int main() {

39
11
12 POINT P;
13
14 printf("Entrer l’abscisse : ");
15 scanf("%lf",&P.x);
16 printf("Entrer l’ordonne : ");
17 scanf("%lf",&P.y);
18
19 printf("Il s’agit du point de coordonne (%lf,%lf)",P.x,P.y);
20
21 return(0);
22 }

On peut bien sur mettre des tableaux ou des pointeurs (en fait c’est la même chose).

1 #include<stdlib.h>
2 #include<stdio.h>
3
4 #define TAILLE_MAX 1000
5
6 typedef enum sexe sexe;
7 enum sexe {
8 GARCON, FILLE
9 };
10
11 typedef struct etudiant etudiant;
12 struct etudiant{
13 char nom[TAILLE_MAX];
14 char prenom[TAILLE_MAX];
15 int age;
16 sexe x;
17 };
18
19 void init_etudiant(etudiant*);
20 void aff_etudiant(etudiant*);
21
22 int main() {
23
24 etudiant major[2];
25
26 init_etudiant(&(major[0]));
27 init_etudiant(&(major[1]));
28
29 printf("Cette annee le major de promo est %s, age de seulement %d ans.
30 F\’elicitation !\n",major[0].prenom,major[0].age);
31
32 if(major[1].x==GARCON){
33 printf("Le second de la promo est monsieur %s.
34 Quel nul !\n",major[1].nom);
35 }
36 else{
37 printf("La seconde de la promo est %c. %s.
38 Quelle nulle !\n",(major[1].prenom)[0],major[1].nom);
39 }
40
41 return(0);

40
42 }
43
44 void init_etudiant(etudiant *E){
45
46 printf("\t\t.:INITIALISATION:.\n\n");
47
48 printf("Prenom de l’etudiant : ");
49 scanf("%s",&(*E).prenom);
50 printf("Nom de l’etudiant : ");
51 scanf("%s",&(*E).nom);
52 printf("Age de l’etudiant : ");
53 scanf("%d",&(*E).age);
54 printf("Tapez 1 s’il l’\’etudiant est une fille, 0 sinon : ");
55 scanf("%d",&(*E).x);
56
57 printf("\n\n");
58 aff_etudiant(E);
59
60 }
61
62 void aff_etudiant(etudiant* E){
63
64 printf("\t\t.:RECAPITULATIF:.\n\n");
65
66 printf("Prenom : %s\n",(*E).prenom);
67 printf("Nom : %s\n",(*E).nom);
68 printf("Age : %d\n",(*E).age);
69
70 printf("\n\n");
71 }

41

Vous aimerez peut-être aussi