Langage de programmation c :

🐍 Il n'y a pas que Python dans la vie !

Langage C  ·  Débogage  ·  Assertions  ·  Tests unitaires en Python

1
Il n'y a pas que Python dans la vie !
a Présentation du langage C

Jusqu'à présent, nous avons surtout utilisé le langage de programmation Python. Il existe beaucoup d'autres langages : Java, C++, Ruby, PHP, JavaScript… Tous partagent plus de points communs que de différences. Nous allons nous intéresser au langage C, qui tient une place à part dans l'histoire de l'informatique.

Le langage C a été créé par Dennis Ritchie (1941–2011) et Ken Thompson (1943– ) en 1972 (les mêmes qu'UNIX). C est encore dans le top 10 des langages les plus utilisés — le noyau de Linux est écrit en C.

⚙️ Compilé (ex. C)
Le compilateur transforme tout le code source en langage machine avant l'exécution. Résultat : programmes très rapides à l'exécution.
▶️ Interprété / Bytecode (ex. Python)
Python compile d'abord en bytecode (pseudocode), puis l'interprète. Plus souple, mais légèrement plus lent qu'un exécutable natif compilé.

Voici le premier programme classique en C :

C
#include <stdio.h>

int main(void) {
    printf("Hello World\n");
    return 0;
}
LigneExplication
#include <stdio.h>Directive de préprocesseur. Charge les prototypes des fonctions d'entrée/sortie (dont printf). Obligatoire.
int main(void) { }Fonction principale obligatoire. int = type de retour entier ; void = pas de paramètre. Les accolades { } délimitent le bloc (à la place de l'indentation Python).
printf("…\n");Affiche un message. \n = retour à la ligne. Chaque instruction se termine par un point-virgule obligatoire.
return 0;Renvoie 0 = exécution réussie. Toute autre valeur signale une erreur.

Si l'on oublie un point-virgule, le compilateur produit une erreur explicite :

Erreur compilateur
main.c:4:24: error: expected ';' after expression
    printf("Hello World\n")
                           ^
                           ;
1 error generated.
💡Python équivalent : une seule ligne suffit — print("Hello World")

Pour utiliser des variables, C exige de les déclarer avec leur type avant utilisation :

Python
i = 15
print(f"La valeur de i est {i}")
C
int main(void) {
    int i;
    i = 15;
    printf("La valeur de i est %d\n", i);
    return 0;
}
📌En Python, le typage est dynamique : une variable peut changer de type en cours d'exécution, pas besoin de le déclarer.

Les boucles :

Python
i = 0
while i < 10:
    print(f"i vaut {i}")
    i = i + 1
C
int i = 0;
while (i < 10) {
    printf("i vaut %d\n", i);
    i = i + 1;
}

Les conditions :

Python
i = 19
if i < 18:
    print("Vous êtes mineur")
else:
    print("Vous êtes majeur")
C
int i = 19;
if (i < 18) {
    printf("Vous êtes mineur");
}
else {
    printf("Vous êtes majeur");
}

Les fonctions : chaque paramètre et la valeur de retour doivent être typés :

Python
def somme(x, y):
    s = x + y
    return s

a, b = 5, 4
res = somme(a, b)
print(f"{a} + {b} = {res}")
C
int somme(int x, int y) {
    int s;
    s = x + y;
    return s;
}

int main(void) {
    int a=5, b=4, res;
    res = somme(a, b);
    printf("%d + %d = %d\n",a,b,res);
    return 0;
}
b Prototype d'une fonction

En C, une fonction doit être définie avant d'être appelée. Si ce n'est pas le cas, le compilateur ne reconnaît pas l'appel. La solution : déclarer un prototype en début de fichier.

C
#include <stdio.h>

int somme(int x, int y);   /* prototype — annonce la fonction */

int main(void) {
    int a=5, b=4, res;
    res = somme(a, b);
    printf("La somme de %d et %d vaut %d\n", a, b, res);
    return 0;
}

int somme(int x, int y) {  /* définition — peut être après main() */
    int s = x + y;
    return s;
}
📌Les prototypes de fonctions sont regroupés dans des fichiers .h (header). C'est ce que fait #include <stdio.h> : il charge le prototype de printf depuis le fichier système stdio.h.
2
Débogage d'un programme
a Python trop « laxiste » ?

Les contraintes C (typage des variables, paramètres, valeur de retour) obligent à plus de rigueur et permettent de détecter des erreurs silencieuses. Voici un exemple :

Python
def somme(x, y):
    s = x + y
    return s
AppelRésultatProblème ?
somme(2, 5)7✅ Correct
somme("2", "5")"25" (concaténation !)⚠️ Aucun avertissement Python — bogue silencieux !

En C, le compilateur avertit immédiatement :

Avertissement compilateur C
warning: incompatible pointer to integer conversion
  passing 'char *' to parameter of type 'int'
  res = somme("2", "5");
              ^~~
💡Ces avertissements sont précieux : ils indiquent exactement où se trouve le problème, alors qu'en Python l'erreur passerait totalement inaperçue.
b Les assertions en Python

Pour pallier le laxisme du typage Python, on peut utiliser assert combiné à isinstance() pour vérifier le type des paramètres :

Python
def somme(x, y):
    assert isinstance(x, int), "x doit être un entier"
    assert isinstance(y, int), "y doit être un entier"
    s = x + y
    return s
AppelRésultat
somme(2, 5)Renvoie 7 — aucun problème ✅
somme("2", "5")AssertionError levée — le programme s'arrête et signale le problème ✅
📌isinstance(x, int) renvoie True si x est entier, False sinon. Si assert reçoit False, une exception est levée et l'exécution s'arrête immédiatement.
c Tester ses programmes — Tests unitaires

Les assertions permettent aussi de mettre en place des tests unitaires : vérifier qu'une fonction renvoie bien la valeur attendue pour différents cas d'entrée.

Python
def somme(x, y):
    s = x + y
    return s

# Tests unitaires
assert somme( 5,  2) ==  7, "Erreur : somme(5, 2)"
assert somme( 0,  0) ==  0, "Erreur : somme(0, 0)"
assert somme( 5, -2) ==  3, "Erreur : somme(5, -2)"
assert somme(-5,  2) == -3, "Erreur : somme(-5, 2)"
assert somme(-5, -2) == -7, "Erreur : somme(-5, -2)"
TestValeur attendueCe que l'on vérifie
somme(5, 2)7Cas standard positif
somme(0, 0)0Cas neutre (zéro)
somme(5, -2)3Un entier négatif
somme(-5, 2)-3Un entier négatif
somme(-5, -2)-7Deux entiers négatifs
⚠️ Points essentiels à retenir
  • Impossible de tout tester Il faut choisir judicieusement les cas à tester, notamment les cas limites (zéro, valeurs négatives, chaînes vides…).
  • Pas une preuve formelle Les tests unitaires ne prouvent pas qu'une fonction est correcte. Pour une preuve formelle, il faut des outils mathématiques dédiés.
  • Étape fondamentale La mise en place de tests unitaires est incontournable dans tout développement logiciel sérieux. Ne jamais la négliger.

🐍 Python vs C — Exercices progressifs

NSI  ·  Classe de Première  ·  De débutant à intermédiaire

1 — Premier contact avec le langage C
Activité 1.1  Hello, monde ! ⭐ Découverte

Pour écrire du C sans installer de compilateur, utilise :

🌐  onlinegdb.com → sélectionne le langage C en haut à droite

Teste le programme C ci-dessous et compare-le à son équivalent Python :

Python
print('Bonjour NSI !')
C
#include <stdio.h>

int main(void) {
    printf("Bonjour NSI !\n");
    return 0;
}

Questions :

a) Quelles différences remarques-tu ?

b) À quoi sert le #include <stdio.h> en C ?

