J'ai également regardé ton code en diagonale. Ce qui est mélangeant est que tu définis tes types comme des pointeurs. Définis les sans cela et mentionnes-le dans tes déclarations à la place. La meilleure façon de t'en sortir est de dire à toutes tes fonctions que le type des éléments est de type void. Et tu fais du transtypage dans le main. Seul le main devrait connaitre le vrai type. Tu devras définir les objets dans le main et passer aux fonctions le pointeur et la longueur des objets. Je n'ai pas compris pour l'insertion. Est-ce que tu décales la fin pour insérer un nouvel élément? Tu pourrais utiliser memcpy en lui donnant la longueur de ce qui doit être recopié. On le fait un élément à la fois en partant de la fin vers le point d'insertion. Sinon tu vas écraser les éléments suivants et ils seront tous égaux au premier décalé.
Le Tout est souvent plus grand que la somme de ses parties.
En utilisant un pointeur vers une fonction qui sait le faire.
---
Comme c'est un problème rigolo, j'ai développé l'idée sur un exemple du même genre (parce que je ne fais pas les exercices, etc).
Pb: faire un conteneur d'objets de type inconnu (mais le même), dans lequel on peut ajouter des éléments à la fin, qu'on peut trier, et faire afficher.
Je fais l'impasse sur l'extensibilité, et les autres opérations utiles - dont la libération, sinon ça va faire des kilomètres de code.
La fonction int_constant fournit un pointeur (éphémère) vers un entier
void* int_constant(int n) // Hack - not reentrant
{
static int number;
number = n;
return &number;
}
Résultat de l'exécution
Avant = [26,14,3,16,35]
Après = [3,14,16,26,35]
PS: une autre histoire serait de stocker toutes les données du tableau dans une zone (contigue) allouée dynamiquement. Dans ce cas il faut avoir aussi la taille des éléments dans la description du type - en supposant que ça soit une taille fixe.
- Edité par michelbillaud 13 février 2022 à 10:23:11
> PS: une autre histoire serait de stocker toutes les données du tableau dans une zone (contigue) allouée dynamiquement. Dans ce cas il faut avoir aussi la taille des éléments dans la description du type - en supposant que ça soit une taille fixe.
Bon, ça ne change pas énormément de choses
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
struct DTD { // data type description
size_t size;
void (*print)(void *thing);
int (*compare)(void *first, void *second);
};
struct Array {
struct DTD *dtd;
size_t size; // number of elements
char data[1024]; // not extensible
};
// address of an element
void * array_address(struct Array* array, int index)
{
return array->data + index * array->dtd->size;
}
// add a copy of data
void array_append(struct Array * array, void *thing)
{
memcpy(array_address(array, array->size ++),
thing,
array->dtd->size);
}
void array_print(struct Array *array )
{
printf("[");
char * separator = "";
for (size_t i = 0; i < array->size; i++) {
printf("%s", separator);
separator = ",";
array->dtd->print(array_address(array, i));
}
printf("]");
}
void array_sort(struct Array *array)
{
// selection
for (size_t i = 0; i < array->size; i++) {
int m = i; // index of minimum
for (size_t j = i+1; j < array->size; j++) {
if (array->dtd->compare(array_address(array, j),
array_address(array, m))
< 0) {
m = j;
}
}
void *a = array_address(array, m);
void *b = array_address(array, i);
char tmp[array->dtd->size];
memcpy(tmp, a, array->dtd->size);
memcpy(a, b, array->dtd->size);
memcpy(b, tmp, array->dtd->size);
}
}
// -- for ints
void int_print(void *thing)
{
int *t = thing;
printf("%d", *t);
}
int int_compare(void * first, void *second)
{
int *f = first, *s = second;
return *f - *s;
}
void* int_constant(int n) // Hack - not reentrant
{
static int number;
number = n;
return &number;
}
int main(int argc, char *argv[])
{
struct DTD int_dtd = {
.size = sizeof(int), // NEW
.print = int_print,
.compare = int_compare
};
struct Array a = {
.dtd = & int_dtd,
.size = 0
};
array_append(&a, int_constant(26));
array_append(&a, int_constant(14));
array_append(&a, int_constant(3));
array_append(&a, int_constant(16));
array_append(&a, int_constant(35));
printf("Avant = ");
array_print(&a);
printf("\n");
array_sort(&a);
printf("Après = ");
array_print(&a);
printf("\n");
return EXIT_SUCCESS;
}
PS:
on utilise des adresses de char (octets) parce qu'on peut faire de l'arithmétique dessus. Et qu'on en a besoin.
il y a peut être des emmerdements à prévoir avec l'alignement des données.
- Edité par michelbillaud 13 février 2022 à 11:23:16
Merci beaucoup pour vos réponse. Je vais essayer d'implémenter sa. En ce qui concerne la consigne, il s'agit d'un TP assez long avec plusieurs consigne. ou il faut ajouter des valeur dans un tableau et les afficher en passant uniquement par des void*
Afficher une variable void (éventuellement *) avec printf() c'est impossible, à moins de caster le void (éventuellement *). printf() a besoin de savoir quel type de variable il (elle ?) doit afficher.
- Edité par edgarjacobs 13 février 2022 à 22:28:36
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.