cerhu > comp.lang.* > comp.lang.c

Michel (24/12/2003, 01h18)
Bonjour,

J'ai une exception avec la fonction bsearch dans le module
VerifierChampsPub et je ne trouve pas du tout, mais alors pas du tout
d'où elle vient. D'autant plus que bsearch fonctionne bien dans le
module GenererResultat.
Merci d'avance et joyeux Noel!
Michel

Définition de InfosFichier dans un .h :

typedef struct infos_fichier {
char **pTabIdPub;
size_t nbElement;
} InfosFichier;

---- module en cause ----------
NB : la fonction VerifierChampsPub reçoit un pointeur vers une chaine de
char (ex 900PU04, donc dans ce cas un pointeur vers le '9') et un
pointeur vers une structure InfosFichier qui contient un pointeur vers
un tableau de pointeurs vers char (les couples de lettres à rechercher)
et le nombre d'éléments du tableau char**

#include <stdio.h>
#include <stdlib.h>
#include <search.h>
#include <string.h>
#include <ctype.h>
#include "entete.h"
#include "definition.h"

#define NB_ELEMENTS 3

Booleen VerifierChampsPub(char *pCaractereTrouve,
InfosFichier *pInfosFichierIni_t) {

char coupleLettres[NB_ELEMENTS];
Booleen idPub = FAUX;

/* on vérifie que les 2° et 3° caractères après *pCaractereTrouve
soient des chiffres et que les 4° et 5° caractères soient des
lettres et que les 6° et 7° caractères soient des chiffres (ex:
900PU04 )
Si ces 6 conditions sont vraies, on vérifie si le couple de lettres
(ex: PU dans 900PU04) se trouve dans le tableau
pInfosFichierIni_t->pTabIdPub qui correspond au contenu d'un
fichier ini, c'est à dire à des couples de lettres */

if(isdigit(*(pCaractereTrouve + 1)) &&
isdigit(*(pCaractereTrouve + 2)) &&
isalpha(*(pCaractereTrouve + 3)) &&
isalpha(*(pCaractereTrouve + 4)) &&
isdigit(*(pCaractereTrouve + 5)) &&
isdigit(*(pCaractereTrouve + 6))) {

/* copie du couple de lettres pour le vérifier */
strncpy(coupleLettres, pCaractereTrouve + 3, NB_ELEMENTS);
coupleLettres[2] = '\0';

/* recherche du couple de lettres dans le tableau */
/* EXCEPTION ICI */
if(bsearch((char*)coupleLettres,
(char*)pInfosFichierIni_t->pTabIdPub,
pInfosFichierIni_t->nbElement,
sizeof(char*),
ComparerChaine) != NULL) {
idPub = VRAI;
}
}
return idPub;
}

------- module ComparerChaine --------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "entete.h"
#include "definition.h"

int ComparerChaine(const void *chaine1, const void *chaine2) {

return strcmp(*(char**) chaine1, *(char**) chaine2);
}

-----module GenererResultat qui utilise aussi ComparerChaine et qui

fonctionne bien -----------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "entete.h"
#include "definition.h"

#define NOM_MODULE "GenererResultat.c"

