Chapitre 8
Programmation en langage C
Lecture : 24 minQuiz de 12 questions
# Fiche de cours : Programmation en langage C
**Matière :** Informatique — **Niveau :** Terminale C, D, E — **Programme MINESEC (Approche par compétences, Juillet 2020)**
## Introduction
Le langage C, créé par Dennis Ritchie en 1972, est un langage de programmation impératif, structuré et compilé. Il constitue la base de nombreux systèmes d'exploitation (Unix, Linux, Windows) et de logiciels embarqués. Sa maîtrise est essentielle pour comprendre le fonctionnement des ordinateurs et aborder les langages plus modernes. Ce chapitre vous permettra de traduire des algorithmes en programmes C exécutables, d'utiliser les structures de contrôle et les tableaux, et de mettre en œuvre la recherche séquentielle. Nous aborderons également l'identification et la correction des erreurs de programmation, compétence indispensable pour tout développeur.
---
## I. Langages de programmation et exemples d'IDE (Codeblocks, Dev-C++)
### I.1. Notion de langage de programmation
Un langage de programmation est un langage formel (avec une syntaxe et une sémantique précises) permettant d'écrire des instructions compréhensibles par une machine. On distingue plusieurs niveaux :
- **Langage machine** : code binaire (0 et 1) directement exécuté par le processeur.
- **Langage d'assemblage** : représentation symbolique du langage machine (ex : `MOV AX, 5`).
- **Langages de haut niveau** : proches du langage humain, indépendants de la machine (C, Python, Java, Pascal). Le langage C est un langage de haut niveau, mais il permet aussi une gestion fine de la mémoire (pointeurs), ce qui le rapproche du niveau bas.
> **À retenir** : Un langage de programmation est un ensemble de règles syntaxiques et sémantiques permettant d'écrire des programmes. Le langage C est un langage compilé, structuré et procédural.
### I.2. Compilation et exécution
Le code source écrit en C (fichier `.c`) doit être traduit en langage machine par un **compilateur**. Le processus est le suivant :
1. **Édition** : écriture du code source dans un éditeur.
2. **Compilation** : le compilateur (ex : GCC) traduit le code source en fichier objet (`.o`).
3. **Édition de liens** : le linker (ou éditeur de liens) combine les fichiers objets et les bibliothèques pour produire un fichier exécutable (`.exe` sous Windows).
4. **Exécution** : l'ordinateur exécute le fichier binaire.
### I.3. Environnements de Développement Intégrés (IDE)
Un IDE (Integrated Development Environment) regroupe un éditeur de code, un compilateur, un débogueur et d'autres outils dans une interface graphique.
- **Code::Blocks** : IDE gratuit, open-source, multiplateforme. Il utilise GCC (GNU Compiler Collection) par défaut. Il offre une gestion de projets multi-fichiers, un débogueur intégré (GDB) et une coloration syntaxique.
- **Dev-C++** : IDE gratuit pour Windows, basé sur MinGW (portage de GCC). Il est simple d'utilisation, idéal pour les débutants. Il inclut un éditeur, un compilateur et un débogueur.
> **À retenir** : Un IDE (Environnement de Développement Intégré) est un logiciel qui regroupe les outils nécessaires au développement : éditeur de code, compilateur, débogueur. Code::Blocks et Dev-C++ sont deux IDE couramment utilisés pour programmer en C.
### I.4. Procédure de création d'un programme en C avec Code::Blocks
1. Lancer Code::Blocks.
2. Cliquer sur "Create a new project" → choisir "Console application" → sélectionner "C" comme langage.
3. Donner un nom au projet et choisir un dossier de sauvegarde.
4. Le fichier `main.c` est créé automatiquement. Écrire le code.
5. Compiler avec **F9** (Build and Run) ou via le menu "Build".
---
## II. Structure d'un programme C
Un programme C est structuré de manière précise. Il est composé de directives de préprocesseur, de déclarations globales, et d'au moins une fonction principale `main()`.
### II.1. Les directives de préprocesseur
Les lignes commençant par `#` sont des directives de préprocesseur. Elles sont traitées avant la compilation. La plus courante est `#include` qui insère le contenu d'un fichier d'en-tête (header).
```c
#include <stdio.h> // Pour les fonctions d'entrée/sortie (printf, scanf)
#include <stdlib.h> // Pour la fonction system() et l'allocation mémoire
```
### II.2. La fonction principale `main()`
Tout programme C exécutable doit contenir une fonction `main()`. C'est le point d'entrée du programme. Elle retourne un entier (int) : `0` signifie que le programme s'est terminé sans erreur.
```c
int main() {
// Instructions du programme
return 0;
}
```
### II.3. Anatomie complète d'un programme C
```c
// 1. Directives de préprocesseur
#include <stdio.h>
// 2. Déclarations globales (constantes, variables globales, prototypes de fonctions)
#define PI 3.14159
int compteurGlobal = 0;
// 3. Fonctions définies par l'utilisateur (avant main ou après avec prototype)
int carre(int x) {
return x * x;
}
// 4. Fonction principale
int main() {
// Déclarations locales
int a = 5;
int resultat;
// Instructions
resultat = carre(a);
printf("Le carre de %d est %d\n", a, resultat);
return 0; // Fin du programme
}
```
> **À retenir** : La structure minimale d'un programme C est : `#include <stdio.h>` suivi de `int main() { ... return 0; }`. Le programme commence toujours son exécution par la fonction `main()`.
### II.4. Les commentaires
Les commentaires sont ignorés par le compilateur. Ils servent à documenter le code.
- `//` pour un commentaire sur une seule ligne.
- `/* ... */` pour un commentaire sur plusieurs lignes.
```c
// Ceci est un commentaire sur une ligne
/* Ceci est un commentaire
sur plusieurs lignes */
```
---
## III. Déclaration des variables et constantes en C
### III.1. Les variables
Une variable est un espace mémoire nommé qui peut contenir une valeur modifiable pendant l'exécution du programme. En C, toute variable doit être déclarée avant son utilisation, en précisant son **type**.
**Syntaxe :** `type nom_variable;` ou `type nom_variable = valeur_initiale;`
### III.2. Les types de base en C
| Type | Taille (octets) | Valeurs possibles | Exemple de déclaration |
|------|-----------------|-------------------|------------------------|
| `int` | 4 | Entiers relatifs (environ -2^31 à 2^31-1) | `int age = 17;` |
| `float` | 4 | Réels (simple précision, ~6-7 chiffres significatifs) | `float note = 14.5;` |
| `double` | 8 | Réels (double précision, ~15-16 chiffres significatifs) | `double pi = 3.1415926535;` |
| `char` | 1 | Caractère (code ASCII) | `char lettre = 'A';` |
| `void` | 0 | Aucune valeur (utilisé pour les fonctions) | `void afficher();` |
### III.3. Règles de nommage des variables
- Le nom doit commencer par une lettre (majuscule ou minuscule) ou un tiret bas `_`.
- Les caractères suivants peuvent être des lettres, des chiffres ou `_`.
- Les noms sont sensibles à la casse (`Nom` ≠ `nom`).
- Les mots-clés du langage sont réservés (`int`, `if`, `while`, `return`, etc.).
> **À retenir** : Une variable est un espace mémoire nommé et typé. Sa valeur peut changer au cours de l'exécution. La déclaration se fait par `type nom;`.
### III.4. Les constantes
Une constante est une valeur qui ne change pas pendant l'exécution du programme. En C, on utilise la directive `#define` ou le mot-clé `const`.
**Méthode 1 : `#define` (constante symbolique, préprocesseur)**
```c
#define TAUX_TVA 0.192
#define NOMBRE_MAX 100
```
**Méthode 2 : `const` (constante typée)**
```c
const int ANNEE = 2024;
const float PI = 3.14159;
```
> **À retenir** : Une constante est une valeur fixe. On la déclare avec `#define NOM valeur` (préprocesseur) ou `const type nom = valeur;`. Par convention, les noms de constantes s'écrivent en MAJUSCULES.
### III.5. Exemple complet de déclarations
```c
#include <stdio.h>
#define TAUX_REUSSITE 10 // Constante symbolique
int main() {
// Déclaration de variables
int nombreEtudiants = 45;
float moyenneClasse = 12.75;
char mention = 'B';
double precision = 0.000001;
// Déclaration d'une constante typée
const int MAX_NOTES = 20;
// Utilisation
printf("Nombre d'etudiants : %d\n", nombreEtudiants);
printf("Moyenne : %.2f\n", moyenneClasse);
printf("Mention : %c\n", mention);
printf("Seuil de reussite : %d\n", TAUX_REUSSITE);
return 0;
}
```
---
## IV. Fonctions d'entrée/sortie en C (printf, scanf)
Les fonctions d'entrée/sortie sont déclarées dans la bibliothèque standard `stdio.h`.
### IV.1. La fonction `printf()` — Sortie formatée
`printf` permet d'afficher du texte et des valeurs à l'écran.
**Syntaxe :** `printf("chaîne de format", arguments);`
La chaîne de format contient du texte et des **spécificateurs de format** qui indiquent comment afficher les arguments.
| Spécificateur | Type de variable |
|---------------|------------------|
| `%d` ou `%i` | `int` |
| `%f` | `float` ou `double` |
| `%c` | `char` |
| `%s` | chaîne de caractères (tableau de char) |
| `%lf` | `double` (pour scanf) |
| `%p` | adresse mémoire (pointeur) |
**Exemples :**
```c
#include <stdio.h>
int main() {
int age = 17;
float taille = 1.75;
char initiale = 'J';
printf("J'ai %d ans.\n", age);
printf("Je mesure %.2f m.\n", taille); // %.2f affiche 2 décimales
printf("Mon initiale est %c.\n", initiale);
printf("Valeur hexadecimale de %d : %x\n", age, age);
return 0;
}
```
**Caractères spéciaux (échappement) :**
- `\n` : nouvelle ligne
- `\t` : tabulation
- `\\` : affiche un backslash
- `\"` : affiche un guillemet
### IV.2. La fonction `scanf()` — Entrée formatée
`scanf` permet de lire des données saisies au clavier.
**Syntaxe :** `scanf("chaîne de format", &variable);`
**Important :** Il faut utiliser le symbole `&` (adresse de) devant la variable pour que `scanf` puisse modifier sa valeur.
```c
#include <stdio.h>
int main() {
int nombre;
float note;
char lettre;
printf("Entrez un entier : ");
scanf("%d", &nombre);
printf("Entrez une note : ");
scanf("%f", ¬e);
printf("Entrez une lettre : ");
scanf(" %c", &lettre); // L'espace avant %c permet d'ignorer le caractère de nouvelle ligne
printf("Vous avez saisi : %d, %.2f, %c\n", nombre, note, lettre);
return 0;
}
```
> **À retenir** : `printf("format", variables)` affiche des valeurs à l'écran. `scanf("format", &variables)` lit des valeurs au clavier. Le symbole `&` est obligatoire devant chaque variable dans `scanf`.
### IV.3. Programme complet : calcul de la moyenne
```c
#include <stdio.h>
int main() {
float note1, note2, note3;
float moyenne;
printf("=== Calcul de moyenne ===\n");
printf("Entrez la note 1 : ");
scanf("%f", ¬e1);
printf("Entrez la note 2 : ");
scanf("%f", ¬e2);
printf("Entrez la note 3 : ");
scanf("%f", ¬e3);
moyenne = (note1 + note2 + note3) / 3;
printf("La moyenne est : %.2f\n", moyenne);
return 0;
}
```
---
## V. Structures de contrôle en langage C
Les structures de contrôle permettent de modifier le flux d'exécution d'un programme. On distingue les structures conditionnelles et les structures répétitives (boucles).
### V.1. La structure conditionnelle `if` et `if...else`
**Syntaxe :**
```c
if (condition) {
// instructions si condition vraie
} else {
// instructions si condition fausse
}
```
**Opérateurs de comparaison :** `==`, `!=`, `<`, `>`, `<=`, `>=`
**Opérateurs logiques :** `&&` (ET), `||` (OU), `!` (NON)
```c
#include <stdio.h>
int main() {
int note;
printf("Entrez votre note : ");
scanf("%d", ¬e);
if (note >= 10) {
printf("Admis\n");
} else {
printf("Echoue\n");
}
// if...else if...else (structure en cascade)
if (note >= 16) {
printf("Mention Tres Bien\n");
} else if (note >= 14) {
printf("Mention Bien\n");
} else if (note >= 12) {
printf("Mention Assez Bien\n");
} else if (note >= 10) {
printf("Mention Passable\n");
} else {
printf("Echec\n");
}
return 0;
}
```
### V.2. La structure `switch...case`
`switch` permet de tester une variable entière ou un caractère contre plusieurs valeurs constantes. Elle est plus lisible que de multiples `if...else if` pour des valeurs discrètes.
**Syntaxe :**
```c
switch (expression) {
case valeur1:
// instructions
break;
case valeur2:
// instructions
break;
default:
// instructions si aucun cas ne correspond
}
```
**Important :** Le `break` est obligatoire à la fin de chaque `case` pour sortir du `switch`. Sans lui, l'exécution "tombe" dans le cas suivant.
```c
#include <stdio.h>
int main() {
int choix;
printf("Menu :\n");
printf("1. Ajouter\n");
printf("2. Supprimer\n");
printf("3. Afficher\n");
printf("Votre choix : ");
scanf("%d", &choix);
switch (choix) {
case 1:
printf("Vous avez choisi Ajouter.\n");
break;
case 2:
printf("Vous avez choisi Supprimer.\n");
break;
case 3:
printf("Vous avez choisi Afficher.\n");
break;
default:
printf("Choix invalide.\n");
}
return 0;
}
```
> **À retenir** : `if...else` est utilisé pour des conditions complexes. `switch...case` est utilisé pour tester une variable entière ou caractère contre des valeurs constantes. Chaque `case` doit se terminer par `break;`.
### V.3. La boucle `for`
La boucle `for` est utilisée lorsque le nombre d'itérations est connu à l'avance.
**Syntaxe :**
```c
for (initialisation; condition; incrémentation) {
// instructions répétées
}
```
```c
#include <stdio.h>
int main() {
int i;
// Afficher les nombres de 1 à 10
for (i = 1; i <= 10; i++) {
printf("%d ", i);
}
printf("\n");
// Afficher les nombres pairs de 0 à 20
for (i = 0; i <= 20; i += 2) {
printf("%d ", i);
}
printf("\n");
// Boucle décroissante
for (i = 10; i >= 1; i--) {
printf("%d ", i);
}
printf("\n");
return 0;
}
```
### V.4. La boucle `while`
La boucle `while` répète les instructions **tant que** la condition est vraie. La condition est testée **avant** chaque itération.
**Syntaxe :**
```c
while (condition) {
// instructions
}
```
```c
#include <stdio.h>
int main() {
int compteur = 1;
int somme = 0;
// Calculer la somme des entiers de 1 à 100
while (compteur <= 100) {
somme += compteur;
compteur++;
}
printf("La somme de 1 a 100 est : %d\n", somme);
return 0;
}
```
### V.5. La boucle `do...while`
La boucle `do...while` exécute les instructions **au moins une fois**, puis répète tant que la condition est vraie. La condition est testée **après** chaque itération.
**Syntaxe :**
```c
do {
// instructions
} while (condition);
```
```c
#include <stdio.h>
int main() {
int nombre;
// Saisie contrôlée : on demande un nombre positif
do {
printf("Entrez un nombre positif : ");
scanf("%d", &nombre);
if (nombre <= 0) {
printf("Erreur ! Le nombre doit etre positif.\n");
}
} while (nombre <= 0);
printf("Vous avez saisi : %d\n", nombre);
return 0;
}
```
> **À retenir** : `for` est adapté quand le nombre d'itérations est connu. `while` teste la condition avant d'exécuter le bloc. `do...while` exécute le bloc au moins une fois puis teste la condition.
### V.6. Tableau comparatif des boucles
| Boucle | Nombre d'itérations | Test de condition | Utilisation typique |
|--------|---------------------|-------------------|---------------------|
| `for` | Connu à l'avance | Avant | Parcours de tableaux, compteurs |
| `while` | Inconnu | Avant | Saisie contrôlée, attente d'une condition |
| `do...while` | Au moins 1 | Après | Menu, saisie avec validation |
---
## VI. Utilisation des tableaux en langage C
### VI.1. Définition et déclaration
Un tableau est une structure de données qui regroupe plusieurs éléments de **même type**, stockés en mémoire de manière contiguë. Chaque élément est accessible par son **indice** (index), qui commence à 0.
**Déclaration :** `type nom_tableau[taille];`
```c
int notes[30]; // Tableau de 30 entiers
float temperatures[7]; // Tableau de 7 réels
char nom[20]; // Tableau de 20 caractères (chaîne)
```
**Initialisation à la déclaration :**
```c
int notes[5] = {12, 15, 8, 17, 10};
float moyennes[3] = {12.5, 14.0, 9.75};
int valeurs[] = {1, 2, 3, 4, 5}; // Taille déduite automatiquement
```
### VI.2. Accès aux éléments
L'accès à un élément se fait par son indice : `nom_tableau[indice]`.
```c
#include <stdio.h>
int main() {
int notes[5] = {12, 15, 8, 17, 10};
// Afficher le premier élément (indice 0)
printf("Premiere note : %d\n", notes[0]);
// Modifier le troisième élément (indice 2)
notes[2] = 14;
// Afficher tous les éléments
for (int i = 0; i < 5; i++) {
printf("notes[%d] = %d\n", i, notes[i]);
}
return 0;
}
```
> **À retenir** : Un tableau est un ensemble d'éléments de même type, accessibles par un indice commençant à 0. La taille du tableau est fixée à la déclaration.
### VI.3. Parcours et opérations sur les tableaux
```c
#include <stdio.h>
#define TAILLE 10
int main() {
int tableau[TAILLE];
int i;
int somme = 0;
int max, min;
// Saisie des éléments
printf("Saisie de %d entiers :\n", TAILLE);
for (i = 0; i < TAILLE; i++) {
printf("Element %d : ", i + 1);
scanf("%d", &tableau[i]);
}
// Calcul de la somme
for (i = 0; i < TAILLE; i++) {
somme += tableau[i];
}
// Recherche du maximum et du minimum
max = tableau[0];
min = tableau[0];
for (i = 1; i < TAILLE; i++) {
if (tableau[i] > max) {
max = tableau[i];
}
if (tableau[i] < min) {
min = tableau[i];
}
}
printf("Somme : %d\n", somme);
printf("Moyenne : %.2f\n", (float)somme / TAILLE);
printf("Maximum : %d\n", max);
printf("Minimum : %d\n", min);
return 0;
}
```
### VI.4. Les chaînes de caractères
En C, une chaîne de caractères est un tableau de `char` terminé par le caractère nul `'\0'`.
```c
#include <stdio.h>
#include <string.h> // Pour les fonctions de manipulation de chaînes
int main() {
char nom[50];
char prenom[] = "Jean"; // Initialisation automatique avec '\0'
printf("Entrez votre nom : ");
scanf("%s", nom); // Pas de & pour une chaîne (nom est déjà une adresse)
printf("Bonjour %s %s\n", prenom, nom);
// Fonctions utiles de string.h
printf("Longueur du nom : %lu\n", strlen(nom));
return 0;
}
```
### VI.5. Tableaux à deux dimensions (matrices)
Un tableau à deux dimensions est un tableau de tableaux. Il est déclaré comme suit : `type nom[lignes][colonnes];`
```c
#include <stdio.h>
#define LIGNES 3
#define COLONNES 3
int main() {
int matrice[LIGNES][COLONNES] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int i, j;
// Affichage de la matrice
printf("Matrice :\n");
for (i = 0; i < LIGNES; i++) {
for (j = 0; j < COLONNES; j++) {
printf("%d ", matrice[i][j]);
}
printf("\n");
}
// Calcul de la somme des éléments
int somme = 0;
for (i = 0; i < LIGNES; i++) {
for (j = 0; j < COLONNES; j++) {
somme += matrice[i][j];
}
}
printf("Somme des elements : %d\n", somme);
return 0;
}
```
---
## VII. Traduction de l'algorithme de recherche séquentielle en langage C
### VII.1. Principe de la recherche séquentielle
La **recherche séquentielle** (ou recherche linéaire) consiste à parcourir un tableau élément par élément, du premier au dernier, jusqu'à trouver la valeur recherchée ou atteindre la fin du tableau.
**Algorithme (pseudo-code) :**
```
ALGORITHME RechercheSequentielle
VARIABLES
tableau : Tableau d'entiers
taille : Entier
valeur : Entier
i : Entier
trouve : Booléen
DEBUT
trouve ← FAUX
i ← 0
TANT QUE (i < taille ET trouve = FAUX) FAIRE
SI tableau[i] = valeur ALORS
trouve ← VRAI
SINON
i ← i + 1
FIN SI
FIN TANT QUE
SI trouve = VRAI ALORS
AFFICHER "Valeur trouvée à l'indice ", i
SINON
AFFICHER "Valeur non trouvée"
FIN SI
FIN
```
### VII.2. Traduction en langage C
```c
#include <stdio.h>
#define TAILLE 10
int main() {
int tableau[TAILLE] = {5, 12, 8, 3, 15, 7, 20, 1, 9, 6};
int valeur;
int i;
int trouve = 0; // 0 = FAUX, 1 = VRAI
int position = -1;
printf("=== Recherche sequentielle ===\n");
printf("Tableau : ");
for (i = 0; i < TAILLE; i++) {
printf("%d ", tableau[i]);
}
printf("\n");
printf("Entrez la valeur a rechercher : ");
scanf("%d", &valeur);
// Recherche séquentielle
i = 0;
while (i < TAILLE && !trouve) {
if (tableau[i] == valeur) {
trouve = 1;
position = i;
} else {
i++;
}
}
// Affichage du résultat
if (trouve) {
printf("Valeur %d trouvee a l'indice %d.\n", valeur, position);
} else {
printf("Valeur %d non trouvee dans le tableau.\n", valeur);
}
return 0;
}
```
### VII.3. Version avec fonction
```c
#include <stdio.h>
#define TAILLE 10
// Fonction de recherche séquentielle
// Retourne l'indice de la valeur si trouvée, -1 sinon
int rechercher(int tableau[], int taille, int valeur) {
int i;
for (i = 0; i < taille; i++) {
if (tableau[i] == valeur) {
return i; // Retourne l'indice dès que trouvé
}
}
return -1; // Valeur non trouvée
}
int main() {
int tableau[TAILLE] = {5, 12, 8, 3, 15, 7, 20, 1, 9, 6};
int valeur;
int resultat;
printf("Entrez la valeur a rechercher : ");
scanf("%d", &valeur);
resultat = rechercher(tableau, TAILLE, valeur);
if (resultat != -1) {
printf("Valeur %d trouvee a l'indice %d.\n", valeur, resultat);
} else {
printf("Valeur %d non trouvee.\n", valeur);
}
return 0;
}
```
> **À retenir** : La recherche séquentielle parcourt le tableau élément par élément. Sa complexité est O(n) dans le pire des cas. Elle fonctionne même si le tableau n'est pas trié.
---
## VIII. Exécution d'un programme de recherche séquentielle en langage C
### VIII.1. Programme complet avec saisie utilisateur
```c
#include <stdio.h>
#define MAX_TAILLE 100
int main() {
int tableau[MAX_TAILLE];
int taille;
int valeur;
int i;
int trouve = 0;
printf("=== Recherche sequentielle interactive ===\n");
// Saisie de la taille du tableau
do {
printf("Combien d'elements (1 a %d) ? ", MAX_TAILLE);
scanf("%d", &taille);
if (taille < 1 || taille > MAX_TAILLE) {
printf("Taille invalide. Recommencez.\n");
}
} while (taille < 1 || taille > MAX_TAILLE);
// Saisie des éléments du tableau
printf("Saisie des %d elements :\n", taille);
for (i = 0; i < taille; i++) {
printf("Element %d : ", i + 1);
scanf("%d", &tableau[i]);
}
// Affichage du tableau
printf("\nTableau : [");
for (i = 0; i < taille; i++) {
printf("%d", tableau[i]);
if (i < taille - 1) {
printf(", ");
}
}
printf("]\n");
// Saisie de la valeur à rechercher
printf("Valeur a rechercher : ");
scanf("%d", &valeur);
// Recherche séquentielle
for (i = 0; i < taille; i++) {
if (tableau[i] == valeur) {
trouve = 1;
break;
}
}
// Affichage du résultat
if (trouve) {
printf("\nRESULTAT : La valeur %d a ete trouvee a l'indice %d (position %d).\n",
valeur, i, i + 1);
} else {
printf("\nRESULTAT : La valeur %d n'existe pas dans le tableau.\n", valeur);
}
return 0;
}
```
### VIII.2. Exemple d'exécution pas à pas
**Entrée utilisateur :**
```
Combien d'elements (1 a 100) ? 5
Element 1 : 10
Element 2 : 25
Element 3 : 7
Element 4 : 42
Element 5 : 18
Valeur a rechercher : 7
```
**Sortie affichée :**
```
=== Recherche sequentielle interactive ===
Tableau : [10, 25, 7, 42, 18]
Valeur a rechercher : 7
RESULTAT : La valeur 7 a ete trouvee a l'indice 2 (position 3).
```
**Déroulement de la recherche :**
1. `i = 0` : `tableau[0] = 10` ≠ 7 → continuer
2. `i = 1` : `tableau[1] = 25` ≠ 7 → continuer
3. `i = 2` : `tableau[2] = 7` = 7 → `trouve = 1`, sortie de la boucle
4. Affichage du résultat avec l'indice 2
### VIII.3. Cas où la valeur n'est pas trouvée
**Entrée utilisateur :**
```
Combien d'elements (1 a 100) ? 3
Element 1 : 5
Element 2 : 8
Element 3 : 12
Valeur a rechercher : 20
```
**Sortie affichée :**
```
Tableau : [5, 8, 12]
Valeur a rechercher : 20
RESULTAT : La valeur 20 n'existe pas dans le tableau.
```
**Déroulement :** Tous les éléments sont parcourus (i = 0, 1, 2), aucun ne correspond à 20. La boucle se termine avec `trouve = 0`.
---
## IX. Identification, interprétation et correction des erreurs de programmation
### IX.1. Types d'erreurs
On distingue trois catégories d'erreurs en programmation :
| Type d'erreur | Description | Détection |
|---------------|-------------|-----------|
| **Erreur de syntaxe** | Violation des règles du langage (oubli de `;`, parenthèse non fermée, etc.) | Détectée par le compilateur |
| **Erreur d'exécution** (runtime) | Se produit pendant l'exécution (division par zéro, accès hors limites, etc.) | Détectée par le système ou le programme |
| **Erreur logique** | Le programme s'exécute mais donne des résultats incorrects | Non détectée automatiquement, nécessite des tests |
### IX.2. Erreurs de syntaxe courantes
```c
// ERREUR 1 : Point-virgule manquant
int main() {
int a = 5
printf("%d", a); // Erreur : ';' manquant après "int a = 5"
return 0;
}
// ERREUR 2 : Parenthèse non fermée
int main() {
printf("Bonjour"; // Erreur : parenthèse fermante manquante
return 0;
}
// ERREUR 3 : Accolade non fermée
int main() {
printf("Bonjour\n");
// Erreur : accolade fermante manquante
}
// ERREUR 4 : Variable non déclarée
int main() {
x = 10; // Erreur : 'x' n'est pas déclaré
return 0;
}
// ERREUR 5 : Utilisation de = au lieu de ==
int main() {
int a = 5;
if (a = 10) { // Erreur logique : affectation au lieu de comparaison
printf("a vaut 10\n");
}
return 0;
}
```
### IX.3. Erreurs d'exécution courantes
```c
// ERREUR : Division par zéro
#include <stdio.h>
int main() {
int a = 10;
int b = 0;
int resultat;
resultat = a / b; // Erreur d'exécution : division par zéro
printf("%d\n", resultat);
return 0;
}
// ERREUR : Accès hors limites d'un tableau
#include <stdio.h>
int main() {
int tableau[5] = {1, 2, 3, 4, 5};
printf("%d\n", tableau[10]); // Erreur : indice 10 hors limites (0-4)
return 0;
}
```
### IX.4. Erreurs logiques
```c
// ERREUR LOGIQUE : Calcul de moyenne incorrect
#include <stdio.h>
int main() {
int note1 = 12, note2 = 15, note3 = 10;
float moyenne;
moyenne = note1 + note2 + note3 / 3; // ERREUR : priorité des opérateurs
// Correct : moyenne = (note1 + note2 + note3) / 3;
printf("Moyenne : %.2f\n", moyenne); // Affiche 25.00 au lieu de 12.33
return 0;
}
```
### IX.5. Messages d'erreur du compilateur et leur interprétation
| Message d'erreur | Signification | Correction |
|------------------|---------------|------------|
| `expected ';' before 'printf'` | Point-virgule manquant avant `printf` | Ajouter `;` à la fin de la ligne précédente |
| `'x' undeclared (first use in this function)` | Variable `x` non déclarée | Déclarer la variable : `int x;` |
| `expected ')' before ';' token` | Parenthèse fermante manquante | Vérifier l'équilibre des parenthèses |
| `assignment to 'int' from 'float'` | Affectation d'un float à un int | Utiliser un cast : `(int)valeur` ou changer le type |
| `undefined reference to 'main'` | Fonction `main` absente | Ajouter `int main() { ... }` |
| `segmentation fault` (à l'exécution) | Accès mémoire invalide | Vérifier les indices de tableaux et les pointeurs |
### IX.6. Procédure de correction des erreurs
**Étape 1 : Lire le message d'erreur**
- Identifier le fichier et le numéro de ligne indiqués.
- Comprendre le type d'erreur signalé.
**Étape 2 : Analyser la ligne fautive**
- Vérifier la syntaxe (points-virgules, accolades, parenthèses).
- Vérifier les types des variables.
- Vérifier les noms des variables et fonctions.
**Étape 3 : Corriger et recompiler**
- Apporter la correction.
- Recompiler le programme.
- Répéter jusqu'à ce qu'il n'y ait plus d'erreurs.
**Étape 4 : Tester le programme**
- Exécuter avec des valeurs normales.
- Tester les cas limites (valeurs extrêmes, saisies invalides).
- Vérifier que les résultats sont corrects.
> **À retenir** : Les erreurs de syntaxe sont détectées par le compilateur. Les erreurs d'exécution apparaissent pendant le fonctionnement. Les erreurs logiques produisent des résultats incorrects sans message d'erreur. La méthode de correction suit : lire le message → analyser la ligne → corriger → recompiler → tester.
### IX.7. Exemple complet : programme avec erreurs à corriger
**Programme erroné :**
```c
#include <stdio.h>
int main() {
int notes[5];
int i;
int somme = 0;
float moyenne;
printf("Saisie des notes :\n");
for (i = 0; i <= 5; i++) { // ERREUR : i <= 5 au lieu de i < 5
printf("Note %d : ", i + 1);
scanf("%d", ¬es[i]);
}
for (i = 0; i < 5; i++) {
somme = somme + notes[i];
}
moyenne = somme / 5; // ERREUR : division entière
printf("Moyenne : %f\n", moyenne);
return 0;
}
```
**Corrections apportées :**
```c
#include <stdio.h>
int main() {
int notes[5];
int i;
int somme = 0;
float moyenne;
printf("Saisie des notes :\n");
for (i = 0; i < 5; i++) { // CORRECTION : i < 5
printf("Note %d : ", i + 1);
scanf("%d", ¬es[i]);
}
for (i = 0; i < 5; i++) {
somme = somme + notes[i];
}
moyenne = (float)somme / 5; // CORRECTION : cast en float
printf("Moyenne : %.2f\n", moyenne); // CORRECTION : %.2f pour 2 décimales
return 0;
}
```
**Explication des corrections :**
1. `i <= 5` provoquait un accès hors limites du tableau (indice 5 inexistant). Corrigé en `i < 5`.
2. `somme / 5` effectuait une division entière (résultat tronqué). Corrigé en `(float)somme / 5`.
3. `%f` affichait trop de décimales. Corrigé en `%.2f`.
---
## Conclusion
Ce chapitre vous a permis d'acquérir les compétences fondamentales de la programmation en langage C : la structure d'un programme, la déclaration des variables et constantes, les entrées/sorties avec `printf` et `scanf`, les structures de contrôle (`if`, `switch`, `for`, `while`, `do...while`), et la manipulation des tableaux. Vous avez également appris à traduire l'algorithme de recherche séquentielle en code C exécutable et à identifier, interpréter et corriger les différentes catégories d'erreurs de programmation.
Ces connaissances constituent une base solide pour aborder des concepts plus avancés comme les fonctions, les pointeurs, les structures de données dynamiques et la programmation modulaire. La pratique régulière, la lecture attentive des messages d'erreur et le test systématique des programmes sont les clés de la maîtrise du langage C.
Quiz du chapitre
12 questions — vérifie chaque réponse pour voir l'explication.