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

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
Thierry46 (discussion | contributions)
→‎Solution proposée : Simplification malloc -> realloc(NULL, suppresion tabulation.
Thierry46 (discussion | contributions)
→‎Éléments fournis : free(NULL) autorisé par la norme + indentation
Ligne 60 : Ligne 60 :


===Éléments fournis===
===Éléments fournis===
<div style="width:70%">{{Boîte déroulante|titre=lire_ligne.c à compléter|contenu =
<div style="width:100%">{{Boîte déroulante|titre=lire_ligne.c à compléter|contenu =
<source lang="c">
<source lang="c">
/**
/**
Ligne 121 : Ligne 121 :
}} </div>
}} </div>


<div style="width:70%">{{Boîte déroulante|titre=lire_ligne.h|contenu =
<div style="width:100%">{{Boîte déroulante|titre=lire_ligne.h|contenu =
<source lang="c">
<source lang="c">
/*
/*
Ligne 157 : Ligne 157 :
}} </div>
}} </div>


<div style="width:70%">{{Boîte déroulante|titre=main_lire_ligne.c|contenu =
<div style="width:100%">{{Boîte déroulante|titre=main_lire_ligne.c|contenu =
<source lang="c">
<source lang="c">
/*
/*
Ligne 163 : Ligne 163 :
* Role ........ : Tester la fonction lire_ligne
* Role ........ : Tester la fonction lire_ligne
* Parametre ... : Aucun
* Parametre ... : Aucun
* Code retour . : EXIT_SUCESS (0)
* Code retour . : EXIT_SUCESS (0)
* Auteur ...... : Thierry46
* Auteur ...... : Thierry46
* Version ..... : 1.0 du 30/1/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 184 : Ligne 184 :
*
*
* Compilation . :
* Compilation . :
* Voir lire_ligne .c pour sa compilation
* Voir lire_ligne .c pour sa compilation
* gcc -pedantic -Wall -std=c99 -o test_lire_ligne.exe main_lire_ligne.c lire_ligne.o
* gcc -pedantic -Wall -std=c99 -o test_lire_ligne.exe main_lire_ligne.c lire_ligne.o
* Exécution : ./test_lire_ligne.exe
* Exécution : ./test_lire_ligne.exe
* Fichiers lies : lire_ligne.c, lire_ligne.h, test_lire_ligne.txt
* Fichiers lies : lire_ligne.c, lire_ligne.h, test_lire_ligne.txt
Ligne 201 : Ligne 201 :
int main(void)
int main(void)
{
{
FILE *hFicTest = NULL;
FILE *hFicTest = NULL;
char *chaine = NULL;
char *chaine = NULL;
int numLigne = 1;
int numLigne = 1;
int retour = EXIT_SUCCESS;
int retour = EXIT_SUCCESS;
char message[TAILLE_MAX_MESSAGE];
char message[TAILLE_MAX_MESSAGE];
hFicTest = fopen(FIC_TEST, "r");
hFicTest = fopen(FIC_TEST, "r");
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 etre 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. //
}
}
do
do
{
{
chaine = lire_ligne(TAILLE_BUFFER, hFicTest, &retour);
chaine = lire_ligne(TAILLE_BUFFER, hFicTest, &retour);
if (retour == EXIT_SUCCESS)
if (retour == EXIT_SUCCESS)
{
{
(void)strncpy(message, "Pas d'erreur", sizeof(message) - 1);
(void)strncpy(message, "Pas d'erreur", sizeof(message) - 1);
}
}
else if (retour == EOF)
else if (retour == EOF)
{
{
(void)strncpy(message, "Fin de fichier", sizeof(message) - 1);
(void)strncpy(message, "Fin de fichier", sizeof(message) - 1);
}
}
else
else
{
{
(void)strncpy(message, strerror(retour), sizeof(message) - 1);
(void)strncpy(message, strerror(retour), sizeof(message) - 1);
}
}
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), chaine lue = \"%s\".\n",
numLigne, retour, message,
numLigne, retour, message,
(chaine == NULL) ? "! Pointeur NULL !" : chaine);
(chaine == NULL) ? "! Pointeur NULL !" : chaine);


free(chaine);
if (chaine != NULL)
chaine = NULL;
{
} while (retour == EXIT_SUCCESS);
free(chaine);
chaine = NULL;
if (hFicTest != NULL)
}
{
} while (retour == EXIT_SUCCESS);
(void)fclose(hFicTest);
}
if (hFicTest != NULL)
{
return EXIT_SUCCESS;
(void)fclose(hFicTest);
}
return EXIT_SUCCESS;
} // int main(void)
} // int main(void)
</source>
</source>
}} </div>
}} </div>


<div style="width:70%">{{Boîte déroulante|titre=test test_lire_ligne.txt|contenu =
<div style="width:100%">{{Boîte déroulante|titre=test test_lire_ligne.txt|contenu =
<pre>
<pre>
1
1

Version du 4 février 2008 à 23:14

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

Filtre qui passe le texte en majuscule

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 getchar, putchar (stdio.h) et toupper (ctypes.h).

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

majuscule.exe < majuscule.c

Solution proposée


Lire une ligne longue avec fgets

Problème à résoudre

La fonction fgets de la bibliothèque standard du langage C permet de lire une chaine 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, chaines 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

Solution proposée

Remarques sur l'exercice

  • 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 programmeurs.
  • 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) facilite la tâche du programmeurs.
  • En Java des classes comme String et StringBuffer prennent en charge les chaines de caractères longues.