Programmation en C: Série 1

Préparation

Démarrez l'ordinateur sous Linux (Ubuntu).

Lancez le logiciel Geany, et crééz un nouveau fichier. Copiez le code suivant dans ce fichier, et sauvegardez-le sous lucky.c dans votre dossier MyFiles:

			#include <stdio.h>
			#include <stdlib.h>
			#include <time.h>

			int main(int argc, char * argv[]) {
				// Initialisation du générateur de nombres aléatoires
				srandom(time(NULL));

				// Générer deux nombres aléatoires entre 1 et 6
				int d1 = 1 + random() % 6;
				int d2 = 1 + random() % 6;

				// Afficher les nombres
				printf("Vous avez lancé un %d et un %d.\n", d1, d2);
				return 0;
			}
		

Exécuter depuis le terminal

En bas de la fenêtre Geany, vous trouvez le Terminal. Pour compiler et exécuter ce programme, tapez les commandes suivanes (après les ">>"):

		# Naviguer dans le bon répertoire
		$$ cd Desktop
		$$ cd MyFiles

		# Compiler lucky.c → lucky, et l'exécuter
		$$ gcc -Wall -lm lucky.c -o lucky
		$$ ./lucky
		Vous avez lancé un 4 et un 2.

Exécuter avec les boutons

Geany propose des boutons pour compiler (build) et exécuter (run) le programme:

Geany Buttons

Pour utiliser ces boutons, vérifiez la configuration sous BuildSet Build Commands:

C commands
Compile gcc -Wall -c "%f"
Build gcc -Wall -o "%e" "%f" -lm
Execute commands
Execute "./%e"

Exercice 1: lancer des dés

Modifiez le programme ci-dessus pour qu'il affiche:

  1. Vous avez gagné! si on a lancé deux 6,
  2. Pas mal! si on a lancé deux fois le même nombre,
  3. Pas de chance! sinon.
			#include <stdio.h>
			#include <stdlib.h>
			#include <time.h>

			int main(int argc, char * argv[]) {
				srandom(time(NULL));

				int d1 = 1 + random() % 6;
				int d2 = 1 + random() % 6;
				printf("Vous avez lancé un %d et un %d.\n", d1, d2);

				if (d1 == 6 && d2 == 6) {
					printf("Vous avez gagné!\n");
				} else if (d1 == d2) {
					printf("Pas mal!\n");
				} else {
					printf("Pas de chance!\n");
				}

				return 0;
			}
		

Exercice 2: les nombres pairs

En utilisant une boucle for ou une boucle while:

  1. Ecrivez un programme qui affiche les nombres pairs de 0 à 20 (y compris).
  2. Calculez et affichez la somme des ces nombres.
			#include <stdio.h>

			int main(int argc, char * argv[]) {
				int sum = 0;
				for (int i = 0; i <= 20; i += 2) {
					printf("%d\n", i);
					sum += i;
				}

				printf("La somme est %d.\n", sum);
				return 0;
			}
		

Exercice 3: le cylindre

  1. Ecrivez un programme qui calcule et affiche le volume d'un cylindre de rayon r = 0.8 et de hauteur h = 2.5. (formules, π)
  2. Ecrivez une fonction qui calcule le volume d'un cylindre de rayon r et de hauteur h. Appelez cette fonction pour calculer le volume et affichez le résultat.
			#include <stdio.h>
			#include <math.h>

			int main(int argc, char * argv[]) {
				double r = 0.8;
				double h = 2.5;
				double volume = M_PI * r * r * h;
				// ou: double volume = M_PI * pow(r, 2) * h;
				printf("Volume du cylindre: %f\n", volume);
				return 0;
			}
		
			#include <stdio.h>
			#include <math.h>

			double volumeCylindre(double r, double h) {
				return M_PI * r * r * h;
			}

			int main(int argc, char * argv[]) {
				double volume = volumeCylindre(0.8, 2.5);
				printf("Volume du cylindre: %f\n", volume);
				return 0;
			}
		

Exercice 4: le niveau du lac de Thoune (env. 10 à 20 lignes de code)

Le niveau du lac de Thoune monte et descend en fonction de la quantité d'eau

Simulez le niveau du lac de Thoune sur 2 jours (48 heures) avec des pas d'une heure et les paramètres suivants:

Surface du lac 47.69 km2
Niveau du lac 557.326 m au début de la simulation
Affluant Aar: 13 m3/s
Kander: 6 m3/s
Effluant Le débit de l'effluent dépend du niveau du lac. On utilise l'approximation suivante:
effluent = (niveau - 557.05 m)2 · 250 m/s [m3/s]

On ignore les autres sources (par ex. pluie) et fuites (par ex. evaporation) d'eau.

Pour chaque heure, ajoutez et enlèvez de l'eau correspondante du lac, et mettez à jour le niveau du lac.

Vérification: avec les paramètres indiques, la variation du niveau est < 1 mm en 48 heures.

Avec quelques petites modifications, vous pouvez simuler plusieurs scénarios:

  1. Si le niveau de départ était 557.500 m, quel serait le niveau après 48 heures? après 96 heures?
  2. En été, la Kander verse 40 m3/s et l'Aar 110 m3/s en moyenne dans le lac. Quel est le niveau du lac en été selon notre modèle? (Astuce: pour arriver à un niveau stable, on doit simuler environ 10 jours.)
  3. Après des pluies abondantes en été (niveau normal: 557.83 m), la Kander verse 101 m3/s pendant 24 heures dans le lac, suivi par 83 m3/s pendant les 24 heures suivantes. A quel niveau l'eau monte après ces 48 heures? Quel est le débit maximal de l'effluent?

