Tableau de caracteres et pointeurs
Le
bpascal123
Bonjour,
J'apprends le C à partir d'un tutorial en ligne. Je n'arrive pas à un
résultat pour un exercice dont la solution de l'auteur ne fonctionne
pas non plus. Vous pouvez voir sur l'exercice et la solution que je ne
parviens pas à implémenter sur http://www.ltam.lu/cours-c// ex.
9.22.
Voici le code qui ne veut pas tourner alors que ça me semble cohérent.
J'y ajoute des fonctions car j'ai déjà parcouru le chapitre fonction
et j'essaie de résoudre les questions de l'allocation dynamique avec
les difficultés du chapitre des fonctions
/*
Ecrire un programme qui lit 4 mots au clavier (longueur maximale: 10
caractères) et attribue leurs adresses à un tableau de pointeurs pMot.
Copier les mots selon l'ordre lexicographique en une seule 'phrase'
dont l'adresse est affectée à un pointeur pPhr. Réserver l'espace
nécessaire à la PHRASE avant de copier les mots. Libérer la mémoire
occupée par chaque mot après l'avoir copié. Utiliser les fonctions de
<string>.
*/
#include <stdio.h> /* printf fgets */
#include <stdlib.h> /* malloc */
#include <string.h> /* strlen strcpy strcmp strcat */
#define MAXLIG 4 /* nbr de ligne max */
#define MAXLET 10 /* nbr de lettre max */
void ReadPhr(char *fpPhr[], int nmax) ;
void WritePhr(char *fpPhr[], int nmax) ;
void WriteMot(char *fpPhr[], char *fpMot, int nmax) ;
void AlphaPhr(char *fpPhr[], int nmax) ;
int main(void)
{
char *pPhr[MAXLIG] ;
char *pMot = 0 ;
ReadPhr(pPhr, MAXLIG) ;
WritePhr(pPhr, MAXLIG) ;
AlphaPhr(pPhr, MAXLIG) ;
WriteMot(pPhr, pMot, MAXLIG) ;
printf("") ;
return 0 ;
}
void ReadPhr(char *fpPhr[], int nmax)
{
char Intro[MAXLET] ;
int i ;
printf("Entrez des mots, fin avec [enter] : ") ;
for ( i = 0 ; i < nmax ; i++ )
{
printf("Entree %d%s : ", i+1, (i == 0) ? "ere" : "eme") ;
fgets(Intro, MAXLET, stdin) ;
*(fpPhr+i) = malloc( strlen(Intro)+1) ;
if ( *(fpPhr+i ) )
strcpy( *(fpPhr+i), Intro ) ;
else
{
printf("Allocation error") ;
exit(-1) ;
}
}
}
void WritePhr(char *fpPhr[], int nmax)
{
int i ;
printf("AFFICHAGE : ") ;
for ( i = 0 ; i < nmax ; i++ )
printf("%s", *(fpPhr+i) ) ;
}
void WriteMot(char *fpPhr[], char *fpMot, int nmax)
{
int i ;
int sz = 0 ;
for ( i = 0 ; i < nmax ; i++ )
sz += strlen( fpPhr[i] ) ;
printf("Taille totale : %d", sz) ;
}
void AlphaPhr( char *fpPhr[], int nmax)
{
void AlphaSwap(char *fpPhr[], int var_i, int var_j) ;
int i, j ;
int pm ;
for ( i = 0 ; i < nmax-1 ; i++ )
{
pm = i ;
for ( j = i+1 ; j < nmax ; j++ )
if ( strcmp( *(fpPhr+pm), *(fpPhr+j) ) > 0 )
pm = j ;
AlphaSwap(fpPhr, i, pm) ;
}
}
void AlphaSwap(char *fpPhr[], int var_i, int var_j)
{
char *aide ;
aide = fpPhr[var_i] ;
fpPhr[var_i] = fpPhr[var_j] ;
fpPhr[var_j] = aide ;
}
-0-
Comme je ne comprends pa l'algorithme de tri alphabétique de l'auteur
pour cet exercice, j'ai fait appel au tri par selection du maximum
Merci,
Pascal
J'apprends le C à partir d'un tutorial en ligne. Je n'arrive pas à un
résultat pour un exercice dont la solution de l'auteur ne fonctionne
pas non plus. Vous pouvez voir sur l'exercice et la solution que je ne
parviens pas à implémenter sur http://www.ltam.lu/cours-c// ex.
9.22.
Voici le code qui ne veut pas tourner alors que ça me semble cohérent.
J'y ajoute des fonctions car j'ai déjà parcouru le chapitre fonction
et j'essaie de résoudre les questions de l'allocation dynamique avec
les difficultés du chapitre des fonctions
/*
Ecrire un programme qui lit 4 mots au clavier (longueur maximale: 10
caractères) et attribue leurs adresses à un tableau de pointeurs pMot.
Copier les mots selon l'ordre lexicographique en une seule 'phrase'
dont l'adresse est affectée à un pointeur pPhr. Réserver l'espace
nécessaire à la PHRASE avant de copier les mots. Libérer la mémoire
occupée par chaque mot après l'avoir copié. Utiliser les fonctions de
<string>.
*/
#include <stdio.h> /* printf fgets */
#include <stdlib.h> /* malloc */
#include <string.h> /* strlen strcpy strcmp strcat */
#define MAXLIG 4 /* nbr de ligne max */
#define MAXLET 10 /* nbr de lettre max */
void ReadPhr(char *fpPhr[], int nmax) ;
void WritePhr(char *fpPhr[], int nmax) ;
void WriteMot(char *fpPhr[], char *fpMot, int nmax) ;
void AlphaPhr(char *fpPhr[], int nmax) ;
int main(void)
{
char *pPhr[MAXLIG] ;
char *pMot = 0 ;
ReadPhr(pPhr, MAXLIG) ;
WritePhr(pPhr, MAXLIG) ;
AlphaPhr(pPhr, MAXLIG) ;
WriteMot(pPhr, pMot, MAXLIG) ;
printf("") ;
return 0 ;
}
void ReadPhr(char *fpPhr[], int nmax)
{
char Intro[MAXLET] ;
int i ;
printf("Entrez des mots, fin avec [enter] : ") ;
for ( i = 0 ; i < nmax ; i++ )
{
printf("Entree %d%s : ", i+1, (i == 0) ? "ere" : "eme") ;
fgets(Intro, MAXLET, stdin) ;
*(fpPhr+i) = malloc( strlen(Intro)+1) ;
if ( *(fpPhr+i ) )
strcpy( *(fpPhr+i), Intro ) ;
else
{
printf("Allocation error") ;
exit(-1) ;
}
}
}
void WritePhr(char *fpPhr[], int nmax)
{
int i ;
printf("AFFICHAGE : ") ;
for ( i = 0 ; i < nmax ; i++ )
printf("%s", *(fpPhr+i) ) ;
}
void WriteMot(char *fpPhr[], char *fpMot, int nmax)
{
int i ;
int sz = 0 ;
for ( i = 0 ; i < nmax ; i++ )
sz += strlen( fpPhr[i] ) ;
printf("Taille totale : %d", sz) ;
}
void AlphaPhr( char *fpPhr[], int nmax)
{
void AlphaSwap(char *fpPhr[], int var_i, int var_j) ;
int i, j ;
int pm ;
for ( i = 0 ; i < nmax-1 ; i++ )
{
pm = i ;
for ( j = i+1 ; j < nmax ; j++ )
if ( strcmp( *(fpPhr+pm), *(fpPhr+j) ) > 0 )
pm = j ;
AlphaSwap(fpPhr, i, pm) ;
}
}
void AlphaSwap(char *fpPhr[], int var_i, int var_j)
{
char *aide ;
aide = fpPhr[var_i] ;
fpPhr[var_i] = fpPhr[var_j] ;
fpPhr[var_j] = aide ;
}
-0-
Comme je ne comprends pa l'algorithme de tri alphabétique de l'auteur
pour cet exercice, j'ai fait appel au tri par selection du maximum
Merci,
Pascal