c) Pourquoi y a-t-il un point-virgule à la fin de chaque instruction en C ?

Activité 1.2  Afficher plusieurs lignes ⭐ Découverte

Observe le programme Python, puis écris son équivalent en C dans la zone prévue.

Python
print("Je m'appelle Ada Lovelace")
print("J'ai 15 ans")
print("J'apprends la NSI")
💡 En C : printf("texte\n"); — le \n représente un retour à la ligne.

Programme C équivalent :

Activité 1.3  Variables et types ⭐ Découverte

En Python, on crée une variable sans préciser son type. En C, on doit déclarer le type avant utilisation.

Python
age = 17
taille = 1.65
print(f"age : {age} ans")
print(f"Taille : {taille} m")
C
int age = 17;
float taille = 1.65;
printf("age : %d ans\n", age);
printf("Taille : %.2f m\n", taille);
Type CÉquivalent PythonExempleFormatage printf
intint (entier)int age = 17;%d
floatfloat (décimal)float pi = 3.14;%f
charstr (1 caractère)char l = 'A';%c

Déclare en C les variables : un entier score valant 42, un flottant moyenne valant 13.5, puis affiche-les.

2 — Conditions et boucles
Activité 2.1  Condition simple ⭐⭐ Bases
Python
age = 17
if age >= 18:
    print("Majeur")
