Série 2 :
Programmation C : structures de contrôles et fonctions

Buts

Le but de cette série d'exercices est de vous permettre de continuer à pratiquer les bases de la programmation en C sur des exemples plus avancés utilisant des structures de contrôle et des fonctions.

Rappel

Avez-vous pris connaissance des conseils relatifs à ces séries d'exercices ?


Exercice 1 : Les tables de multiplication (itération for, niveau 1)

Objectif

Écrivez un programme tables.c affichant les tables de multiplication de 2 à 10.

Votre programme devra produire la sortie suivante à l'écran :

Tables de multiplication

Table de 2 :
  1 * 2 = 2
  ...
  10 * 2 = 20
...
Table de 5 :
  1 * 5 = 5
  2 * 5 = 10
  ...
...
Table de 10 :
  1 * 10 = 10
  ...
  10 * 10 = 100

Méthode :

Utilisez deux structures d'itération for imbriquées l'une dans l'autre.


Exercice 2 : Rebonds de balles (itération for, niveau 2)

Objectif :

L'objectif de cet exercice est de résoudre le problème suivant :

Lorsqu'une balle tombe d'une hauteur initiale h, sa vitesse à l'arrivée au sol est v=sqrt(2*h*g). Immédiatement après le rebond, sa vitesse est v1=eps*v (où eps est une constante et v la vitesse avant le rebond). Elle remonte alors à la hauteur h=(v1*v1)/2*g.

Le but est d'écrire un programme (rebonds1.c) qui calcule la hauteur à laquelle la balle remonte après un nombre NBR de rebonds.

Méthode :

On veut résoudre ce problème, non pas du point de vue formel (équations) mais par simulation du système physique (la balle).

Utilisez une itération for et des variables v, v1, (les vitesses avant et après le rebond), et h, h1 (les hauteurs au début de la chute et à la fin de la remontée).

Tâches :

Écrivez le programme rebonds1.c qui affiche la hauteur après le nombre de rebonds spécifié.

Votre programme devra utiliser la constante g, de valeur 9,81 et demander à l'utilisateur d'entrer les valeurs de

Essayez les valeurs H0 = 10, eps = 0.9, NBR = 20 :
Au 20ème rebond, la hauteur sera de 0.147809 m.

Remarque :


Exercice 3 : Rebonds de balles - le retour. (boucles do...while, niveau 2)

On se demande maintenant combien de rebonds fait cette balle avant que la hauteur à laquelle elle rebondit soit plus petite que (ou égale à) une hauteur donnée h_fin.

Écrivez le programme rebonds2.c qui affiche le nombre de rebonds à l'écran.

Il devra utiliser une boucle do...while, et demander à l'utilisateur d'entrer les valeurs de :

Essayez les valeurs H0=10, eps=0.9, h_fin=0.5 :
Nombre de rebonds : 15

Exercice 4 : Une histoire de prêt (boucle, niveau 2)

L'objectif de cet exercice est de résoudre le problème suivant :

Une banque fait un prêt à une personne X pour un montant total de S0 francs. X rembourse chaque mois un montant r et paye un intérêt ir*SS est la somme restant à rembourser et ir le taux d'intérêt employé.

Quelle est la somme des intérêts encaissés par la banque quand X a remboursé la totalité de son prêt ?

Écrivez le programme pret.c qui calcule la somme des intérêts encaissés et la durée en mois du remboursement, puis qui affiche ces informations à l'écran.

Contraintes :

Testez votre programme avec les valeurs suivantes: S0=30000, r=1300, ir=0.01 (i.e. 1%) :
Somme des intérêts encaissés : 3612.00 (sur 24 mois).

Exercice 5 : Nombres premiers (structures de contrôle, niveau 2)

Écrivez le programme premier.c qui demande à l'utilisateur d'entrer un entier n strictement plus grand que 1, puis décide si ce nombre est premier ou non.

Algorithme :

  1. Vérifier si le nombre n est pair (si oui, il n'est pas premier sauf si c'est 2).
  2. Pour tous les nombres impairs inférieurs ou égaux à la racine carrée de n, vérifier s'ils divisent n. Si ce n'est pas le cas, alors n est premier.

Tâches :

Testez votre programme avec les nombres : 2, 16, 17, 91, 589, 1001, 1009, 1299827 et 2146654199. Indiquez ceux qui sont premiers.

Exercice 6 : Expressions arithmétiques (niveau 3)