Poser une question


(même complète, ça ne fonctionne pas) :
void WriteMot(char *fpPhr[], char *fpMot, int nmax)
{
int i ;
int sz = nmax ;
for ( i = 0 ; i < nmax ; i++ )
sz += strlen( fpPhr[i] + 1 ) ;
fpMot = malloc(sz) ;
for ( i = 0 ; i < nmax ; i++ )
strcat( fpMot, fpPhr[i] ) ;
for ( i = 0 ; i < nmax ; i++ )
printf("%c", fpMot) ;
}
Réfléchis bien au sujet de cette expression. A quoi s'applique + 1 ? En
fait, tu ajoutes 1 au pointeur du mot i, ce qui aura pour effet de
calculer sa taille à partir de la 2ème lettre (si elle existe !). Tu
obtiendras donc la taille du mot - 1, soit une perte de 4 (nmax)
caractères par rapport à la taille dont tu as besoin. Les concaténations
déborderont de 4 dans fpMot -> comportement indéfini.
Je suppose que ce que tu voulais vraiment faire, c'était rajouter 1 à la
taille à chaque fois, mais pourquoi ? L'énoncé ne demande pas que les
mots soient séparés par quelque-chose (un espace par exemple serait
bienvenu).
Ca serait pas plutôt :
for ( i = 0 ; i< nmax ; i++ )
sz += strlen( fpPhr[i] ) ;
sz++; /* pour le ' ' */
...que tu veux faire ?
Supprimer cette boucle, elle fait s'afficher la chaîne 4 fois.
^
"%s"
Tu devrais déjà avoir un meilleur résultat.
Remarques :
- tes mots contiennent le 'n' de ta saisie avec fgets(), donc les
strcat() les concatènent avec le reste. Ils n'ont aucune incidence sur
le reste du programme, mais lors de l'affichage des mots, il y a un 'n'
supplémentaire. Aussi lors de l'affichage de la phrase finale, elle fait
plusieurs lignes puisque tu concatènes les mots avec leur 'n'
respectifs. Il faut que tu t'arranges pour ne pas récupérer les 'n'.
- MAXLET est censé contenir le nombre de lettres maximum, mais tu
alloues char[MAXLET]. Et le ' ' de fin ?
- Libérer la mémoire réservée par les différents malloc() au bon moment
(et de la bonne manière).
- Le franglais genre WriteMot(), c'est limite tu trouves pas ? Bien
choisir ses noms de fonctions fait aussi partie du boulot. Si tu as des
problèmes avec l'anglais, alors nomme tes fonctions en français mais ne
mélange pas.
- si tu définis AlphaSwap() au-dessus de AlphaPhr(), tu n'auras plus
besoin de la déclarer avant de l'utiliser.
- *(pt+i) peut être remplaçé par pt[i].
--
Alex
Normal, tu n'affiches pas le tableau trié ...
Ceci fonctionne :
/*
Ecrire un programme qui lit 4 mots au clavier (longueur maximale: 10
caractères) et attribue leurs adresses à un tableau de pointeurs pMot.
Copier les mots selon l'ordre lexicographique en une seule 'phrase'
dont l'adresse est affectée à un pointeur pPhr. Réserver l'espace
nécessaire à la PHRASE avant de copier les mots. Libérer la mémoire
occupée par chaque mot après l'avoir copié. Utiliser les fonctions de
*/
#include #include #include
#define MAXLIG 4 /* nbr de ligne max */
void ReadPhr (char *fpPhr[], int nmax)
{
char Intro[10];
int i;
printf ("nEntrez des mots, fin avec [enter] : n");
for (i = 0; i < nmax; i++)
{
printf ("Entree %d%s : ", i + 1, (i == 0) ? "ere" : "eme");
fgets (Intro, sizeof Intro, stdin);
*(fpPhr + i) = malloc (strlen (Intro) + 1);
if (*(fpPhr + i))
strcpy (*(fpPhr + i), Intro);
else
{
printf ("nAllocation errorn");
exit (-1);
}
}
}
void WritePhr (char *fpPhr[], int nmax)
{
int i;
printf ("nAFFICHAGE : n");
for (i = 0; i < nmax; i++)
{
printf ("%sn", *(fpPhr + i));
}
}
void WriteMot (char *fpPhr[], int nmax)
{
int i;
int sz = 0;
for (i = 0; i < nmax; i++)
{
sz += strlen (fpPhr[i]);
}
printf ("Taille totale : %dn", sz);
}
void AlphaSwap (char *fpPhr[], int var_i, int var_j)
{
char *tmp = fpPhr[var_i];
fpPhr[var_i] = fpPhr[var_j];
fpPhr[var_j] = tmp;
}
void AlphaPhr (char *fpPhr[], int nmax)
{
int i;
for (i = 0; i < nmax - 1; i++)
{
int pm = i;
int j;
for (j = i + 1; j < nmax; j++)
{
if (strcmp (*(fpPhr + pm), *(fpPhr + j)) > 0)
{
pm = j;
}
}
AlphaSwap (fpPhr, i, pm);
}
}
int main (void)
{
char *pPhr[MAXLIG];
ReadPhr (pPhr, MAXLIG);
WritePhr (pPhr, MAXLIG);
AlphaPhr (pPhr, MAXLIG);
WriteMot (pPhr, MAXLIG);
WritePhr (pPhr, MAXLIG);
printf ("nn");
return 0;
}
...
Ca fonctionne sans afficher les mots saisis sur une et une seule
phrase :
ex.:
entree 1 : bonjourn
entree 2 : monden
resultat :
"bonjour monde"
je n'arrive pas à obtenir le résultat ci-dessus parmi mais je peux
obtenir les autres affichage (affichage trié...).
J'ai essayé de refaire l'exercice avec les éléments de ta réponse :
"Réfléchis bien au sujet de cette expression. A quoi s'applique +
1 ?..."
En fait dans la série d'exercices, je reprends la solution de
l'auteur...
/* Lecture d'une phrase */
printf("Phrase %d : ",I);
gets(INTRO);
TEXTE[I] = malloc(strlen(INTRO)+1);
C'est vrai que je ne comprends pas bien la présence de +1. C'est peut-
être parce que la solution de l'auteur fait appel à gets.
Je ne connais pas bien gets mais d'après ce que je sais pour fgets,
fgets lit et renvoie 'n', ce qui fait que strlen renvoie le nombre de
lettre + le caractère invisible n.
Maintenant que tu pointes le doigt sur ça, je comprends que ce n'est
pas cohérent et que ça ajoute des espaces mémoires en plus qui
resteront vide. En plus, je recherche plutôt à enlever l'espace
mémoire qui contient n pour que les mots apparaissent sur une même
ligne.
J'ai refais le code à partir des éléments que tu proposes sans succ ès
apparent.
Merci Alex de m'avoir éclairé et de m'éclairer un peu plus si tu n'es
pas en vacance ou si tu as le temps,
Pascal