else:
    print("Mineur")
C
int age = 17;
if (age >= 18) {
    printf("Majeur\n");
}
else {
    printf("Mineur\n");
}
📌 En C, les parenthèses autour de la condition sont obligatoires. Les accolades { } remplacent l'indentation Python.

Écris en C une fonction estMajeur qui prend un age et affiche "Majeur" ou "Mineur" :

Activité 2.2  Boucle while ⭐⭐ Bases
Python
i = 1
while i <= 5:
    print(i)
    i = i + 1
C
int i = 1;
while (i <= 5) {
    printf("%d\n", i);
    i = i + 1;
}

a) Réécris ce programme pour afficher les nombres de 1 à 10 en C :

b) Affiche uniquement les nombres pairs de 2 à 20 :

💡 Pour tester si un nombre est pair en C : if (i % 2 == 0)
Activité 2.3  Boucle for ⭐⭐ Bases
Python
for i in range(5):
    print(i)
C
for (int i = 0; i < 5; i++) {
    printf("%d\n", i);
}
PartieRôle
int i = 0Initialisation : on crée la variable compteur
i < 5Condition : on continue tant que i < 5
i++Incrémentation : équivaut à i = i + 1

Écris en C un programme qui calcule et affiche la somme des entiers de 1 à 100 avec une boucle for :

3 — Fonctions en C
Activité 3.1  Ma première fonction C ⭐⭐ Bases

En C, on doit préciser le type de retour et le type de chaque paramètre :

Python
def double(n):
    return n * 2

print(double(5))
C
int double_val(int n) {
    return n * 2;
}

int main(void) {
    printf("%d\n", double_val(5));
    return 0;
}

Traduis ces fonctions Python en C :

a) Fonction carre qui renvoie le carré d'un entier :

b) Fonction estPair qui renvoie 1 si pair, 0 sinon :

Activité 3.2  estMajeur en C ⭐⭐ Bases

Écris en C une fonction estMajeur qui prend un paramètre age (entier) et renvoie 1 si age ≥ 18 et 0 sinon. Teste-la dans main() avec les valeurs 15 et 20.

💡 En C, il n'y a pas de booléen natif : on utilise 0 (faux) et 1 (vrai).
Activité 3.3  Prototype ⭐⭐⭐ Intermédiaire

Ce programme C est mal organisé : la fonction est définie après son appel. Corrige-le en ajoutant le prototype :

C
#include <stdio.h>