Soient les expressions suivantes : On rappelle que le logarithme est défini sur les réels strictement positifs, la racine carrée sur les réels positifs ou nuls, la fraction 1/x sur les réels non nuls. Les autres fonctions sont définies sur l'ensemble des réels.

Écrivez un programme formules.c qui :

  1. demande à l'utilisateur d'entrer un réel ;
  2. enregistre la réponse de l'utilisateur dans une variable x de type réel ;
  3. teste pour chacune des expressions ci-dessus si elle est définie pour x :
information Pour utiliser les fonctions mathématiques, vous devez ajouter en début de programme la ligne :

#include <math.h>

et l'option -lm à la fin de votre commande de compilation :
gcc monfichier.c -o monfichier -lm
(ce genre d'instructions seront expliquées plus tard dans le cours).
Vous pouvez alors utiliser les fonctions log pour le logarithme, sqrt pour la racine carré (SQuare RooT), exp pour l'exponentielle, et sin pour le sinus.
Pour l'élévation au carré, utilisez plutôt la multiplication que la fonction pow (man pow), qui est plus lente.

Testez votre programme avec les valeurs : -1, 0, 1, 2, 3, 8

Résultas attendus:

Entrez un nombre réel : -1
Expression 1 : -1.581977
Expression 2 : non définie
Expression 3 : -0.666667
Expression 4 : non définie

Entrez un nombre réel : 0
Expression 1 : non définie
Expression 2 : non définie
Expression 3 : -0.000000
Expression 4 : non définie

Entrez un nombre réel : 1
Expression 1 : -0.581977
Expression 2 : non définie
Expression 3 : non définie
Expression 4 : non définie

Entrez un nombre réel : 2
Expression 1 : -0.313035
Expression 2 : 10.243407
Expression 3 : non définie
Expression 4 : 0.711989

Entrez un nombre réel : 3
Expression 1 : -0.157187
Expression 2 : 8.959013
Expression 3 : non définie
Expression 4 : non définie

Entrez un nombre réel : 8
Expression 1 : -0.002685
Expression 2 : 22.137106
Expression 3 : 1.333333
Expression 4 : 1.106779

Exercice 7 : Résolution d'une équation du 3e degré
(variables, expressions arithmétiques, branchements conditionnels; niveau 2)

On veut maintenant faire un programme qui demande trois valeurs (a0, a1, a2) à l'utilisateur et affiche la (ou les) solution(s) réelle(s) z de l'équation :

z3 + a2 z2 + a1 z + a0 = 0

Indications - commencer par calculer :

Q =
R =
D = Q3 + R2

Démonstration des formules à la page : http://mathworld.wolfram.com/CubicEquation.html

Si D < 0, on calcule les trois solutions réelles ainsi :

cos-1 est la fonction acos de C, fournie par <math.h>, i.e. il faut inclure ce fichier en début de programme
z1 =
z2 =
z3 =

Sinon, on calcule :

S = la racine cubique de x est obtenue par "pow(x,1.0/3.0)" en C.
Notez que la racine cubique de (-x) est l'opposé de la racine cubique de x.
Il faut en effet traiter séparément le cas où x < 0 du cas x >= 0, car C ne l'accepte pas dans la fonction pow.
T =

Si D=0 et S+T != 0, il y a 2 racines :

z1 =
z2 = (racine double)

Sinon, il y a une racine unique : z1 ci-dessus.


Exercice 8 : Prototypes (fonctions, niveau 1, puis 2 pour les points 4 & 5)

Écrivez un programme proto.c dans lequel vous définissez une fonction demander_nombre() respectant le prototype suivant :

int demander_nombre(void);

Cette fonction doit demander un entier à l'utilisateur et retourner sa valeur.

  1. Placez la définition de la fonction avant le main().
    Faites appel à la fonction dans le main() et affichez le résultat renvoyé.

Exercice 9 : Calcul approché d'une intégrale (fonctions niveau 1)

On peut montrer que pour une fonction suffisamment régulière (disons ici C-infinie), on a la majoration suivante :
formule
où M8 est un majorant de la dérivée huitième de f sur le segment [a,b].

Écrivez un programme calculant la valeur approchée d'une intégrale à l'aide de cette formule, c'est-à-dire par :

formule

Où les valeurs a et b sont entrées par l'utilisateur.

Pour cela écrivez 3 fonctions :

  1. Une fonction f de votre choix, qui correspond à la fonction dont vous souhaitez calculer l'intégrale. (Essayez plusieurs cas avec x2, x3, ..., sin(x), 1/x, etc. Il faudra bien sûr recompiler le programme à chaque fois). Pour utiliser les fonctions mathématiques, n'oubliez pas d'ajouter
    #include <math.h>
    en début de programme et compiler avec l'option -lm.

Utilisez ces fonctions dans le main() pour réaliser votre programme.

Note : Vous pourrez trouver ici une démonstration de la formule donnée plus haut.

(Niveau Avancé)   Question subsidiaire (Niveau 3) :
Comment faire pour ne pas recompiler le programme pour chaque nouvelle fonction ?

En tant que tel, c'est-à-dire laisser l'utilisateur saisir lui-même sa formule, cela est beaucoup trop compliqué pour ce cours d'introduction.
Mais si on simplifie le problème en donnant la possibilité de choisir parmi un ensemble de fonctions préféfinies (inclues alors dans le programme), alors c'est faisable en utilisant des pointeurs sur des fonctions. Les pointeurs seront introduits en semaine 5 dans le cours, et les pointeurs sur fonction seront vus en semaine 7. Il faudra donc patienter encore un peu...


Exercice 10 : La fonction cosinus (définition et appel de fonction, niveau 2)

Écrivez le programme cos.c qui calcule une approximation de la fonction cosinus cos(x) (pour x dans [0, 2*pi])

Méthode

Pour calculer cos(x), utilisez la série définie par :

formule formule
  formule

Tâches

Écrivez les fonctions (appellées depuis la fonction cos(x))

N sera demandé en entrée à l'utilisateur dans la fonction main() (vous pouvez utiliser ici la fonction demander_nombre de l'exercice 1), puis tant que l'utilisateur n'entre pas 0.0, le programme calcule et affiche le cosinus du nombre entré.