Pour tracer des diagrammes du niveau, vous pouvez copier-coller les résultats dans LibreOffice Calc, Apple Numbers, ou Microsoft Excel. Pour afficher un diagramme depuis le terminal, vous pouvez rediriger la sortie dans un fichier:

$$ ./lac > resultats

puis le plotter avec gnuplot:

$$gnuplot
plot "resultats" using 1 with lines
quit
			#include <stdio.h>
			#include <math.h>

			int main(int argc, char * argv[]) {
				// Conditions au départ
				double surface = 47.69e6;
				double niveau = 557.326;

				// Evolution heure par heure
				for (int i = 0; i < 48; i++) {
					// Effluant en m³/s
					double outflow = pow(niveau - 557.05, 2.0) * 250;

					// Affluant Aare + Kander en m³/s
					double inflow = 13 + 6;

					// Mettre à jour le niveau
					double volumeDifference = (inflow - outflow) * 3600;
					niveau = niveau + volumeDifference / surface;

					// Affichage
					printf("%4d\t%0.6f\t%0.6f\t%0.6f\n", i + 1, niveau, inflow, outflow);
				}

				return 0;
			}
		
   0	557.325997	19.000000	19.044000
   1	557.325993	19.000000	19.043542
   2	557.325990	19.000000	19.043088
   3	557.325987	19.000000	19.042639
   4	557.325984	19.000000	19.042195
   5	557.325981	19.000000	19.041756
   6	557.325977	19.000000	19.041321
   7	557.325974	19.000000	19.040890
   8	557.325971	19.000000	19.040464
   9	557.325968	19.000000	19.040043
  10	557.325965	19.000000	19.039626
  11	557.325962	19.000000	19.039213
  12	557.325959	19.000000	19.038804
  13	557.325957	19.000000	19.038400
  14	557.325954	19.000000	19.038000
  15	557.325951	19.000000	19.037605
  16	557.325948	19.000000	19.037213
  17	557.325945	19.000000	19.036825
  18	557.325942	19.000000	19.036442
  19	557.325940	19.000000	19.036062
  20	557.325937	19.000000	19.035687
  21	557.325934	19.000000	19.035315
  22	557.325932	19.000000	19.034947
  23	557.325929	19.000000	19.034583
  24	557.325927	19.000000	19.034223
  25	557.325924	19.000000	19.033867
  26	557.325921	19.000000	19.033514
  27	557.325919	19.000000	19.033165
  28	557.325916	19.000000	19.032819
  29	557.325914	19.000000	19.032478
  30	557.325912	19.000000	19.032139
  31	557.325909	19.000000	19.031805
  32	557.325907	19.000000	19.031474
  33	557.325904	19.000000	19.031146
  34	557.325902	19.000000	19.030821
  35	557.325900	19.000000	19.030500
  36	557.325898	19.000000	19.030183
  37	557.325895	19.000000	19.029869
  38	557.325893	19.000000	19.029558
  39	557.325891	19.000000	19.029250
  40	557.325889	19.000000	19.028945
  41	557.325887	19.000000	19.028644
  42	557.325884	19.000000	19.028345
  43	557.325882	19.000000	19.028050
  44	557.325880	19.000000	19.027758
  45	557.325878	19.000000	19.027469
  46	557.325876	19.000000	19.027183
  47	557.325874	19.000000	19.026900
			#include <stdio.h>
			#include <math.h>

			// Variable globale
			double surface = 47.69e6;

			// Fonction pour avancer la simulation de plusieurs heures à débit constant
			double avancerSimulation(double niveau, int heures, double inflow) {
				for (int i = 0; i < heures; i++) {
					double outflow = pow(niveau - 557.05, 2.0) * 250;
					niveau = niveau + (inflow - outflow) * 3600 / surface;
				}

				return niveau;
			}

			int main(int argc, char * argv[]) {
				// Simulation de base
				double niveau = avancerSimulation(557.326, 48, 13 + 6);
				printf("Après 48 heures: %0.6f\n", niveau);

				// Scénario: niveau de départ plus haut
				double niveauA48 = avancerSimulation(557.5, 48, 13 + 6);
				double niveauA96 = avancerSimulation(niveauA48, 48, 13 + 6);
				printf("A après 48 heures: %0.6f\n", niveauA48);
				printf("A après 96 heures: %0.6f\n", niveauA96);

				// Scénario: été
				double niveauB = avancerSimulation(557.326, 240, 110 + 40);
				printf("B après 10 jours (240 heures): %0.6f\n", niveauB);

				// Scénario: après une pluie
				double niveauC24 = avancerSimulation(557.83, 24, 110 + 101);
				double niveauC48 = avancerSimulation(niveauC24, 24, 110 + 83);
				printf("C après 48 heures: %0.6f\n", niveauC48);

				return 0;
			}
		
Après 48 heures: 557.325874
A après 48 heures: 557.419350
A après 96 heures: 557.378774
B après 10 jours (240 heures): 557.823996
C après 48 heures: 557.918693