Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

remplir des structures

15 réponses
Avatar
nicolas
bonsoir a tous,

j aimerai faire une fonction generique pour remplir n importe quel type
de structure.


void remplir_struct(char **data, void *structur);

mon tableau est remplit de la facon suivante: deux cases par deux cases:

data[0] = "toto" /* la valeur */
data[1] = "str" /* le type */
data[2] = "84"
data[3] = "int"

et ainsi pouvoir remplir une structure de ce type

struct toto {
char *str;
int i;
};

je pensais pouvoir remplir le void *structur a coup de sizeof et de cast
mais je ne pense pas que ce soit une bonne idee..

j aimerai avoir vos lumiere sur ce probleme.

merci d'avance pour tout.

10 réponses

1 2
Avatar
Emmanuel Delahaye
nicolas wrote on 21/01/05 :
bonsoir a tous,

j aimerai faire une fonction generique pour remplir n importe quel type de
structure.

void remplir_struct(char **data, void *structur);

mon tableau est remplit de la facon suivante: deux cases par deux cases:

data[0] = "toto" /* la valeur */
data[1] = "str" /* le type */
data[2] = "84"
data[3] = "int"

et ainsi pouvoir remplir une structure de ce type

struct toto {
char *str;
int i;
};


Ca, c'est pas trop possible.

je pensais pouvoir remplir le void *structur a coup de sizeof et de cast mais
je ne pense pas que ce soit une bonne idee..

j aimerai avoir vos lumiere sur ce probleme.

merci d'avance pour tout.


Il faut définir un conteneur générique

struct conteneur
{
void *p;
size_t size_elem;
size_t nb_elem;
};

On peut eventuellement ajouter le nom du champ

char const *s_name;

Ensuite, en fonction, des information, on alloue la taille nécessaire
pour chaque objet et conteneur. On peut éventuellement faire un tableau
flexible de conteneurs...

struct structure
{
struct conteneur **pp;
size_t nb_cont;
};

On peut aussi utiliser une méthode 'plate' qui consiste à mapper des
données dans un tableau flexible de unsigned char selon un 'plan'
défini par une syntaxe de description de données (ASN.1, XDR etc.) qui
permet de fabriquer une structure d'information contenant le nom des
données leurs offsets, tailles etc. C'est utile pour mapper une zone
mémoire précise (Flash, RAM sauvergardée...) ou des informations sur
disque...

Sky's the limit...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.

Avatar
nicolas
Emmanuel Delahaye wrote:

On peut aussi utiliser une méthode 'plate' qui consiste à mapper des
données dans un tableau flexible de unsigned char selon un 'plan' défini
par une syntaxe de description de données (ASN.1, XDR etc.) qui permet
de fabriquer une structure d'information contenant le nom des données
leurs offsets, tailles etc. C'est utile pour mapper une zone mémoire
précise (Flash, RAM sauvergardée...) ou des informations sur disque...

Sky's the limit...



merci beaucoup je vais aller dans ce sens ...
merci encore

Avatar
nicolas
bonsoir,
j ai donc teste ce que vous m avez propose precedement mais je me heurte
a un probleme: les floats

voici le bout de code que j utilise:



----------------------------------------------------------
#include <stdlib.h>

#define SIZE sizeof(int) * 17 + sizeof(float) * 3
#define MASK "iiiiiiifiiiiffiiiiii"

size_t get_size(char type)
{
if (type == 'i')
return (sizeof(int));
if (type == 'f')
return (sizeof(float));
return (0);
}

int main()
{
void *data;
void **index;

int count;
size_t current;
char *mask = MASK;

int *toto;

data = malloc(SIZE);
index = malloc(sizeof(void *) * strlen(MASK));
current = 0;
for (count = 0; count < strlen(MASK); count++)
{
index[count] = data;
data += get_size(mask[count]);
}

(int) index[2] = 42;
(int) index[0] = 11;
(int) index[17] = 42;
toto = index[1];
*toto = 42;
printf("%dn", index[2]);
printf("%dn", index[1]);
}
----------------------------------------------------------

lorsqu il s'agit d un float le compilateur m interdit de faire cela :
(float) index[7] = 0.4342;

j ai donc decide de passer par un pointeur de type float *
mais sans resultat ...
j ai essaye la meme chose avec les int: passe par un int * pour assigner
la valeur, de meme sans resultat. D ou ma question:

pourquoi "(int) index[2] = 42" marche et non "*toto" ???

je me suis trompe quelque part mais je n arrive pas a trouver ou...

je vous remercie d avance pour vos reponses.

bonne soiree a tous.
Avatar
nicolas
je n'y arrive vraiment pas personne pour m aider ?
Avatar
nicolas
Emmanuel Delahaye wrote:
nicolas wrote on 23/01/05 :

je n'y arrive vraiment pas personne pour m aider ?



Poste le code qui ne fonctionne pas...



je l avais poste hier ... ca n a pas du fonctionner


==================================== bonsoir,
j ai donc teste ce que vous m avez propose precedement mais je me heurte
a un probleme: les floats

voici le bout de code que j utilise:



----------------------------------------------------------
#include <stdlib.h>

#define SIZE sizeof(int) * 17 + sizeof(float) * 3
#define MASK "iiiiiiifiiiiffiiiiii"

size_t get_size(char type)
{
if (type == 'i')
return (sizeof(int));
if (type == 'f')
return (sizeof(float));
return (0);
}

int main()
{
void *data;
void **index;

int count;
size_t current;
char *mask = MASK;

int *toto;

data = malloc(SIZE);
index = malloc(sizeof(void *) * strlen(MASK));
current = 0;
for (count = 0; count < strlen(MASK); count++)
{
index[count] = data;
data += get_size(mask[count]);
}

(int) index[2] = 42;
(int) index[0] = 11;
(int) index[17] = 42;
toto = index[1];
*toto = 42;
printf("%dn", index[2]);
printf("%dn", index[1]);
}
----------------------------------------------------------

lorsqu il s'agit d un float le compilateur m interdit de faire cela :
(float) index[7] = 0.4342;

j ai donc decide de passer par un pointeur de type float *
mais sans resultat ...
j ai essaye la meme chose avec les int: passe par un int * pour assigner
la valeur, de meme sans resultat. D ou ma question:

pourquoi "(int) index[2] = 42" marche et non "*toto" ???

je me suis trompe quelque part mais je n arrive pas a trouver ou...

je vous remercie d avance pour vos reponses.

bonne soiree a tous.


Avatar
Emmanuel Delahaye
nicolas wrote on 23/01/05 :
je n'y arrive vraiment pas personne pour m aider ?


Poste le code qui ne fonctionne pas...

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Avatar
Emmanuel Delahaye
nicolas wrote on 23/01/05 :
void **index;
index = malloc(sizeof(void *) * strlen(MASK));
(int) index[2] = 42;
(int) index[0] = 11;
(int) index[17] = 42;


Tu fabriques un tableau de pointeurs sur des blocs anonymes (void*).
L'assignation des données ne peut se faire que si on connait leur
adresse et leur taille à coup de memcpy().

Il est préférable de définir un format commun de conteneur:

typedef struct
{
size_t size; /* taille d'un element */
size_t nb; /* nombre d'elements */
void *address; /* adresse du debut du bloc */
}
cont_s;

et faire un tableau de ces elements...

/* statique */
cont_s a_cont[123];

ou

/* dynamique */
cont_s *p_cont = malloc (sizeof *p_cont * 123);

D'autre part, on ne peut pas faire d'arithmetique de pointeurs avec un
void *.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.

Avatar
nicolas
Emmanuel Delahaye wrote:
nicolas wrote on 23/01/05 :

void **index;
index = malloc(sizeof(void *) * strlen(MASK));
(int) index[2] = 42;
(int) index[0] = 11;
(int) index[17] = 42;



Tu fabriques un tableau de pointeurs sur des blocs anonymes (void*).
L'assignation des données ne peut se faire que si on connait leur
adresse et leur taille à coup de memcpy().


je remplis mon void **index avec les adresses de void *data, c est a
dire que j'index chaque element de mon zone memoire data.

pour remplir mon tableau je devrai donc faire quelque chose comme ca :

memcpy(index[2], &value, sizeof(int)); /* pour un int */

Il est préférable de définir un format commun de conteneur:

typedef struct
{
size_t size; /* taille d'un element */
size_t nb; /* nombre d'elements */
void *address; /* adresse du debut du bloc */
}
cont_s;

et faire un tableau de ces elements...

/* statique */
cont_s a_cont[123];

ou

/* dynamique */
cont_s *p_cont = malloc (sizeof *p_cont * 123);


donc lorsque j ai un int je remplis ma stucture comme ceci ?:

.size = sizeof (int)
.nb = 1 /* il sera toujour a un ??! */
.address = une zone memoire de data ?

dans ce cas pourquoi utilise une structure, j avoue etre completement
perdu la ...



D'autre part, on ne peut pas faire d'arithmetique de pointeurs avec un
void *.



je ne savais pas ... pourtant dans mes tests mon ptr avancait
correctement (ou du moins semblait)

merci encore pour ton aide... je suis vraiment perdu.


Avatar
Horst Kraemer
nicolas wrote:

bonsoir,
j ai donc teste ce que vous m avez propose precedement mais je me heurte
a un probleme: les floats

voici le bout de code que j utilise:



----------------------------------------------------------
#include <stdlib.h>

#define SIZE sizeof(int) * 17 + sizeof(float) * 3
#define MASK "iiiiiiifiiiiffiiiiii"

size_t get_size(char type)
{
if (type == 'i')
return (sizeof(int));
if (type == 'f')
return (sizeof(float));
return (0);
}

int main()
{
void *data;
void **index;

int count;
size_t current;
char *mask = MASK;

int *toto;

data = malloc(SIZE);


Quand tu changes data après tu perds ton pointeur intial. Il faut le
sauver.

void *data0;
void *data;
data = data0 = malloc(SIZE);
/* ... */
free (data0);

index = malloc(sizeof(void *) * strlen(MASK));
current = 0;
for (count = 0; count < strlen(MASK); count++)
{
index[count] = data;
data += get_size(mask[count]);


C'est du C GNU. En C tu devrais écire:

data = (char *) data + get_size(mask[count])


}

(int) index[2] = 42;


Ce n'est pas ce que tu veux. D'abord c'est un "lvalue cast", une
extension de certains compilateurs comme gcc qui n'est pas défini par
la norme de langage C. Ici ce cast a l'effet

index[2] = (void *)42;

c.a.d. tu essaies de stocker la valeur intégrale 42 *dans* le pointeur
index[2] et tu détruis la valeur de index[2] au lieu de stocker 42
dans la mémoire vers laquelle index[2] pointe. L'affectation correcte
serait

*(int*)index[2] = 42;
*(float*)index[7] = 0.4342;


printf("%dn", *(int*)index[2]);
printf("%fn", *(float*)index[7]);



Mais tu n'as pas fait ce que Emmanuel a proposé...

Avatar
nicolas
Horst Kraemer wrote:
nicolas wrote:


bonsoir,
j ai donc teste ce que vous m avez propose precedement mais je me heurte
a un probleme: les floats

voici le bout de code que j utilise:



----------------------------------------------------------
#include <stdlib.h>

#define SIZE sizeof(int) * 17 + sizeof(float) * 3
#define MASK "iiiiiiifiiiiffiiiiii"

size_t get_size(char type)
{
if (type == 'i')
return (sizeof(int));
if (type == 'f')
return (sizeof(float));
return (0);
}

int main()
{
void *data;
void **index;

int count;
size_t current;
char *mask = MASK;

int *toto;

data = malloc(SIZE);



Quand tu changes data après tu perds ton pointeur intial. Il faut le
sauver.

void *data0;
void *data;
data = data0 = malloc(SIZE);
/* ... */
free (data0);


index = malloc(sizeof(void *) * strlen(MASK));
current = 0;
for (count = 0; count < strlen(MASK); count++)
{
index[count] = data;
data += get_size(mask[count]);



C'est du C GNU. En C tu devrais écire:

data = (char *) data + get_size(mask[count])



}

(int) index[2] = 42;



Ce n'est pas ce que tu veux. D'abord c'est un "lvalue cast", une
extension de certains compilateurs comme gcc qui n'est pas défini par
la norme de langage C. Ici ce cast a l'effet

index[2] = (void *)42;

c.a.d. tu essaies de stocker la valeur intégrale 42 *dans* le pointeur
index[2] et tu détruis la valeur de index[2] au lieu de stocker 42
dans la mémoire vers laquelle index[2] pointe. L'affectation correcte
serait

*(int*)index[2] = 42;
*(float*)index[7] = 0.4342;


printf("%dn", *(int*)index[2]);
printf("%fn", *(float*)index[7]);



Mais tu n'as pas fait ce que Emmanuel a proposé...







j ai teste apres les explications de Emmanuel et ca semble mieux marcher ;)
merci de ta reponse


1 2