Remarques :


Exercice 11 : Histoires de dates (structures de contrôle, fonctions, niveau 1)

[proposé par A. Perrin, 2009]

Le 31 Décembre 2008, la version 30 Go du Zune player, un lecteur audio de Microsoft, se bloquait au démarrage. La solution officielle fût d'attendre le 1er janvier. Un bug à été découvert dans la gestion des années bissextiles.

Voici le code qui se trouvait dans la version buggée du Zune player. Le nombre de jours écoulés depuis le 01/01/1980 (« l'epoch » Microsoft), à compter de 1, est enregistré dans une puce. Au démarrage, le Zune player lit le nombre de jours et le convertit en date.

    int days = 10593;       /* 31 décembre 2008, normalement lu depuis la puce */
    int year = ORIGINYEAR;  /* 1980, l'epoch pour Microsoft */

    while (days > 365) {
        if (IsLeapYear(year)) { /* 2008 est une année bissextile */
            if (days > 366) {
                days -= 366;
                year += 1;
            }
        }
        else {
            days -= 365;
            year += 1;
        }
    }
  1. Trouvez l'erreur et proposez une solution (supposez que la fonction IsLeapYear est correcte).

  2. Implémentez et vérifiez votre solution dans un nouveau programme nommé zune.c qui demande un entier supérieur ou égal à 1, représentant le nombre de jours écoulés depuis le 31/12/1979 (1 correspond au 01/01/1980 et 10593 au 31 décembre 2008), puis affiche la date correspondante sur la sortie standard.

    Exemples d'exécution :

     $ ./zune
    Entrez etc. : 10593
    31/12/2008
    
    $ ./zune
    Entrez etc. : 42
    11/02/1980
    
    $ ./zune
    Entrez etc. : 1
    01/01/1980
    
    $ ./zune
    Entrez etc. : 1337
    29/08/1983
    

    Indices :

  3. Pour continuer sur le même thème...

    Le «timestamp» UNIX est le nombre de secondes écoulées depuis le 01/01/1970 à 00:00. En utilisant la fonction time de la bibliothèque time.hman 2 time» pour plus de détails), écrivez un programme unix-time.c qui affiche la date et l'heure actuelle.

    Exemple d'exécution :

    $ ./unix-time
    1235583855 secondes se sont ecoulees depuis le 1.1.1970 a minuit.
    Nous sommes donc le 25/02/2009 a 17:44:15.
    

    Comparez la sortie de votre programme à la date actuelle. Y'a-t-il une différence ? Si oui, expliquez pourquoi.


Dernière mise à jour le 25 février 2022
Last modified: Fri Feb 25, 2022