Académique Documents
Professionnel Documents
Culture Documents
Semestre 3
Filières : TIG / ISI
SUPPORT DE COURS
LANGAGE C
MODULE 1
Une première définition de ce langage est apparue en 1978 avec l’ouvrage de Kernighan et
Ritchie The C programming language. Mais ce langage a continué d’évoluer après cette
date à travers les différents compilateurs qui ont vu le jour. Son succès international a
contribué à sa normalisation, d’abord par l’ANSI (American National Standard Institute), puis
par l’ISO (International Standards Organization), plus récemment en 1993 par le CEN
(Comité européen de normalisation) et enfin, en 1994, par l’AFNOR. En fait, et fort
heureusement, toutes ces normes sont identiques, et l’usage veut qu’on parle de « C ANSI
» ou de « C norme ANSI ».
A la même époque (1983), Bjarne Stroustrup créa sa première version du langage C++.
Celui-ci est une extension du langage C afin de permettre la programmation orientée objets.
Plus tard, dans les années 95, Java prendra place parmi la grande lignée des langages
dérivés de C. Quoi qu'il en soit, C (voir C++) reste à l'heure actuelle, le langage
incontournable dans les domaines ou les performances (et les temps de réponses) sont de
mises.
Présentation
Un programme C est un ensemble d’instructions qui se saisit dans un fichier .c à l’aide d’un
éditeur (ex. : Notepad), ce type de fichier s’appelle une source. Les instructions qui y sont
écrites s’appellent du code ou encore le code source. Un compilateur est un logiciel qui lit
le code source et le convertit en un code exécutable, c’est-à-dire un ensemble d’instructions
compréhensible par le processeur. La compilation d’une source se fait en deux étapes : la
compilation proprement dite et le linkage. On utilise en général le terme compilation en
englobant les deux étapes précédemment citées.
–La compilation à proprement parler produit un fichier objet, dont l’extension est .obj.
– Les sources peuvent être réparties dans plusieurs fichiers, ceux-ci doivent tous ˆêtre
compiles s´séparément.
Ensuite, le linkage des différents fichiers objets est assemblage produisant un
exécutable .exe.
2
présuppose qu'un environnement d'exécution soit installé sur le poste pour interpréter les
différentes instructions du langage et les exécuter : ces langages ne permettent pas de
produire des exécutables très efficace (efficace certes, mais pas les plus efficaces). Au
contraire, les langages compilés (C, C++, ...) garantissent les meilleures performances étant
donné que le code source est traduit une fois pour toute (avant la première exécution) en
langage machine. Pour rappel, le langage machine est le seul langage qui puisse être
directement exécuté par votre processeur. Ainsi, les langages compilés évitent les étapes
de traduction du code durant l'exécution (l'interprétation).
Un compilateur est un outil qui permet donc la transformation d'un code source en langage
machine. Le langage C nécessite donc un compilateur pour traduire, une fois pour toute,
votre code source C. Il existe plusieurs compilateurs C, en fonction du système d'exploitation
utilisé et des sociétés d'édition logiciel retenues. Voici une description de quelques
compilateurs C.
Le compilateur gcc est développé sur les différentes plates-formes Linux/Unix. Il est connu
pour relativement bien supporter les différentes versions du standard ISO du langage C. Il
produit des exécutables efficaces. Il est considéré comme une référence en termes de
compilateur C. De plus, il permet de faire de la « cross-compilation » : cela permet de
travailler sur une plate-forme et d'y produire un exécutable pour une autre plate-forme.
L'ensemble des options proposées par MinGW restent les mêmes que celles de gcc. Il en
résulte que les informations proposées tout au long de ce cours pour compiler vos
programmes s'appliquent donc parfaitement à MinGW. Il est intégré dans Code::Blocks.
Remarque : c’est l’éditeur Code ::Blocks que nous considérerons pour la compilation des
exemples de code tout au long de notre cours.
Clang
Ce compilateur est une alternative à gcc. Le site officiel de Clang est disponible à l'adresse
Internet suivante : http://clang.llvm.org. Il est notamment utilisé sur les plates-formes Mac,
mais peut aussi être utilisé sur d'autres plates-formes. Il permet aussi la cross-compilation.
Visual C++
Le terme « Visual C++ » est utilisé pour qualifier l'ensemble des outils liés au développement
C++ sous l'environnement Visual Studio de la société Microsoft. Dans cet ensemble d'outils,
vous trouverez notamment le compilateur C++ de la société Microsoft. Ce dernier est très
performant et supporte relativement bien les derniers standards du langage C. Sur
environnement Windows, il est donc en concurrence avec le compilateur MinGW.
3
Présentation de Code ::Block
Téléchargement de Code::Blocks
Comme indiqué plus faut, nous allons utiliser l' IDE CODE::BLOCKS.
Il est en anglais mais nous irons rarement scruter les menus. Je l'ai choisi car il permet de
programmer en C et en C++.
De plus, c'est un IDE libre (open source) il peut donc être développé par n'importe qui, il
est gratuit, et ce que vous produisez avec vous appartient.
codeblocks-x.xx-setup.exe
codeblocks-x.xx.mingw-setup.exe
Sans rentrer dans les détails, c'est pour se faciliter la vie, par exemple si vous
utilisez Console application, Code::Blocks va vous préparer le terrain et vous pourrez
programmer en console.
4
Oui, pour l'instant nous allons nous contenter de la console Windows...
Nous allons travailler sur cette console pendant un bon bout de temps et après vous
pourrez approfondir et passer à la programmation en fenêtre si ça vous tente. Vous
verrez qu'on peut créer des jeux avec cette console.
5
Code::Blocks nous demande notre langage, sélectionnez le C.
Ensuite, sélectionnez le compilateur que vous voulez utiliser, ici, c'est GNU GCC
Compiler qui nous intéresse puisqu'il est capable de compiler le C.
GCC est l'abréviation de GNU Compiler Collection (c'est le compilateur créé par le
projet GNU).
Il s'agit en réalité d'une collection de logiciels libres intégrés capables de compiler divers
langages de programmation comme le C et le C++. Dire que GCC est un compilateur est
donc un abus de langage adopté par la plupart des programmeurs.
6
Il faut aussi choisir une configuration de compilation...
Debug, si vous voulez faire une recherche poussée de vos erreurs (on ne le fera jamais
donc un peu inutile). Ce mode alourdi l'exécutable puisqu'il conserve toutes les
informations pour débugger, mais la compilation est plus rapide.
Et Release, si vous voulez optimiser votre programme au maximum pour qu'il puisse
être transporté de machine en machine.
En effet, pour partager un programme à vos amis, il faut compiler en Release et non pas
en Debug.
Il est mieux de compiler en Debug pour tester votre programme mais une fois ce
dernier terminé, il faut le compiler en Release pour pouvoir le partager.
Maintenant nous allons faire une vérification pour voir si vous avez bien
votre compilateur prêt à l’emploi.
7
Bien sûr, avec un PC en 64 bits, l'autodection aurait fonctionnée. Mais si c'est trop
facile, ce n’est pas drôle.
Maintenant, à gauche dans l'onglet Projects, cliquez sur main.c dans l'arborescence de
votre projet.
Du code source doit s'afficher à droite. C'est le contenu du fichier main.c que vous
pouvez maintenant éditer !
8
Regardez ces boutons importants :
Build permet de compiler (presque) tous les fichiers source de votre projet afin de créer
un exécutable.
S'il y a des erreurs lors de la compilation (ça arrive vite ça), la petite fenêtre tout en bas Build
messages vous informera des erreurs et affichera (dans le meilleur des cas) un carré
rouge au début d'une ligne dans votre code source (on en reparlera un peu plus loin).
A droite de ces boutons, vous voyez Build target, c'est ici que vous devez choisir votre
mode de compilation, comme je veux compiler rapidement et que je n'ai pas envie de
transporter mon programme, j'utilise Debug.
Appuyez sur F9 pour faire un Build and run et admirez le résultat du code source par
défaut (le code source minimal) :
Ne vous occupez pas des deux dernières lignes, ce sont juste des informations générées
par Code::Blocks, elle n'apparaissent pas si vous lancez votre exécutable depuis
l'explorateur Windows.
9
Donc du coup, le programme ne se met pas en pause et vous ne pouvez pas lire ce qu'il
affiche.
On réglera ça dans le prochain chapitre, allons voir notre dossier de notre projet...
Les fichiers *.C sont les fichiers que vous avez écrits à la main en C via votre IDE.
Je prends comme exemple main.c.
Les fichiers dans le dossier obj portant l'extension *.O (ou *.OBJ) peuvent être
supprimés, ce sont des fichiers temporaires.
En effet, l'utilité du fichier *.O n'est pas compréhensible pour le moment, mais il ne va
pas tarder à l'être.
10
CHAPITRE
NOTION DE BASE
1
Pour n'importe quel programme, il faudra taper un minimum de code. Ce code ne fera rien
de particulier, mais il est indispensable.
C'est ce "code minimum" que nous allons découvrir maintenant. Il devrait servir de base
pour la plupart de vos programmes en langage C.
Pour rappel, sous Code::Blocks (qui est l'IDE que je vais utiliser tout au long de ce cours),
il faut aller dans le menu File / New / Project, puis choisir Console
Application et sélectionner le langage C.
Les 2 écritures sont possibles, mais la seconde (la compliquée) est la plus courante. J'aurai
donc tendance à utiliser plutôt cette dernière dans les prochains chapitres. En ce qui nous
concerne, que l'on utilise l'une ou l'autre des écritures, ça ne changera rien pour nous.
11
Traduit en C, cela devient :
#include <stdio.h>
main()
{
printf("hello world\n");
return 0;
}
On approfondira les composantes de ce programme dans la suite du chapitre...
Le type d'une fonction qui ne fournit pas de résultat (comme les procédures en langage
algorithmique ou en Pascal), est déclaré comme void (vide).
12
Paramètres d'une fonction
La définition des paramètres (arguments) d'une fonction est placée entre parenthèses ()
derrière le nom de la fonction.
Si une fonction n'a pas besoin de paramètres, les parenthèses restent vides ou
contiennent le mot void.
La fonction minimale qui ne fait rien et qui ne fournit aucun résultat est alors:
void dummy()
{
}
Instructions
En C, toute instruction simple est terminée par un point-virgule ; (même si elle se trouve
en dernière position dans un bloc d'instructions). Par exemple: printf("hello, world\n");
b. La fonction "main"
La fonction main est la fonction principale des programmes en C :
Elle se trouve obligatoirement dans tous les programmes.
L'exécution d'un programme entraîne automatiquement l'appel de la fonction main.
Dans les premiers chapitres, nous allons simplement "traduire" la structure programme du
langage algorithmique par une définition équivalente de la fonction main :
Paramètres de main
- Si la liste des paramètres de la fonction main est vide, il est d'usage de la déclarer par ().
- Si nous utilisons des fonctions prédéfinies (par exemple : printf), il faut faire précéder la
définition de main par les instructions #include correspondantes (soit inclure la librairie qui
contient la fonction désirée).
Remarque avancée :
Il est possible de faire passer des arguments de la ligne de commande à un programme.
Dans ce cas, la liste des paramètres doit contenir les déclarations correspondantes.
13
Dans notre cours, nous n'allons pas utiliser des arguments de la ligne de commande.
Ainsi la liste des paramètres de la fonction main sera vide (void) dans tous nos exemples
et nous pourrons employer la déclaration suivante qui fait usage des valeurs par défaut :
main()
{
}
c. Les variables
Les variables contiennent les valeurs qui sont utilisées pendant l'exécution du
programme.
Les noms des variables sont des identificateurs quelconques.
Les différents types de variables simples et les opérateurs admissibles sont discutés au
chapitre 3.
d. Les identificateurs
Les noms des fonctions et des variables en C sont composés d'une suite de lettres et de
chiffres.
Le premier caractère doit être une lettre.
Le symbole '_' est aussi considéré comme une lettre.
* L'ensemble des symboles utilisables est donc: {0,1,2,...,9,A,B,...,Z,_,a,b,...,z}
* Le premier caractère doit être une lettre (ou le symbole '_')
* C distingue les majuscules et les minuscules, ainsi: "Nom_de_variable" est différent de
"nom_de_variable"
* La longueur des identificateurs n'est pas limitée, mais C distingue 'seulement' les 31
premiers caractères.
Remarques :- Il est déconseillé d'utiliser le symbole '_' comme premier caractère pour un
identificateur, car il est souvent employé pour définir les variables globales de
l'environnement C.
Le standard dit que la validité de noms externes (par exemple : noms de fonctions ou
variables globales) peut être limité à 6 caractères (même sans tenir compte des majuscules
et minuscules) par l'implémentation du compilateur, mais tous les compilateurs modernes
14
distinguent au moins 31 caractères de façon que nous pouvons généraliser qu'en pratique
les règles ci-dessus s'appliquent à tous les identificateurs.
Exemple :
Identificateurs corrects : nom1 / nom_2 / _nom_3 / Nom_De_Variable
Identificateurs incorrects : 1nom / nom.2 / -nom-3 / Nom De Variable
e. Les commentaires
Un commentaire commence toujours par les deux symboles "/*" et se termine par les
symboles "*/".
Il est interdit d'utiliser des commentaires imbriqués.
Exemples :
/* Ceci est un commentaire */
Discussion :
- La fonction main ne reçoit pas de données, donc la liste des paramètres est vide.
- La fonction main fournit un code d'erreur numérique à l'environnement, donc le type du
résultat est int et n'a pas besoin d'être déclaré explicitement.
- Le programme ne contient pas de variables, donc le bloc de déclarations est vide.
- La fonction main contient deux instructions :
- L'argument de la fonction printf est une chaîne de caractères indiquée entre les guillemets.
Une telle suite de caractères est appelée chaîne de caractères constante (string constant).
- La suite de symboles "\n" à la fin de la chaîne de caractères "hello, world\n" est la notation
C pour passer à la ligne (angl: new line). En C, il existe plusieurs couples de symboles qui
contrôlent l'affichage ou l'impression de texte.
15
\0 - NULL
\a - sonnerie
\\ - trait oblique
\' - apostrophe
\? - point d'interrogation
\f - saut de page (imprimante)
Le fichier "STDIO.H" contient les informations nécessaires pour pouvoir utiliser les
fonctions de la bibliothèque standard.
16
CHAPITRE
TYPE ET OPERATEURS
2
Introduction
Les variables et les constantes sont les données principales qui peuvent être manipulées
par un programme. Les déclarations introduisent les variables qui sont utilisées, fixent leur
type et parfois aussi leur valeur de départ. Les opérateurs contrôlent les actions que
subissent les valeurs des données. Pour produire de nouvelles valeurs, les variables et les
constantes peuvent être combinées à l'aide des opérateurs dans des expressions.
Le type d'une donnée détermine l'ensemble des valeurs admissibles, le nombre d'octets à
réserver en mémoire et l'ensemble des opérateurs qui peuvent y être appliqués.
Motivation
La grande flexibilité de C nous permet d'utiliser des opérandes de différents types dans un
même calcul.
Cet avantage peut se transformer dans un terrible piège si nous ne prévoyons pas
correctement les effets secondaires d'une telle opération (conversions de type
automatiques, arrondissements, etc.).
Une étude minutieuse de ce chapitre peut donc aider à éviter des phénomènes parfois
"inexplicables"...
Oui, et il existe encore de nombreux types en langage C, j'ai conservé ici les principaux
17
Remarquez, les types précédés du terme unsigned n'ont pas de signe, on dit qu'ils sont non
signés mais peuvent donc stocker plus de nombres positifs (2 fois plus que le type
signé).
Pourquoi avoir créé plein de types ? Le type double n'aurait pas suffit ?
Oui, il aurait suffi mais je n'appelle pas ça économiser de la mémoire (c'est un peu le but),
effectivement, un double occupera plus de place en mémoire qu'un char.
Je vous présente les types de variables que nous allons utiliser le plus souvent dans ce
cours.
char qui permet de stocker des lettres, en effet, il existe la table ASCII qui convertit
des nombres en lettres.
Par exemple, le nombre 65 correspond à la lettre A, 66 à la lettre B...
Le type char est donc utilisé 99% des cas pour stocker une lettre (oui, une seule
lettre).
int qui permet de stocker des nombres entiers, le type long aurait été aussi bien, il
faut bien faire un choix.
Il y a quelques années, le type long comportait quelques différences avec le type int,
pour des raisons de compatibilité, il a été conservé. Le type int est agréable à utiliser,
on s'en sert pour stocker tous les nombres entiers (même 0 et 1).
Vous aurez peut-être l'impression de gâcher de la mémoire, mais ce n'est
vraiment pas ce qui manque sur un ordinateur.
double qui permet de stocker des nombres décimaux, donc avec une virgule.
Attention, en programmation, la virgule est représentée par un point (.).
Comme pour le int, on s'en servira pour stocker tous les nombres décimaux.
Voilà en résumé les types que nous allons utiliser le plus souvent, avec ces 3 types on
peut faire des merveilles.
Nous allons maintenant programmer un peu !
Déclaration de variables en C
<Type> <NomVar1>, <NomVar2>, ...
... en gros, il s'agit de la même architecture... (C’était vraiment très intéressant, merci, au
revoir...) ;)
Par exemple,
en algorithmique, on a : traduit en C, cela devient :
entier n1 , n2 int n1 , n2 ;
réel r1 , r2 float r1 ;
caractère c1 double r2 ;
boolléen b1 char c1 ;
char b1 ;
18
Remarques
r1 est passé du type algo réel à float en C, alors que r2 est passé de réel à double.
Cela s'explique par le fait qu'on a choisi de coder r1 sur seulement 4 octets, et r2 sur
8 octets (on aurait donc besoin de pouvoir monter plus haut en valeur avec r2 qu'avec
r1...).
le type algorithmique "booléen" (VRAI / FAUX) n'existe pas en C, on utilise alors un
type numérique (int ou char, qui se code sur moins d'octets) pour le représenter.
VRAI devient alors la valeur numérique 1, et FAUX devient 0.
le type algorithmique "chaines de caractères" n'existe pas non plus, on utilise des
tableaux de caractères... mais on étudiera cela plus loin.
3. Initialisation de variables
Pour rendre notre programme plus propre et aux normes, il est préférable d'initialiser la
variable dès sa déclaration, elle n'aura même pas le temps de prendre une
valeur hasardeuse.
Exemples :
int MAX=1023;
char TAB="\t";
float X=1.05e-4;
int main()
{
int maVariable = 5;
printf("maVariable = %d", maVariable);
return 0;
}
4. Les constantes
Le mot clé const permet la déclaration des constantes.
En utilisant l'attribut const, nous pouvons indiquer que la valeur d'une variable ne change pas
au cours d'un programme. Il suffit d'ajouter le mot clé const devant le type de la variable lors
de la déclaration pour rendre la variable constante (sa valeur ne peut pas être modifiée).
Exemples :
const int MAX=767;
const double e=2.71828182845905;
const char NEWLINE="\n";
int main()
{
const int MA_CONSTANTE;
maConstante = 5;
printf("MA_CONSTANTE = %d", MA_CONSTANTE);
return 0;
}
Ici, j'ai changé le type d'écriture du nom de la variable, j'utilise les majuscules et
un underscore (_), prenez l'habitude de déclarer vos constantes avec des majuscules,
le code source sera par la suite plus clair.
Le compilateur nous sort une erreur nous demandant pourquoi on essaie de modifier la
valeur d'une constante (logique).
19
La variable MA_CONSTANTE comporte une valeur dès sa déclaration (qui peut être
n'importe quoi), il faut donc l'initialiser dès sa déclaration pour lui assigner une valeur de
notre choix.
5. Les opérateurs
a. Les opérateurs arithmétiques
Les opérateurs de calcul arithmétiques permettent d'effectuer des opérations
mathématiques entre deux valeurs et seulement deux valeurs. Ils sont très simples à utiliser,
c'est comme les mathématiques à l’école.
Opérateurs Descriptions Exemples
int maVariable = 5 + 12;
+ addition
/* maVariable vaut 17 */
- int maVariable = 5 - 12;
soustraction
/* maVariable vaut -7 */
int maVariable = 3 * 4;
* multiplication
/* maVariable vaut 12 */
division int maVariable = 12 / 3;
/
/* maVariable vaut 4 */
int maVariable = 20 % 3;
%
Modulo (reste de la division entière) /* maVariable vaut 2
(car 20 = 3 * 6 + 2) */
b. Opérateurs d'Accumulation
Pour chacun des opérateurs de calcul, il existe un opérateur
d'accumulation permettant d'alléger l'écriture en évitant les opérations de la
forme maVariable = maVariable + 2.
+=
addition i += 5;
/* i vaut 9 */
++ incrémentation unitaire
i++;
/* i vaut 5 */
-= soustraction
i -= 3;
/* i vaut 1 */
-- décrémentation unitaire
i--;
/* i vaut 3 */
*= multiplication
i *= 4;
/* i vaut 16 */
20
/= division
i /= 2;
/* i vaut 2 */
i %= 3;
%= modulo /* i vaut 1
(car 4 = 3 * 1 + 1) */
Nota :
X = I++ passe d'abord la valeur de I à X et incrémente après
X = I-- passe d'abord la valeur de I à X et décrémente après
X = ++I incrémente d'abord et passe la valeur incrémentée à X
X = --I décrémente d'abord et passe la valeur décrémentée à X
c. Opérateurs Relationnels
Le résultat d'une opération relationnelle est une valeur booléenne.
Un booléen est une variable auquel on fait prendre les valeurs 0 et 1 (0 pour faux et 1 pour
vrai).
En réalité, toutes les valeurs différentes de 0 valent vrai mais on va éviter de compliquer les
choses.
En C, il n'y a pas de type consacré aux booléens, on utilisera donc un int qui peut prendre les
valeurs 0 et 1 pour simuler un booléen.
!= différent
int monBooleen = 3 != 4;
/* monBooleen vaut 1 */
> supérieur
int monBooleen = 5 > 5;
/* monBooleen vaut 0 */
< inférieur
int monBooleen = 4 < 5;
/* monBooleen vaut 1 */
Avec les exemples du tableau, vous devez avoir compris pas mal de choses.
Voici un code source que j'ai écrit pour tester si l'utilisateur du programme est majeur.
21
int main()
{
int age = 0, majeur = 0;
return 0;
}
Cet exemple beaucoup plus concret nous affiche l'âge de l'utilisateur et la valeur du
booléen majeur (vaut 0 si age est inférieur à 18 et vaut 1 sinon).
Quel age avez-vous ? 43
age = 43
majeur = 1
d. Opérateurs Logiques
Une opération logique est une opération booléenne qui renvoie une valeur booléenne.
Sans plus attendre, le tableau !
|| ou
int monBooleen = 0 || 0;
/* monBooleen vaut 0 */
! non
int monBooleen = !0;
/* monBooleen vaut 1 */
a = !b : a vaut 1 si b vaut 0.
Si b vaut 0, a vaut 1.
22
Un exemple pour bien comprendre, on demande à l'utilisateur une boisson et une viande.
int main()
{
int boisson = 0, viande = 0, obese = 0;
return 0;
}
C'est un peu compliqué mais avouez que c'est terriblement logique non ?
Si on a choisi le Soda (choix 2) et le Hamburger (choix 1) bien on est obèse, le booléen
obese vaut 1 (est vrai).
Que voulez-vous boire ?
1. Eau
2. Soda
1. Hamburger
2. Porc
obese = 1
Je le reconnais, ce n'est pas une partie de plaisir, vous verrez dans le prochain chapitre que
tout cela a un sens incroyable (oui je vous jure).
Retenez juste les descriptions de ces opérateurs, notez qu'ils s'utilisent fréquemment avec
les opérateurs relationnels et ce sera suffisant pour le moment.
Exemples :
i=0
23
i++
X = pow(A,4)
printf(" Bonjour !\n")
a = (5*x+10*y)*2
(a+b) >= 100
position != limite
b. Instructions
Une expression comme I=0 ou I++ ou printf(...) devient une instruction, si elle est suivie
d'un point-virgule.
Exemples :
i=0;
i++;
X=pow(A,4);
printf(" Bonjour !\n");
a=(5*x+10*y)*2;
c. Evaluation et résultats
En C toutes les expressions sont évaluées et retournent une valeur comme résultat :
(3+2==5) retourne la valeur 1 (VRAI)
A=5+3 retourne la valeur 8
Comme les affectations sont aussi interprétées comme des expressions, il est possible de
profiter de la valeur rendue par l'affectation :
((A=sin(X)) == 0.5)
24
choisirait la conversion automatique ; dans ce cas, nous devons forcer la conversion à l'aide
d'un opérateur spécial (cast).
Ces manipulations implicites convertissent en général des types plus "petits" en des types
plus "larges" ; de cette façon on ne perd pas en précision.
Lors d'une affectation, la donnée à droite du signe d'égalité est convertie dans le type à
gauche du signe d'égalité.
Dans ce cas, il peut y avoir perte de précision si le type de la destination est plus faible
que celui de la source.
25
int n = Nom_Variable;
}
Le compilateur remplace limit par 12 partout dans le programme. Il n'est pas nécessaire
de mettre un ; à la fin de la définition d'une constante.
b. Les macros
Une macro est une fonction à paramètre qui renvoie le résultat de l'opération logique à
effectuer sur ces paramètres.
Les macros à paramètres sont surtout utiles dans C, car dans C++ on peut définir du code
"en ligne" qui joue presque le même rôle, mais est mieux testé par le compilateur.
Dans l'exemple ci-dessous, une macro est définie puis utilisée.
#define DoubleByte(a,b) ((a<<8) | (b&255))
int i = DoubleByte(12,200);
26
CHAPITRE
LES ENTRÉES/SORTIE
3
Introduction
La bibliothèque standard <stdio.h> contient un ensemble de fonctions qui assurent la
communication de la machine avec le monde extérieur.
Utilisation :
printf("<format>" , <Expression1> , <Expression2> ...)
La partie <format> peut contenir :
- du texte
- des séquences d'échappement
- des spécificateurs de format (indiquent la manière dont les valeurs des expressions sont
imprimées)
Remarques :
Il doit toujours y avoir un spécificateur de format pour chaque expression, il commence
toujours par % et se termine par un ou deux caractères qui indiquent le format d'impression.
Exemple :
int A = 1234;
int B = 567;
printf("%i fois %i est %li \n", A, B, (long) A*B);
On a alors à l'écran:
1234 fois 567 est 699678
Les différents spécificateurs de format pour printf
%d ou %i int entier relatif
%u int entier naturel (unsigned)
%o int entier exprimé en octal
%x int entier exprimé en hexadécimal
%c int caractère
%f double rationnel en notation décimale
%e double rationnel en notation scientifique
%s char* chaîne de caractères
%f float rationnel
%e float rationnel représenté par sa forme : +/- <Mantisee> * 10 ^ <Exposant>
Remarque : Pour pouvoir traiter correctement les arguments du type long, il faut utiliser
les spécificateurs %ld, %li, %lu, %lo, %lx, %lf, %le.
27
Largeur minimale pour les entiers
Pour les entiers, nous pouvons indiquer la largeur minimale de la valeur à afficher.
Dans le champ ainsi réservé, les nombres sont justifiés à droite.
Exemples : (_ représente un espace vide)
printf("%4d", 123);
==> _123
printf("%4d", 1234);
==> 1234
printf("%4d", 12345);
==> 12345
printf("%4u", 0);
==> ___0
printf("%4X", 123);
==> __7B
printf("%4x", 123);
==> __7b
Exemples :
printf("%f", 100.123);
==> 100.123000
printf("%12f", 100.123);
==> __100.123000
printf("%.2f", 100.123);
==> 100.12
printf("%5.0f", 100.123);
==> __100
printf("%10.3f", 100.123);
==> ___100.123
printf("%.4f", 1.23456);
==> 1.2346
28
Exemple :
int JOUR, MOIS, ANNEE;
scanf("%i %i %i", &JOUR, &MOIS, &ANNEE);
Les différents spécificateurs de format pour scanf
%d ou %i int entier relatif
%u int entier naturel (unsigned)
%o int entier exprimé en octal
%x int entier exprimé en hexadécimal
%c int caractère
%f double rationnel en notation décimale
%e double rationnel en notation scientifique
%s char* chaîne de caractères
%f float rationnel
%e float rationnel représenté par sa forme : +/- <Mantisee> * 10 ^ <Exposant>
Exemple :
int A,B;
scanf("%4d %2d", &A, &B);
Si nous entrons le nombre 1234567, nous obtiendrons les affectations suivantes:
A=1234
B=56
le chiffre 7 sera gardé pour la prochaine instruction de lecture.
Exemple :
int JOUR, MOIS, ANNEE, RECU;
RECU = scanf("%i %i %i", &JOUR, &MOIS, &ANNEE);
réagit de la façon suivante ( / représente uen valeur indéfinie) :
Introduit RECU JOUR MOIS ANNEE
12 4 1980 3 12 4 1980
12/4/1980 1 12 / /
12.4 1980 1 12 / /
12 4 19.80 3 12 4 19
29
Exemple :
char A = 225;
char B = "\a";
int C = "\a";
putchar("x"); /* afficher la lettre x */
putchar("?"); /* afficher le symbole ? */
putchar("\n"); /* retour à la ligne */
putchar(65); /* afficher le symbole avec le code 65 (ASCII: "A") */
putchar(A); /* afficher la lettre avec le code 225 (ASCII: "ß") */
putchar(B); /* beep sonore */
putchar(C); /* beep sonore */
putchar(EOF); /* marquer la fin du fichier */
Type du résultat
Les valeurs retournées par getchar sont ou bien des caractères (0 - 255) ou bien le
symbole EOF.
Comme la valeur du symbole EOF sort du domaine des caractères, le type résultat
de getchar est int. En général, getchar est utilisé dans une affectation:
int C;
C = getchar();
30
LES STRUCTURES CHAPITRE
CONDITIONNELLES 4
La valeur zéro correspond à la valeur logique faux et toute valeur différente de zéro est
considérée comme vrai.
a. if – else
SYNTAXE :
if ( <expression> )
<bloc d'instructions 1>
else
<bloc d'instructions 2> ;
Si l'<expression> fournit une valeur différente de zéro, alors le <bloc d'instructions 1> est
exécuté
Si l'<expression> fournit la valeur zéro, alors le <bloc d'instructions 2> est exécuté
Exemple 1
if (a > b)
max = a;
else
max = b;
Exemple 2
if (A-B)
printf("A est différent de B\n");
else
printf("A est égal à B\n");
Application 1 :
Aficher du texte à l'écran en fonction de l'âge de l'utilisateur, par exemple, dites à l'utilisateur
qu'il est majeur si (if) il a plus de 18 ans et qu'il est mineur sinon (else).
Application 2 :
A partit de la saisie, des tailles respectives de deux enfants Jules et Jean, dite celui qui est
le plus grand.
31
Remarque
La partie else est facultative lorsqu’on n’a que 2 choix. On peut donc utiliser if de la façon
suivante:
if ( <expression> )
<bloc d'instructions> ;
Application 1 :
En fonction de la couleur du feu tricolore (Rouge, Orange, Vert), dites au Robot conducteur
l’action à exécuter (S’arrêter, Ralentir, Avancer).
Application 2 :
Ecrire un programme qui demande à l'utilisateur de faire le choix de son pays et lui affiche
sa nationalité. On s’inspirera du menu en console ci-dessous.
1. France
2. Canada
3. Belgique
4. Suisse
Choix : 1
Tu es francais.
32
2. Les structures de choix « switch »
Lorsque les choix à faire sont nombreux, switch est plus adapté.
Syntaxe :
switch (expression)
{
case valeur1 : instruction 1;
break;
case valeur2 : instruction 2;
break;
.
.
.
Case valeurn : instruction n;
}
Où expression et valeurx représentent des valeurs entières. Si expression est égal à valeur1
alors l’instruction1 est exécuté. Si expression est égal à valeur2 alors l’instruction2 est
exécuté, etc.
Le cas default correspond au cas où expression n’est égal à aucune des valeur valeur1,
valeur2,…, valeurn.
Un switch permet de tester des égalités et seulement des égalités ! C'est donc un mot clé
moins puissant qu'un if.
Il permet généralement de gérer un menu pour éviter d'avoir plein de else if de partout
comme précédemment.
Voici le même code que tout à l'heure en utilisant le switch, donc sans les else if :
switch(pays)
{
case 1 :
printf("\nTu es francais.");
break;
case 2 :
printf("\nTu es canadien.");
break;
case 3 :
printf("\nTu es belge.");
break;
case 4 :
printf("\nTu es suisse.");
break;
default :
printf("\nTu es un extraterrestre.");
break;
}
33
CHAPITRE
LES BOUCLES
5
1. while
La structure while correspond tout à fait à la structure tant que du langage algorithmique
while ( <expression> )
<bloc d'instructions> ;
Tant que l'<expression> fournit une valeur différente de zéro, le <bloc d'instructions>
est exécuté.
Si l'<expression> fournit la valeur zéro, l’exécution continue avec l'instruction qui
suit le bloc d'instructions.
Le <bloc d'instructions> est exécuté zéro ou plusieurs fois.
Application :
Ecrire un programme qui demande l’âge de l’utilisateur et lui affiche « Vous été mineur
chaque fois que l’âge saisi est <18.
2. do - while
La structure do - while est semblable à la structure while, avec la différence suivante :
while évalue la condition avant d'exécuter le bloc d'instructions,
do - while évalue la condition après avoir exécuté le bloc d'instructions. Ainsi le bloc
d'instructions est exécuté au moins une fois.
do
<bloc d'instructions>
while ( <expression> );
Le <bloc d'instructions> est exécuté au moins une fois et aussi longtemps que
l'<expression> fournit une valeur différente de zéro.
Exemple
float N;
do
{
printf("Introduisez un nombre entre 1 et 10 :");
scanf("%f", &N);
}
while (N<1 || N>10);
34
3. for
La structure for en Pascal et la structure pour en langage algorithmique sont utilisées pour
faciliter la programmation de boucles de comptage. La structure for en C est plus générale
et beaucoup plus puissante.
for ( <expr1> ; <expr2> ; <expr3> )
<bloc d'instructions> est équivalent à :
<expr1>; while ( <expr2> )
{
<bloc d'instructions>
<expr3>;
}
<expr1> est évaluée une fois avant le passage de la boucle. Elle est utilisée pour initialiser
les données de la boucle.
<expr2> est évaluée avant chaque passage de la boucle. Elle est utilisée pour décider si
la boucle est répétée ou non.
<expr3> est évaluée à la fin de chaque passage de la boucle. Elle est utilisée pour
réinitialiser les données de la boucle.
Il y a 3 instructions condensées entre les parenthèses du for, à part ça, la boucle for s'utilise
comme la boucle while, il faut juste que je vous explique ces 3 instructions :
i = 0; permet d'initialiser la variable compteur, i, pour ensuite commencer la boucle.
L'initialisation s'effectue une seule fois et non pas à chaque tour de boucle.
i < 20; est la condition, rien à dire, c'est comme pour while.
i++ est l'incrémentation qui est effectuée à la fin de chaque tour de boucle et non pas au
début.
Dans notre cas, c'est une incrémentation mais ça peut être d'autres opérations comme la
décrémentation (--).
35
CHAPITRE
LES TABLEAUX
6
Les tableaux sont certainement les variables structurées les plus populaires. Ils sont
disponibles dans tous les langages de programmation et servent à résoudre une multitude
de problèmes.
En faisant le rapprochement avec les mathématiques, on dit encore que "A est un vecteur
de dimension N"
Exemple
La déclaration
int JOURS[12]={31,28,31,30,31,30,31,31,30,31,30,31};
Définit un tableau du type int de dimension 12. Les 12 composantes sont initialisées par les
valeurs respectives 31, 28, 31, ... , 31.
On peut accéder à la première composante du tableau par JOURS[0], à la deuxième
composante par JOURS[1], . . . , à la dernière composante par JOURS[11].
a. Déclaration et mémorisation
Déclaration de tableaux en C
<TypeSimple> <NomTableau>[<Dimension>];
4500, 5600};
36
Si un tableau est formé de N composantes et si une composante a besoin de M octets en
mémoire, alors le tableau occupera de N*M octets.
b. Initialisation
Lors de la déclaration d'un tableau, on peut initialiser les composantes du tableau, en
indiquant la liste des valeurs respectives entre accolades. Exemple int A[5] = {10, 20,
30, 40, 50};
Réservation automatique
Si la dimension n'est pas indiquée explicitement lors de l'initialisation, alors l'ordinateur
réserve automatiquement le nombre d'octets nécessaires. Exemple : int A[] = {10, 20,
Attention !
Considérons un tableau T de dimension N:
En C,
- l'accès au premier élément du tableau se fait par T[0]
- l'accès au dernier élément du tableau se fait par T[N-1]
La structure for se prête particulièrement bien au travail avec les tableaux. La plupart des
applications se laissent implémenter par simple modification des exemples-types de
l'affichage et de l'affectation.
Exercice :
Ecrire un programme qui lit la dimension N d'un tableau T du type int (dimension maximale
: 50 composantes), remplit le tableau par des valeurs entrées au clavier et affiche le tableau.
Calculer et afficher ensuite la somme des éléments du tableau.
#include <stdio.h> main()
{
/* Déclarations */ int T[50]; /*
tableau donné */ int N; /*
dimension */ int I; /* indice
courant */
37
long SOM; /* somme des éléments - type long à cause */
/* de la grandeur prévisible du résultat. */
/* Saisie des données */
printf("Dimension du tableau (max.50) : ");
scanf("%d", &N );
for (I=0; I<N; I++)
{
printf("Elément %d : ", I);
scanf("%d", &T[I]);
}
/* Affichage du tableau */
printf("Tableau donné :\n"); for
(I=0; I<N; I++) printf("%d ", T[I]);
printf("\n");
/* Calcul de la somme */ for
(SOM=0, I=0; I<N; I++) SOM
+= T[I];
/* Edition du résultat */
printf("Somme de éléments : %ld\n", SOM);
return 0;
}
38
Exemple
Considérons un tableau NOTES à une dimension pour mémoriser les notes de 20
élèves d'une classe dans un devoir: int NOTE[20] = {45, 34, ... , 50, 48};
Pour mémoriser les notes des élèves dans les 10 devoirs d'un trimestre, nous pouvons
rassembler plusieurs de ces tableaux uni-dimensionnels dans un tableau NOTES à deux
dimensions :
int NOTE[10][20] = {{45, 34, ... , 50, 48},
{39, 24, ... , 49, 45},
... ... ...
{40, 40, ... , 54, 44}};
Dans une ligne nous retrouvons les notes de tous les élèves dans un devoir. Dans une
colonne, nous retrouvons toutes les notes d'un élève.
a. Déclaration et mémorisation
Déclaration de tableaux à deux dimensions en C
<TypeSimple> <NomTabl>[<DimLigne>][<DimCol>];
Exemples int A[10][10]; float B[2][20]; char D[15][40];
Mémorisation
Comme pour les tableaux à une dimension, le nom d'un tableau est le représentant de
l'adresse du premier élément du tableau (c.-à-d. l'adresse de la première ligne du
tableau). Les composantes d'un tableau à deux dimensions sont stockées ligne par ligne
dans la mémoire.
39
b. Initialisation
Lors de la déclaration d'un tableau, on peut initialiser les composantes du tableau, en
indiquant la liste des valeurs respectives entre accolades. A l'intérieur de la liste, les
composantes de chaque ligne du tableau sont encore une fois comprises entre accolades.
Pour améliorer la lisibilité des programmes, on peut indiquer les composantes dans
plusieurs lignes.
Exemples
int A[3][10] ={{ 0,10,20,30,40,50,60,70,80,90},
{10,11,12,13,14,15,16,17,18,19},
{ 1,12,23,34,45,56,67,78,89,90}};
Lors de l'initialisation, les valeurs sont affectées ligne par ligne en passant de gauche à
droite. Nous ne devons pas nécessairement indiquer toutes les valeurs : Les valeurs
manquantes seront initialisées par zéro. Il est cependant défendu d'indiquer trop de valeurs
pour un tableau.
Lors du travail avec les tableaux à deux dimensions, nous utiliserons deux indices (p.ex: I
et J), et la structure for, souvent imbriquée, pour parcourir les lignes et les colonnes des
tableaux.
40
Exercice :
Ecrire un programme qui lit les dimensions L et C d'un tableau T à deux dimensions du type
int (dimensions maximales : 50 lignes et 50 colonnes). Remplir le tableau par des valeurs
entrées au clavier et afficher le tableau ainsi que la somme de tous ses éléments.
41