Algo & C
Algo & C
à l’algorithmique
et à la programmation
en C
5pP\ 0DOJRX\UHV
5LWD =URXU
)DELHQ )HVFKHW
Initiation
à l’algorithmique
et à la programmation
en C
Cours avec 129 exercices corrigés
H pGLWLRQ
Illustration de couverture : © alwyncooper - [Link]
ISBN 978-2-10-071001-0
$ 9$17 352326
/ · e78',$17
Ce livre permet d’aborder la programmation en langage C sans connaissance préa-
lable de l’informatique. Il est conçu pour pouvoir être utilisé comme un outil d’ap-
prentissage en autodidacte. L’étudiant peut utiliser ce livre, et notamment les exer-
cices corrigés, en complément de l’enseignement qu’il reçoit par ailleurs. Il peut
aussi apprendre seul, en abordant les chapitres dans l’ordre, en contrôlant ses connais-
sances avec les exercices corrigés et avec les travaux pratiques sur machine.
Le texte présente de manière concise les bases qui sont nécessaires aux exercices.
Les exercices de chaque chapitre sont progressifs et doivent de préférence être traités
dans l’ordre. Une indication de la difficulté des exercices est donnée par des étoiles
lors de l’énoncé.
© Dunod. Toute reproduction non autorisée est un délit.
Les pièges et les erreurs les plus courants sont mis en évidence clairement
dans le texte par des panneaux spéciaux Attention !
&RPSOpPHQWV
Des compléments sont donnés au fil du texte ; ils apportent un éclairage sur cer-
taines notions difficiles et peuvent être abordés lors d’une seconde lecture ou
lors de la phase d’exercices.
;,,,
,QLWLDWLRQ j O·DOJRULWKPLTXH HW j OD SURJUDPPDWLRQ HQ &
/ · (16(,*1$17
Le langage C, dont découlent de très nombreux autres langages actuels, reste la réfé-
rence pour la programmation bas niveau. En particulier, ce langage est très présent en
programmation système et réseaux. L’apprentissage de l’algorithmique en C permet
notamment de percevoir la gestion mémoire à partir d’une gestion manuelle, qui ap-
porte une meilleure compréhension des constructeurs et destructeurs du C++ ou des
subtilités du garbage collector en Java... L’apprentissage des structures de données
en C permet de comprendre en détail la nature des objets manipulés à travers les li-
brairies Java ou la STL du C++. L’abord de la programmation par le C est le moyen
le plus efficace de former des informaticiens complets, ayant au final une maîtrise
parfaite du bas niveau comme du haut niveau et une compréhension profonde des
concepts.
L’enseignant pourra s’appuyer sur la structure de l’ouvrage, qui permet de dé-
rouler le contenu sans référence à ce qui suit. L’exposé, mais surtout les exercices
contiennent de très nombreux exemples qui peuvent être réutilisés. L’ouvrage est
conçu pour un apprentissage autonome. Les exercices de chaque chapitre sont pro-
gressifs. En complément des exercices propres à chaque enseignant, les exercices du
livre peuvent être donnés à faire aux étudiants qui peuvent consulter la solution a
posteriori.
;,9
Partie 1
Bases du langage C
48 · 81
4 8 · (67 &(
25',1$7(85 "
( ;(03/(6 ' · $33/,&$7,216
'( / · ,1)250$7,48(
Voici quelques exemples d’utilisation des ordinateurs :
• Bureautique L’ordinateur emmagasine des données saisies par une secrétaire par
exemple (textes, chiffres, fichiers clients, etc.) ou des données issues d’archives, et
les met en forme pour permettre une compréhension synthétique, un affichage ou
une communication de ces données.
• Jeux vidéo L’ordinateur combine des données entrées par le concepteur du jeu
(données sur l’univers) avec les événements créés par l’utilisateur du jeu (clics de
souris, etc.) pour générer des images, du son, etc.
• Prévision météorologique À partir de la donnée des relevés de toutes les stations
météo d’une zone géographique, l’ordinateur calcule une situation future et génère
des cartes de températures et de pressions atmosphériques.
• Applications multimédia sur Internet L’ordinateur télécharge des données sto-
ckées sur un serveur distant et affiche ces données sur l’ordinateur de l’utilisateur.
Éventuellement, des actions de l’utilisateur peuvent influer sur les données affi-
chées (on parle alors d’applications interactives).
Dans tous ces exemples, l’ordinateur traite des données, et produit un résultat, soit
communiqué à l’utilisateur (son, images, texte), soit affiché sur un écran, ou stocké
sur un disque, ou un autre support.
© Dunod. Toute reproduction non autorisée est un délit.
&KDSLWUH • 4X·HVWFH TX·XQ RUGLQDWHXU "
Ainsi le nombre 12 (en base 10) sera codé en base 2 par la suite binaire 00001100,
ce qui signifie que :
12 = 0 + 0 + 0 + 0 + 8 + 4 + 0 + 0
= 0 × 27 + 0 × 26 + 0 × 25 + 0 × 24 + 1 × 23 + 1 × 22 + 0 × 21 + 0 × 20
Une donnée égale soit à 0 soit à 1 s’appelle un bit. Une séquence de 8 bits consé-
cutifs s’appelle un octet (en anglais byte). On mesure la quantité de mémoire stockée
dans les ordinateurs en :
• Octets : 1 octet = 8 bits ;
• Kilo-octets (en abrégé Ko ou en anglais Kb) : un Ko vaut 1024 octets.
• Méga-octets (en abrégé Mo ou Mb) : un Mo vaut 1 048 576 octets
• Giga-octets (en abrégé Go ou Gb) : un Go vaut 1 073 741 824 octets
L’apparition des nombres 1024, 1 048 576 et 1 073 741 824 peut paraître surpre-
nante, mais ce sont des puissances de 2. On retient en général qu’un Ko fait environ
mille octets, un Mo environ un million, et un Go environ un milliard.
3URFHVVHXU
Le processeur effectue des opérations (par exemple des opérations arithmétiques
comme des additions ou des multiplications). Ces opérations sont câblées dans le
processeur, c’est-à-dire qu’elles sont effectuées par des circuits électroniques pour
être efficaces. Avec le temps, de plus en plus d’opérations complexes sont câblées au
niveau du processeur, ce qui augmente l’efficacité. La vitesse d’un processeur, c’est-
à-dire en gros le nombre d’opérations par seconde, appelée vitesse d’horloge, est
mesurée en hertz (Hz), kilohertz (1kHz = 1000Hz) , megahertz (1MHz = 106 Hz, et
gigahertz (1GHz = 109 Hz). Sur les architectures récentes, la puce contient plusieurs
cores, chaque core étant l’équivalent d’un processeur et les cores communiquant entre
eux très rapidement par des bus de données. Pour la personne qui programme en C,
la configuration et la structure de la puce est transparente, c’est-à-dire que l’on n’a
pas à s’en préoccuper (sauf pour l’optimisation en programmation très avancée).
)RQFWLRQQHPHQW G·XQ RUGLQDWHXU
3pULSKpULTXHV
Le programme reçoit des données des périphériques en entrée, et communique ses
résultats en sortie à des périphériques. Une liste (non exhaustive) de périphériques
usuels est :
• le clavier qui permet à l’utilisateur de saisir du texte ;
• la souris qui permet à l’utilisateur de sélectionner, d’activer ou de créer à la main
des objets graphiques ;
• l’écran qui permet aux programmes d’afficher des données sous forme graphique ;
• l’imprimante qui permet de sortir des données sur support papier ;
• le disque dur ou la clef USB qui permettent de stocker des données de manière
permanente. Les données sauvegardées sur un tel disque sont préservées, y compris
après terminaison du programme ou lorsque l’ordinateur est éteint, contrairement
aux données stockées en mémoire centrale qui disparaissent lorsque le programme
© Dunod. Toute reproduction non autorisée est un délit.
se termine.
Les périphériques d’entrée (tels que le clavier et la souris) transmettent les données
dans un seul sens, du périphérique vers la mémoire centrale. Les périphériques de
sortie (tels que l’écran ou l’imprimante) recoivent des données dans un seul sens, de
la mémoire centrale (ou de la mémoire vidéo) vers le périphérique. Les périphériques
d’entrée-sortie (tels que le disque dur, le port USB, ou la carte réseau) permettent la
communication dans les deux sens entre la mémoire centrale et le périphérique.
&KDSLWUH • 4X·HVWFH TX·XQ RUGLQDWHXU "
Unité centrale
Flot de données
5HWHQLU O·HVVHQWLHO
352*5$00(6
3 5(0,(56
4 8 · (67 &( 48 · 81 352*5$00( "
Un programme informatique réalise en général trois choses :
• Il lit des données en entrée. Le programme doit en effet savoir à partir de quoi tra-
vailler. Par exemple, pour utiliser une calculatrice, on doit lui donner des nombres
et lui dire quelles opérations effectuer. Pour cela, on utilise souvent un clavier,
mais le programme peut aussi tirer les données d’un disque dur ou encore d’un
autre ordinateur via un réseau ou autre.
• Il effectue des calculs. À partir des données en entrée, le programme va appliquer
automatiquement des méthodes pour traiter ces données et produire un résultat.
Les méthodes que sont capables d’effectuer les ordinateurs s’appellent des algo-
rithmes. Par exemple, une calculatrice va appliquer l’algorithme d’addition ou de
multiplication.
• Il écrit des données en sortie. Lorsque le programme a obtenu un résultat, il
doit écrire ce résultat quelque part pour qu’on puisse l’utiliser. Par exemple, une
calculatrice va afficher un résultat à l’écran ou stocker le résultat en mémoire.
d’effectuer les calculs les plus simples sur des nombres et de stocker le résultat
dans une variable ;
d’afficher un texte ou un nombre à l’écran avec la fonction printf.
Ce faisant, nous verrons la structure d’un programme C très simple et quelques
notions sur la syntaxe du langage. Les notions vues dans ces exemples seront déve-
loppées dans les chapitres suivants. Une fois que le programmeur a écrit son pro-
gramme, qui est du texte en langage C, il doit compiler le programme pour créer un
fichier exécutable pour qu’un utilisateur du programme puisse utiliser ce programme.
Le processus de compilation est décrit en annexe.
&KDSLWUH • 3UHPLHUV SURJUDPPHV
Les phrases comprises entre /∗ et ∗/ sont des commentaires. Elles n’ont pas d’in-
fluence sur le déroulement du programme. Les (bons) programmeurs mettent des
commentaires pour clarifier leur code, ce qui est crucial lorsqu’on travaille en équipe.
La première ligne est une directive #include < stdio.h > qui permet d’utili-
ser les fonctions de la bibliothèque stdio.h dans le programme. Cette bibliothèque
contient notamment les fonctions d’affichage à l’écran printf et de lecture au clavier
scanf.
Vient ensuite la ligne déclarant le début de la fonction main, le programme prin-
cipal. Le programme principal est la suite des instructions qui seront exécutées. En
l’occurrence, il n’y a qu’une seule instruction : un affichage à l’écran par printf. Le
\n permet de passer à la ligne après l’affichage du mot « Bonjour ».
(IIHFWXHU XQ FDOFXO HW PpPRULVHU OH UpVXOWDW
Ne pas oubier le & dans le scanf ! Cela provoquerait une erreur mémoire (ou er-
reur de segmentation) lors de l’exécution du programme et le programme serait
brutalement interrompu.
&RPSOpPHQWV
√
La syntaxe doit être respectée rigoureusement. Si on oublie un point-virgule,
ou bien si on remplace par exemple un guillemet " par une quote ’, cela pro-
voque en général une erreur à la compilation. Dans certains cas très précis,
il y a plusieurs possibilités pour la syntaxe. Par exemple, le mot void dans la
déclaration du main est facultatif.
√
Parfois, surtout en phase de conception, un programme peut être syntaxique-
ment correct, mais le comportement du programme n’est pas celui souhaité
par le programmeur, en raison d’une erreur de conception ou d’inattention.
On dit que le programme comporte un bogue (en anglais bug).
&KDSLWUH • 3UHPLHUV SURJUDPPHV
√
Le return 0 à la fin du main indique seulement que la valeur 0 est retournée
au système (ce qui indique que le programme se termine sans erreur). Nous
n’utiliserons pas la possibilité de retourner des valeurs au système. Ces fonc-
tionalités sont généralement étudiées avec les systèmes d’exploitation.
5HWHQLU O·HVVHQWLHO
Exercices
∗ Pour convertir des degrés Fahrenheit en degrés Celsius, on a la formule sui-
vante :
C 0.55556 × (F − 32)
a) Écrire un programme C qui calcule l’image par f d’un nombre saisi au clavier.
&RUULJpV
f (x + h) − f (x)
f (x) .
h
c∗ Une bille de plomb est lâchée du haut d’un immeuble et tombe en chute
libre. Au bout d’un temps t (exprimé en secondes), la bille est descendue d’une hau-
teur (en mètres) :
1
h = g.t2
2
avec
g = 9.81 (exprimé en (m.s−2 ))
a) Écrire un programme qui calcule la hauteur descendue au bout d’un temps t saisi
au clavier.
Corrigés
© Dunod. Toute reproduction non autorisée est un délit.
a)
int main(void)
{
float celsius, fahrenheit;
printf("Entrez une température en degrés Fahrenheit : ");
scanf("%f", &fahrenheit);
celsius = 0.55556 * (fahrenheit - 32.0);
printf("Température de %f degré Celsius.\n", celsius);
return 0;
}
&KDSLWUH • 3UHPLHUV SURJUDPPHV
b)
int main(void)
{
float celsius, fahrenheit;
printf("Entrez une température en degrés Celsius : ");
scanf("%f", &celsius);
fahrenheit = (celsius / 0.55556) + 32.0;
printf("Température de %f degré Fahrenheit.\n", fahrenheit);
return 0;
}
int main(void)
{
float prix, prixRemise;
printf("Entrez un prix : ");
scanf("%f", &prix);
prixRemise = 0.9 * prix;
printf("Le prix avec 10 %% de remise est de %f.\n", prixRemise);
return 0;
}
a)
int main(void)
{
float x, fx;
printf("Entrez un nombre : ");
scanf("%f", &x);
fx = (2.0 * x + 3.0) / (3.0 * x * x + 2.0);
printf("f(%f) = %f\n", x, fx);
return 0;
}
b)
int main(void)
{
float x, h, fx, fx_plus_h, fPrime_x;
printf("Entrez un nombre : ");
scanf("%f", &x);
printf("Entrez un écart h : ");
scanf("%f", &h);
fx = (2.0 * x + 3.0) / (3.0 * x * x + 2.0);
fx_plus_h = (2.0 * (x + h) + 3.0) / (3.0 * (x + h) * (x + h) + 2.0);
fPrime_x = (fx_plus_h - fx) / h;
printf("f’(%f) = %f\n", x, fPrime_x);
return 0;
}
&RUULJpV
a)
int main(void)
{
float h, t; %