InfosFichier * GenererResultat(InfosFichier *pInfosFichierRF_t,
InfosFichier *pInfosFichierSP_t) {

static InfosFichier InfosFichierResultat_t;
InfosFichier *pInfosFichierResultat_t = &InfosFichierResultat_t;
char **pTabIdPubASupprimer = NULL;
char **temp = NULL;
Booleen idTrouve = FAUX;
size_t i, j = 0;

for(i = 0; i < pInfosFichierRF_t->nbElement; i++) {

/* bsearch retourne NULL si la valeur n'est pas dans le tableau */
if(bsearch((char*) &pInfosFichierRF_t->pTabIdPub[i],
pInfosFichierSP_t->pTabIdPub,
pInfosFichierSP_t->nbElement,
sizeof(char*), ComparerChaine) == NULL) {

/* réservation mémoire pour stocker un pointeur vers la chaîne
id */
if((temp = realloc(pTabIdPubASupprimer, sizeof(char*) * (j+1)))
!= NULL) {
pTabIdPubASupprimer = temp;
temp = NULL;

/* mémorisation de l'id trouvé */
if((pTabIdPubASupprimer[j++] =
strdup(pInfosFichierRF_t->pTabIdPub[i])) == NULL) {
TraiterErreur(NOM_MODULE, __LINE__ - 1, "\202chec
d'allocation m\202moire par \"strdup\".");
}
}
else {
TraiterErreur(NOM_MODULE, __LINE__ - 12, "\202chec
d'allocation m\202moire par \"realloc\".");
//LibererMemoire(pTabIdPub, j);
}
}

}

/* valorisation des champs de la structure */
InfosFichierResultat_t.pTabIdPub = pTabIdPubASupprimer;
InfosFichierResultat_t.nbElement = j;

return pInfosFichierResultat_t;
}
Yves ROMAN (26/12/2003, 15h46)
Michel a écrit :
[..]
> size_t nbElement;
> } InfosFichier;
> ---- module en cause ----------

....
[..]
> /* recherche du couple de lettres dans le tableau */
> /* EXCEPTION ICI */
> if(bsearch((char*)coupleLettres,
> (char*)pInfosFichierIni_t->pTabIdPub,
> pInfosFichierIni_t->nbElement,
> sizeof(char*),
> ComparerChaine) != NULL) {
> idPub = VRAI;
> }


Je suppose que bsearch va appliquer ComparerChaine aux éléments du tableau
(comme qsort) et a la clef pour la comparer aux éléments du tableau. Ils doivent
donc être du même type, à savoir char ** : l'adresse d'un pointeur vers une
chaine de caractères.
Mais tu lui passes comme clef l'adresse d'une chaine de caractères.
Il va donc essayer de convertir le contenu de coupleLettres comme une adresse,
et va planter en la déréférencant.
Il faut donc rajouter un niveau d'indirection

char * pCle = coupleLettres ;
if(bsearch(&pCle,
pInfosFichierIni_t->pTabIdPub,
pInfosFichierIni_t->nbElement,
sizeof(char*),
ComparerChaine) != NULL) {
....

[..]
> pInfosFichierSP_t->pTabIdPub,
> pInfosFichierSP_t->nbElement,
> sizeof(char*), ComparerChaine) == NULL) {


Ici tu passes bien l'adresse d'un char *

....
Michel (26/12/2003, 16h07)
Yves ROMAN a écrit :

> Je suppose que bsearch va appliquer ComparerChaine aux éléments du tableau
> (comme qsort) et a la clef pour la comparer aux éléments du tableau. Ils doivent
> donc être du même type, à savoir char ** : l'adresse d'un pointeur vers une
> chaine de caractères.
> Mais tu lui passes comme clef l'adresse d'une chaine de caractères.
> Il va donc essayer de convertir le contenu de coupleLettres comme une adresse,
> et va planter en la déréférencant.
> Il faut donc rajouter un niveau d'indirection
> char * pCle = coupleLettres ;


Ce qui revient à écrire &coupleLettres comme 1er argument de bsearch.
Mais ça plante quand même (même exception).
Michel
[..]
Yves ROMAN (26/12/2003, 16h26)
Michel a écrit :
> Yves ROMAN a écrit :

ou, si tu préfères, ce qui revient au même
char * pCle = &coupleLettres ;

> Ce qui revient à écrire &coupleLettres comme 1er argument de bsearch.
> Mais ça plante quand même (même exception).


Ce n'est pas pareil car
bsearch(coupleLettres,...
et
bsearch(&coupleLettres,...
font la meme chose : ils passent comme valeur d'argument l'adresse de
coupleLettres[0]
alors que
bsearch(&pCle,...
passe comme valeur d'argument l'adresse de pCle, c'est a dire l'adresse d'une
zone memoire qui contient elle-même l'adresse de coupleLettres[0]

C'est l'éternel piège de la pseudo-dualité entre pointeur et tableau : on a
l'impression de pouvoir les utiliser l'un a la place de l'autre mais ils n'ont
rien a voir, en particulier lorsqu'on en prend l'adresse :
dans une expression :
coupleLettres est équivalent à un char *
pCle est un char *
mais
&coupleLettres est un char *
&pCle est un char **
[..]
Michel (26/12/2003, 17h47)
Yves ROMAN a écrit :

> Ce n'est pas pareil car
> bsearch(coupleLettres,...
> et
> bsearch(&coupleLettres,...
> font la meme chose : ils passent comme valeur d'argument l'adresse de
> coupleLettres[0]


Euh, j'ai un doute là.
Si coupleLettres est déclaré comme ça :
char coupleLettres[3];
alors :
'coupleLettres' correspond au nom du tableau, donc à l'adresse de son
1er élément, donc à &coupleLettres[0] (c'est donc un char*)
alors que
'&coupleLettres' correspond à l'adresse de l'adresse du tableau (c'est
donc un char**)
Enfin, il me semble bien...

Michel
Michel (26/12/2003, 17h58)
Yves ROMAN a écrit :

> ou, si tu préfères, ce qui revient au même
> char * pCle = &coupleLettres ;


Je pense que tu te trompes car tu mets un char** dans un char*
En effet, coupleLettres était défini comme ça :
char coupleLettres[3];
alors 'coupleLettres' est l'adresse du 1er élément du tableau de char
(donc un char*). Donc '&coupleLettres' est un char** que tu affectes à
pCle qui est un char*
Le compilateur l'indique par un warning.
Michel
Emmanuel Delahaye (26/12/2003, 18h20)
In 'fr.comp.lang.c', Michel <noSpam> wrote:

> Si coupleLettres est déclaré comme ça :
> char coupleLettres[3];
> alors :
> 'coupleLettres' correspond au nom du tableau, donc à l'adresse de son
> 1er élément, donc à &coupleLettres[0] (c'est donc un char*)
> alors que
> '&coupleLettres' correspond à l'adresse de l'adresse du tableau (c'est
> donc un char**)


Non. Un pointeur n'est pas un tableau. En fait avec

char coupleLettres[3];

&coupleLettres est du type char (*)[3] (pointeur sur tableau de 3 char).

La /valeur/ est la même que &coupleLettres[0], coupleLettres + 0 ou
coupleLettres, mais le /type/ est différent.
Discussions similaires
Problème avec bsearch()

Retour de la fonction bsearch

bsearch

Personne ne sait pour l'exception de bsearch ?


Fuseau horaire GMT +2. Il est actuellement 12h12. | Privacy Policy