Exercices en langage C/Structures de controle
Un livre de Wikibooks.
| Exercices en langage C |
| Sommaire |
| Livre |
| Modifier ce modèle |
Sections |
[modifier] Structures conditionnelles
[modifier] Tester votre age
Écrire un programme testage.c contenant une fonction main qui :
- lire sur le clavier l'âge de l'utilisateur avec la fonction
scanf; - teste si la réponse est valide par analyse du code retour de
scanfet teste si la valeur est comprise entre 0 et 130; - affiche si l'utilisateur est majeur (>= 18 ans) ou mineur.
/* Nom : testage.c Auteur : Thierry46 Role : Demande l'âge de l'utilisateur, teste si la réponse est valide et affiche si l'utilisateur est majeur (>= 18 ans). Paramètres : non pris en compte. Code retour : 0 (EXIT_SUCCESS) Pour produire un exécutable avec le compilateur libre GCC : gcc -Wall -std=c99 -o testage.exe testage.c Pour exécuter, tapez : ./testage.exe Version : 1.0 du 18/1/2008 Licence : GNU GPL */ #include <stdio.h> #include <stdlib.h> /* Constantes symboliques pour changement plus facile : pas besoin de chercher toutes les occurences de la constante litterale dans le corps de la fonction. */ #define AGE_MAJEUR 18 #define AGE_MINI 0 #define AGE_MAXI 130 int main(void) { // Declare les variables int ageLu = 0; int nbChampLu = 0; int codeRetour = EXIT_SUCCESS; // Valeur par defaut // Ecrit la question à l'écran (void)puts("Quel est votre age :"); // Lit la réponse de l'utilisateur : un entier nbChampLu = scanf("%d", &ageLu); // Teste si scanf a bien reussi a convertir le nombre entre if (nbChampLu != 1) { (void)fputs("\aErreur : Vous devez entrer un nombre entier !\n", stderr); codeRetour = EXIT_FAILURE; } else if (ageLu < AGE_MINI || ageLu>AGE_MAXI) { (void)fprintf(stderr, "\aErreur : Vous devez entrer un nombre entier compris entre %d et %d !\n", AGE_MINI, AGE_MAXI); codeRetour = EXIT_FAILURE; } else { // Le test se fait a l'appel de puts (void)puts((ageLu < AGE_MAJEUR) ? "Vous etes mineur !" : "Vous etes majeur !"); } return codeRetour; } // int main(...
[modifier] Structures répétitives
[modifier] Triangle d'étoiles
Compléter la fonction afficherTriangle dans le programme ci-dessous : cette fonction devra afficher un triangle rempli d'étoiles (*) sur un nombre de lignes donné passé en paramètre, exemple :
* ** *** **** ***** ****** ******* ********
- 1ère version : sans utiliser de tableau à l'aide de deux boucles for imbriquées.
- 2ème version : avec une seule boucle for et un tableau de chaîne de caractère où vous accumulerez des étoiles.
/* Nom : etoile.c Compilation : gcc -Wall -std=c99 -o etoile.exe etoile.c Exécution : ./etoile.exe */ #include <stdio.h> #include <stdlib.h> /* Nom ... : afficherTriangle Role .. : Afficher un triangle d'etoiles Parametre : nbLignes : nombre de lignes du triangle */ static void afficherTriangle(const int nbLignes) { // Partie à compléter } // static void afficherTriangle(... // Fonction principale pour test int main(void) { int nbLignes = 0; int nbChampsLu = 0; int codeRetour = EXIT_SUCCESS; (void)fputs("Lignes ? ", stdout); nbChampsLu = scanf("%u", &nbLignes); if (nbChampsLu == 1 && nbLignes > 0) { afficherTriangle(nbLignes); } else { (void)fputs("Erreur : Vous devez entrer un entier strictement positif !\n", stderr); codeRetour = EXIT_FAILURE; } return codeRetour; } // int main(...
1ère version : sans utiliser de tableau à l'aide de deux boucles for imbriquées.
/* Nom ... : afficherTriangle Role .. : Afficher un triangle d'etoiles Parametre : nbLignes : nombre de lignes du triangle Version 1 du 9/1/2008 */ static void afficherTriangle(const int nbLignes) { for (int numLigne = 1; numLigne <= nbLignes; numLigne++) { for (int numColonne = 1; numColonne <= numLigne; numColonne++) { (void)putchar('*'); } (void)putchar('\n'); } } // static void afficherTriangle(...
Remarque :
- for (int i = 0 : c'est une syntaxe introduite en C99. Avec les anciennes normes C, La variable aurait dû être déclarée hors de la boucle. Cette nouvelle syntaxe permet d'avoir des variables d'itération locales à la boucle for.
- (void)putchar('*'); : la fonction putchar retourne le caractère écrit dans le flux de sortie ou EOF en cas d'erreur. Comme j'ai décidé de ne pas utiliser ce code retour, je le signale en castant à void la fonction. L'outil qualité lint signale toute fonction retournant une valeur qui n'est pas affectée à une variable ou ignoré explicitement. Cela permet d'éviter l'erreur qui consiste à oublier de traiter un code retour de fonction.
Dans un code opérationnel robuste, tous les codes retours doivent être traités et un traitement doit être prévu en cas d'erreur. Le type void n'existait pas en C K&R.
2ème version : avec une seule boucle for et un tableau de chaîne de caractère où vous accumulerez des étoiles.
/* Nom ... : afficherTriangle Role .. : Afficher un triangle d'etoiles Parametre : nbLignes : nombre de lignes du triangle Version 2 du 9/1/2008 */ static void afficherTriangle(const int nbLignes) { // Déclaration de la chaine de caractère (voir ma remarque) char chaineEtoiles[nbLignes+1]; // Initialisation du tableau avec un terminateur de chaine chaineEtoiles[0] = '\0'; for (int numLigne = 1; numLigne <= nbLignes; numLigne++) { (void)strcat(chaineEtoiles, "*"); (void)puts(chaineEtoiles); } } // static void afficherTriangle(...
Remarque :
- Le tableau chaineEtoiles est de type VLA (Variable-Length Arrays) introduite par C99. Avec les versions de C précédente, il aurait fallu allouer dynamiquement le tableau au début du programme, puis le désalloué à la fin.
[modifier] Somme d'entiers
Ecrire un programme somme demandant à l'utilisateur de taper 10 entiers et qui affiche leur somme. Le programme ne devra utiliser que 3 variables et ne devra pas utiliser de tableau.
/* Programme : somme Role : demander 10 entiers et afficher leur somme Compilation : gcc -Wall -std=c99 -o somme.exe somme.c Execution : ./somme.exe Version 2.0 du 9/1/2008 */ #include <stdio.h> #include <stdlib.h> #define NB_ENTIERS 10 int main(void) { int valeurLue = 0; int somme = 0; // Lecture des valeurs (void)printf("Vous allez devoir entrer %d entiers\n", NB_ENTIERS); for (int i = 0; i < NB_ENTIERS ; i++) { // Demande et lecture de l'entier (void)printf("Tapez l'entier de rang %d : ", i+1); (void)scanf("%d", &valeurLue); somme = somme + valeurLue; } // for (int i = 0... // Affichage du résultat (void)printf("la somme des %d entiers vaut : %d\n", NB_ENTIERS, somme); return EXIT_SUCCESS; } // int main(...
Remarques qualité sur la correction proposée :
- Un cartouche d'entête indique des informations utiles dont les particularités de la compilation (-std=c99), la version.
- Les messages guident l'utilisateur : il sait ou il en est dans sa saisie.
- Utilisation d'une constante symbolique NB_ENTIERS au lieu de valeurs littérales 10 : si le nombre d'entier à demander change, il n'y aura qu'une seule ligne à modifier au lieu de 3 dans notre cas.
- for (int i = 0 : c'est une syntaxe autorisée en C99. Avec les anciennes normes C, La variable aurait dû être déclarée hors de la boucle. Cette nouvelle syntaxe permet d'avoir des variables d'itération locales à la boucle for.
- (void)printf(... : la fonction printf retourne le nombre de caractères écrit dans le flux de sortie. Comme j'ai décidé de ne pas utiliser ce code retour, je le signale en castant à void la fonction. L'outil qualité lint signale toute fonction retournant une valeur qui n'est pas affectée à une variable ou ignoré explicitement. Cela permet d'éviter l'erreur qui consiste à oublier de traiter un code retour de fonction.
- Le code retour de scanf est ignoré. Il renvoie le nombre de valeurs correctement récupérée. Dans un code opérationnel robuste, tous les codes retours doivent être traités et un traitement doit être prévu en cas d'erreur. Le type void n'existait pas en C K&R.

