« Exercices en langage C/Fonctions » : différence entre les versions

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
DannyS712 (discussion | contributions)
m <source> -> <syntaxhighlight> (phab:T237267)
Aucun résumé des modifications
 
Ligne 7 : Ligne 7 :
==Filtre qui passe le texte en majuscule==
==Filtre qui passe le texte en majuscule==
===Problème à résoudre===
===Problème à résoudre===
Ecrivez un programme majuscule.c qui lit des données sur le flux stdin et écrits sur stdout après avoir transformé les caractères lus en majuscules. Vous utiliserez les fonctions <code>getchar</code>, <code>putchar</code> (stdio.h) et <code>toupper</code> (ctype.h).
Écrivez un programme majuscule.c qui lit des données sur le flux stdin et écrits sur stdout après avoir transformé les caractères lus en majuscules. Vous utiliserez les fonctions <code>getchar</code>, <code>putchar</code> (stdio.h) et <code>toupper</code> (ctype.h).


Vous testerez votre programme en lui faisant convertir son propre fichier source majuscule.c.
Vous testerez votre programme en lui faisant convertir son propre fichier source majuscule.c.
Ligne 17 : Ligne 17 :
/**
/**
* Programme . : majuscule
* Programme . : majuscule
* Role ...... : convertit les caractéres lus sur stdin en majuscule.
* Rôle ...... : convertit les caractères lus sur stdin en majuscule.
* Parametres : Aucun
* Paramètres : Aucun
* Compilation et EDL : gcc -Wall -o majuscule.exe majuscule.c
* Compilation et EDL : gcc -Wall -o majuscule.exe majuscule.c
* Auteur ...... : Thierry46
* Auteur ...... : Thierry46
Ligne 45 : Ligne 45 :


===Problème à résoudre===
===Problème à résoudre===
La fonction <code>fgets</code> de la bibliothèque standard du langage C permet de lire une chaine de caractère de longueur limitée dans un flux.
La fonction <code>fgets</code> de la bibliothèque standard du langage C permet de lire une chaîne de caractère de longueur limitée dans un flux.


Vous allez compléter une fonction ''lire_ligne'' répondant au spécifications suivantes :
Vous allez compléter une fonction ''lire_ligne'' répondant au spécifications suivantes :
Ligne 52 : Ligne 52 :
* La longueur des lignes lues n'est pas limitée.
* La longueur des lignes lues n'est pas limitée.
* Contrôle des paramètres et retour des codes d'erreurs systèmes, détection de la fin du fichier.
* Contrôle des paramètres et retour des codes d'erreurs systèmes, détection de la fin du fichier.
* Vous utiliserez au maximum les fonctions de la bibliothèque standard du langage C : allocation mémoire, chaines de caractères...
* Vous utiliserez au maximum les fonctions de la bibliothèque standard du langage C : allocation mémoire, chaînes de caractères...
* Son prototype est donné par ''lire_ligne.h''.
* Son prototype est donné par ''lire_ligne.h''.
* Vous utiliserez le programme de ''main_lire_ligne.c'' pour lire_ligne.
* Vous utiliserez le programme de ''main_lire_ligne.c'' pour lire_ligne.
Ligne 63 : Ligne 63 :
/**
/**
* Fonction .. : lire_ligne
* Fonction .. : lire_ligne
* Role ...... : tente de lire une ligne entiere depuis le flux.
* Rôle ...... : tente de lire une ligne entière depuis le flux.
* - Le caractere de saut de ligne '\n' final est enleve.
* - Le caractère de saut de ligne '\n' final est enlève.
* - L'appellant doit se charger de la desallocation de la chaine retournee.
* - L’appelant doit se charger de la désallocation de la chaîne retournée.
*
*
* Parametres :
* Paramètres :
* - pChaine : adresse de retour de la chaine
* - pChaine : adresse de retour de la chaîne
* - tailleBufferLecture : taille du buffer de lecture,
* - tailleBufferLecture : taille du buffer de lecture,
* dans la pratique on pourra choisir _POSIX_MAX_INPUT (ref limits.h).
* dans la pratique on pourra choisir _POSIX_MAX_INPUT (ref limits.h).
* - flux : un pointeur sur le descripteur du fichier a lire.
* - flux : un pointeur sur le descripteur du fichier a lire.
*
*
* - Valeur retournee :
* - Valeur retournée :
* - Si OK : EXIT_SUCCESS.
* - Si OK : EXIT_SUCCESS.
* - Si Fin de fichier atteinte sans rencontrer \n : EOF,
* - Si Fin de fichier atteinte sans rencontrer \n : EOF,
* - la chaine retournée contient le debut de la ligne longue.
* - la chaîne retournée contient le début de la ligne longue.
* - Si rien a lire, retour d'un pointeur NULL pour la chaine.
* - Si rien a lire, retour d'un pointeur NULL pour la chaîne.
* - En cas de probleme : Le code d'erreur systeme utilisable par perror.
* - En cas de problème : Le code d'erreur système utilisable par perror.
* et retour d'un pointeur NULL pour la chaine.
* et retour d'un pointeur NULL pour la chaîne.
*
*
* Auteur ...... : Votre nom
* Auteur ...... : Votre nom
Ligne 124 : Ligne 124 :
/*
/*
* Nom .... : lire_ligne.h
* Nom .... : lire_ligne.h
* Role ... : Definitions et prototype de lire_ligne.h
* Rôle ... : Définitions et prototype de lire_ligne.h
* Auteur ...... : Thierry46
* Auteur ...... : Thierry46
* Version ..... : 1.0 du 30/1/2008
* Version ..... : 1.0 du 30/1/2008
Ligne 160 : Ligne 160 :
/*
/*
* Nom ......... : main_lire_ligne.c
* Nom ......... : main_lire_ligne.c
* Role ........ : Tester la fonction lire_ligne
* Rôle ........ : Tester la fonction lire_ligne
* Parametre ... : Aucun
* Paramètre ... : Aucun
* Code retour . : EXIT_SUCESS (0)
* Code retour . : EXIT_SUCESSS (0)
* Auteur ...... : Thierry46
* Auteur ...... : Thierry46
* Version ..... : 1.1 du 4/2/2008
* Version ..... : 1.1 du 4/2/2008
* Licence ..... : GNU GPL.
* Licence ..... : GNU GPL.
lire_ligne : Lecture d'une ligne longue dans un fichier texte
lire_ligne : Lecture d'une ligne longue dans un fichier texte
Copyright (C) 2008 Thierry46
Copyright (C) 2008 Thierry46
Ligne 209 : Ligne 209 :
if (hFicTest == NULL)
if (hFicTest == NULL)
{
{
(void)printf("%s : le fichier %s n'a pas pu etre ouvert !\n",
(void)printf("%s : le fichier %s n'a pas pu être ouvert !\n",
__func__, FIC_TEST);
__func__, FIC_TEST);
// Je laisse poursuivre pour tester assertion dans lire_ligne. //
// Je laisse poursuivre pour tester assertion dans lire_ligne. //
Ligne 231 : Ligne 231 :
message[sizeof(message) - 1] = '\0';
message[sizeof(message) - 1] = '\0';
(void)printf("Ligne %d : retour = %d (%s), chaine lue = \"%s\".\n",
(void)printf("Ligne %d : retour = %d (%s), chaîne lue = \"%s\".\n",
numLigne, retour, message,
numLigne, retour, message,
(chaine == NULL) ? "! Pointeur NULL !" : chaine);
(chaine == NULL) ? "! Pointeur NULL !" : chaine);
Ligne 265 : Ligne 265 :
/**
/**
* Fonction .. : lire_ligne
* Fonction .. : lire_ligne
* Role ...... : tente de lire une ligne entiere depuis le flux.
* Rôle ...... : tente de lire une ligne entière depuis le flux.
* - Le caractere de saut de ligne '\n' final est enleve.
* - Le caractère de saut de ligne '\n' final est enleve.
* - L'appellant doit se charger de la desallocation de la chaine retournee.
* - L’appelant doit se charger de la désallocation de la chaîne retournée.
*
*
* Parametres :
* Paramètres :
* - pChaine : adresse de retour de la chaine
* - pChaine : adresse de retour de la chaîne
* - tailleBufferLecture : taille du buffer de lecture,
* - tailleBufferLecture : taille du buffer de lecture,
* dans la pratique on pourra choisir _POSIX_MAX_INPUT (ref limits.h).
* dans la pratique on pourra choisir _POSIX_MAX_INPUT (ref limits.h).
* - flux : un pointeur sur le descripteur du fichier a lire.
* - flux : un pointeur sur le descripteur du fichier a lire.
*
*
* - Valeur retournee :
* - Valeur retournée :
* - Si OK : EXIT_SUCCESS.
* - Si OK : EXIT_SUCCESS.
* - Si Fin de fichier atteinte sans rencontrer \n : EOF,
* - Si Fin de fichier atteinte sans rencontrer \n : EOF,
* - la chaine retournée contient le debut de la ligne longue.
* - la chaîne retournée contient le début de la ligne longue.
* - Si rien a lire, retour d'un pointeur NULL pour la chaine.
* - Si rien a lire, retour d'un pointeur NULL pour la chaîne.
* - En cas de probleme : Le code d'erreur systeme utilisable
* - En cas de problème : Le code d'erreur système utilisable
* par perror et retour d'un pointeur NULL pour la chaine.
* par perror et retour d'un pointeur NULL pour la chaîne.
*
*
* Auteur ...... : Thierry46
* Auteur ...... : Thierry46

Version actuelle du 22 juillet 2022 à 19:09

Ces exercices concernent l'utilisation des fonctions de la bibliothèque standard du langage C.

Filtre qui passe le texte en majuscule[modifier | modifier le wikicode]

Problème à résoudre[modifier | modifier le wikicode]

Écrivez un programme majuscule.c qui lit des données sur le flux stdin et écrits sur stdout après avoir transformé les caractères lus en majuscules. Vous utiliserez les fonctions getchar, putchar (stdio.h) et toupper (ctype.h).

Vous testerez votre programme en lui faisant convertir son propre fichier source majuscule.c.

majuscule.exe < majuscule.c

Solution proposée[modifier | modifier le wikicode]

Lire une ligne longue avec fgets[modifier | modifier le wikicode]

Problème à résoudre[modifier | modifier le wikicode]

La fonction fgets de la bibliothèque standard du langage C permet de lire une chaîne de caractère de longueur limitée dans un flux.

Vous allez compléter une fonction lire_ligne répondant au spécifications suivantes :

  • Retour d'une ligne lue dans un flux texte passé en paramètre.
  • Vous éliminerez les caractères de saut de ligne lus.
  • La longueur des lignes lues n'est pas limitée.
  • Contrôle des paramètres et retour des codes d'erreurs systèmes, détection de la fin du fichier.
  • Vous utiliserez au maximum les fonctions de la bibliothèque standard du langage C : allocation mémoire, chaînes de caractères...
  • Son prototype est donné par lire_ligne.h.
  • Vous utiliserez le programme de main_lire_ligne.c pour lire_ligne.
  • Vous devrez traiter le fichier test_lire_ligne.txt fourni.
  • Les instructions de compilation et d'édition de lien sont dans les commentaires des fichiers fournis.

Éléments fournis[modifier | modifier le wikicode]

Solution proposée[modifier | modifier le wikicode]

Remarques sur l'exercice[modifier | modifier le wikicode]

  • Le test des paramètres dans la solution est expéditif.
  • Pour obtenir des programmes robustes, le langage C oblige à une gestion pénible des erreurs. Avec le langage Java par exemple, les mécanismes d'exception facilitent la tâche du programmeur.
  • L'utilisation de l'allocation dynamique de mémoire est risquée : fuite mémoire. Avec le langage Java par exemple, le ramasse miettes (Garbage collector) se charge de la libération de la mémoire.
  • En Java des classes comme String et StringBuffer prennent en charge les chaines de caractères longues.

Test d'un générateur de nombre aléatoire[modifier | modifier le wikicode]

Problème à résoudre[modifier | modifier le wikicode]

La bibliothèque standard du langage C offre au programmeur plusieurs fonctions pour générer des nombres aléatoires. La plus connue est rand().

Vous allez écrire un programme verifrand.c qui estime la répartition des nombres aléatoires générés : moyenne et dispersion. Nous allons traiter l'ensemble des nombres générés comme une série discrète regroupée.

  1. Générez 1 million (NB_TIRAGE) notes (xi) entre 0 et 20 (N) comprises (NB_NOTE = 21) à l'aide de la fonction rand().
  2. Répartissez-les dans le tableau effectif (n) où ni représente l'effectif (nombre d'occurrences cumulées) de la note xi.
  3. calculez et affichez la moyenne arithmétique :
  4. calculez et affichez l'écart moyen de la série :

Solution proposée[modifier | modifier le wikicode]

Remarques sur l'exercice[modifier | modifier le wikicode]

  • La série générée avec rand() sur ma machine est bien centrée sur la moyenne théorique 10/20 : les nombres de notes en dessous et au dessus de 10 sont quasi-identiques. L'écart moyen de la série est proche de 5 ce qui indique que les notes sont bien réparties.
  • La fonction rand() est pseudo-aléatoire : deux exécutions du programme donnent exactement la même série de note.
  • Vous pouvez tester d'autres fonctions comme random() ou arc4random(). Cette dernière, de qualité cryptographique, utilise l'algorithme nommé ARC4. Elle est aléatoire.