int main(void) {
    printf("Resultat : %d\n", triple(7));  /* erreur ! */
    return 0;
}

int triple(int n) {
    return n * 3;
}
📌 Le prototype se note : int triple(int n); — ne pas oublier le point-virgule !

Programme corrigé :

Activité 3.4  Fonction facture ⭐⭐⭐ Intermédiaire

Tu gères un magasin. Tout client qui achète au moins 5 fois le même article bénéficie d'une remise de 5 %.

Python
def facture(prix_unitaire, quantite):
    total = prix_unitaire * quantite
    if quantite >= 5:
        total = total * 0.95  # remise de 5 %
    return total

Traduis cette fonction en C (type de retour : float) :

Teste avec : prix=12.50, quantité=3, puis quantité=7 :

4 — Assertions et tests unitaires en Python
Activité 4.1  Comprendre assert ⭐⭐ Bases

assert vérifie qu'une condition est vraie. Si elle est fausse, Python lève une AssertionError.

Python
assert 2 + 2 == 4           # OK
assert 2 + 2 == 5           # AssertionError !
assert 2 + 2 == 5, "Erreur" # avec message

Sans exécuter le code, indique lesquelles de ces assertions vont lever une erreur :

assert 10 > 5☐ Passe☐ Erreur
assert len('NSI') == 4☐ Passe☐ Erreur
assert 3 * 3 == 9☐ Passe☐ Erreur
assert 'a' in 'python'☐ Passe☐ Erreur
assert 2 ** 8 == 256☐ Passe☐ Erreur
Activité 4.2  Tester la fonction double ⭐⭐ Bases
Python
def double(n):
    return n * 2

Écris 5 tests unitaires pertinents (cas standard, zéro, négatif, grand nombre…) :

💡 Un bon jeu de tests couvre : un cas standard, le zéro, un nombre négatif, et un cas limite.
Activité 4.3  Tester estMajeur ⭐⭐ Bases
Python
def estMajeur(age):
    if age >= 18:
        return 1
    else:
        return 0

Écris des tests unitaires pour les cas suivants :

Cas à testerValeur attendue
Âge clairement mineur (ex: 12)
Âge clairement majeur (ex: 25)
Cas limite : exactement 18 ans
Cas limite bas : 17 ans
Activité 4.4  Tester la fonction distance ⭐⭐⭐ Intermédiaire
Python
from math import sqrt

def distance(point1, point2):
    return sqrt((point1[0]-point2[0])**2 + (point1[1]-point2[1])**2)

Aide-toi des propriétés mathématiques pour choisir des cas dont tu connais le résultat :

AppelRésultat attenduIndice
distance((0,0), (0,0))Même point
distance((0,0), (1,0))Segment horizontal de longueur 1
distance((0,0), (3,4))Triangle 3-4-5 de Pythagore
distance((0,0), (0,5))Segment vertical
📌 Pour les flottants, évite ==. Préfère : assert abs(distance(...) - valeur) < 0.001

Assertions :

5 — Projet : calculatrice Python ↔ C
Activité 5.1  Traduire un programme complet ⭐⭐⭐⭐ Avancé

Voici une mini-calculatrice Python complète avec ses tests :

Python
def addition(a, b):       return a + b
def soustraction(a, b):   return a - b
def multiplication(a, b): return a * b
def division(a, b):
    if b == 0:
        print("Erreur : division par zéro !")
        return 0
    return a / b

assert addition(3, 4)       == 7
assert soustraction(10, 3)  == 7
assert multiplication(3, 4) == 12
assert division(10, 2)      == 5.0
assert division(5, 0)       == 0
print("Tous les tests sont passés !")

Travail à réaliser :

a) Traduis les 4 fonctions en C avec leurs prototypes.

b) Gère le cas division par zéro : affiche un message et renvoie 0.

c) Écris la fonction main() pour tester les 4 fonctions.

d) Que remplace le assert Python dans le programme C ? Explique.