1. Manipulation des chaînes de caractères.
Pour la manipulation des chaînes de caractères, il est
possible d'utiliser les fonctions suivantes, accessibles grâce à l'inclusion
du fichier string.h en début de programme :
- char *strcpy(char *ch1,const char *ch2)
Cette fonction copie la chaîne pointée par ch2 (\0 compris)
à l'adresse ch1, et renvoie ch1
- char *strncpy(char *ch1,const char *ch2,size_t n)
Cette fonction copie exactement n caractères de la chaîne pointée par ch2
à l'adresse ch1,
en tronquant la chaîne pointée par ch2 ou en la complétant par des caractères
\0 si besoin est, et renvoie ch1
Cette fonction ne termine pas systématiquement la copie par un caractère \0,
donc après un appel à strncpy, le premier paramètre qui a été passé n'est pas forcément
une chaîne de caractères, alors qu'après un appel à la fonction strcpy,
le premier paramètre qui a été passé est forcément une chaîne de caractères.
- char *strcat(char *ch1,const char *ch2)
Cette fonction concatène la chaîne pointée par ch2 (caractère
\0 compris) à la chaîne pointée par ch1,
et renvoie ch1
- char *strncat(char *ch1,const char *ch2,size_t n)
Cette fonction concatène les n premiers caractères
(ou tous les caractères, si ch2 a moins de n caractères)
de la chaîne pointée par ch2 (suivis d'un caractère \0)
à la chaîne pointée par ch1, et renvoie ch1
- int strcmp(const char *ch1,const char *ch2)
Cette fonction compare les chaînes pointées par ch1 et ch2, caractère
par caractère, et renvoie une valeur négative si ch1
est avant ch2 dans l'ordre des codes ASCII, 0
si ch1 et ch2 sont identiques, et une valeur
positive si ch1 est après ch2
- int strncmp(const char *ch1,const char *ch2,size_t n)
Cette fonction compare les chaînes pointées par ch1 et de ch2,
sur les n premiers caractères, et renvoie une valeur
négative si ch1 est avant ch2 dans l'ordre
des codes ASCII, 0 si ch1 et ch2
sont identiques, et une valeur positive si ch1 est après
ch2
- size_t strlen(const char *ch)
Cette fonction retourne la longueur de la chaîne pointée par ch,
caractère \0 exclu.
2. Exercice 1.
Écrire un programme qui inverse une chaîne de caractères
tapée au clavier par l'utilisateur, en utilisant les fonctions de manipulation de chaînes
présentes dans la bibliothèque de fonctions string.h. On déclarera dans le programme principal trois tableaux de
caractères :
#include <stdio.h>
#include <string.h>
#define MAX 100
int main(void)
{
- char texte[MAX+1],texte_inverse[MAX+1],chaine[2];
- ...
}
Remarques :
-
Le tableau de caractères chaine servira
à contenir successivement chaque caractère de texte,
complété par le caractère \0
-
On demande de ne pas utiliser d'instruction d'affectation des deux types suivants :
3. Exercice 2.
Répondre à la même question que l'exercice 1, en utilisant une liste chaînée pour enregistrer
la chaîne de caractères. Chaque élément de la
liste contiendra un caractère et un pointeur vers le caractère
suivant :
struct texte
{
- char car;
- struct texte *p_suivant;
};
On commencera par lire la chaîne de caractères et par
créer la liste chaînée par ajouts successifs d'éléments en queue, en veillant à ne pas
allouer d'espace mémoire superflu (le nombre de structures
créées doit être égal au nombre de caractères
de la chaîne). Ensuite, on affichera le contenu de la liste chaînée,
en guise de vérification. Enfin, on inversera les valeurs des champs
car deux à deux, en procédant de la
manière suivante :
- Échanger les valeurs des champs car
du premier élément et du dernier élément de
la liste chaînée.
- Répéter cet échange pour le successeur du premier
élément et pour le prédécesseur du dernier
élément, jusqu'à la "rencontre".
Remarques :
- Le chaînage ne doit pas être modifié.
- Pour passer du dernier élément à son prédécesseur
dans la liste chaînée, on se placera au début de la
liste chaînée, et on effectuera un nombre de "sauts"
décrémenté de un par rapport au nombre d'éléments
de la liste.
Contrôle des allocations dynamiques :
Dans le but de contrôler si la gestion des allocations dynamiques a été correctement effectuée,
on demande de rajouter à ce programme :
- La déclaration des deux variables globales suivantes :
int cpt_malloc=0,cpt_free=0;
- Une incrémentation de la variable globale cpt_malloc après chaque
appel à la fonction malloc, et une incrémentation de la variable globale
cpt_free après chaque appel à la fonction free
- La séquence suivante, à la fin de la fonction main :
if (cpt_free==cpt_malloc)
{
- fprintf(stderr,"Mémoire correctement gérée :\n");
- fprintf(stderr,"%d allocations dynamiques.\n",cpt_malloc);
- exit(0);
}
else
{
- fprintf(stderr,"Mauvaise gestion des allocations dynamiques !\n");
- exit(1);
}
4. Exercice 3.
Répondre à la même question que précédemment, en utilisant une liste chaînée du type défini
plus haut, puis en reconstruisant le chaînage à l'envers,
et enfin en affichant le nouveau chaînage.
Attention :
Dans ce dernier programme, on ne fera aucune nouvelle allocation
de mémoire, lors de la création de la nouvelle liste chaînée.
Ces pages ont été réalisées
par A. Crouzil, J.D. Durou et Ph. Joly.
Pour tout commentaire, envoyer un mail à
crouzil@irit.fr, à durou@irit.fr ou à Philippe.Joly@irit.fr.