Pile et listes chaînées
Theo_0055
Messages postés
273
Date d'inscription
Statut
Membre
Dernière intervention
-
[Dal] Messages postés 6205 Date d'inscription Statut Contributeur Dernière intervention -
[Dal] Messages postés 6205 Date d'inscription Statut Contributeur Dernière intervention -
Bonjour je voulais savoir comment on fait pour empiler une chaine de caractère dans une pile
Exemple: chaine={AGFGDG}
Je veux empiler ceci sur une pile mais je sais pas comment faire, pouvez vous m'aider svp
Je sais comment empiler un caractère mais un bloc contenant une chaine de caractère ,je sais pas
Exemple: chaine={AGFGDG}
Je veux empiler ceci sur une pile mais je sais pas comment faire, pouvez vous m'aider svp
Je sais comment empiler un caractère mais un bloc contenant une chaine de caractère ,je sais pas
A voir également:
- Pile et listes chaînées
- Pile carte mere - Guide
- Pile manette wii ✓ - Forum Wii
- Pile bios empêche démarrage pc ✓ - Forum Matériel & Système
- PIle BIOS ✓ - Forum Carte-mère/mémoire
- Listes déroulantes excel - Guide
9 réponses
Bonjour Theo_0055,
Une "pile" peut être implémentée de plusieurs façons en C.
Si tu disposes d'un code que tu as réalisé et qui gère une pile pour un caractère, il est possible que ton code puisse être adapté pour gérer des chaînes de caractères.
Utilises-tu une liste chaînée, un simple tableau, autre chose ?
Dal
Une "pile" peut être implémentée de plusieurs façons en C.
Si tu disposes d'un code que tu as réalisé et qui gère une pile pour un caractère, il est possible que ton code puisse être adapté pour gérer des chaînes de caractères.
Utilises-tu une liste chaînée, un simple tableau, autre chose ?
Dal
J’utilise une liste chaîné et une pile
Les caractères et chaînes de caractère sont dans ma liste chaîné et je veux empiler cela sur ma pile
Les caractères et chaînes de caractère sont dans ma liste chaîné et je veux empiler cela sur ma pile
Dans ton code, tu dois donc certainement définir une struct, et avec ce type struct que tu attribues aux maillons de ta liste chaînée, tu dois stocker :
Peux-tu poster ton type struct avec lequel tu gères une pile de char, stp ?
Tu dois aussi avoir des fonctions de manipulation de la pile, qui te permettent d'ajouter un élément, de retirer, retourner le nombre d'éléments de la pile, etc. Mais voyons déjà quelle tête a ton type.
- un moyen d'accéder à l'élément contenu dans le maillon
- un pointeur sur l'élément suivant
Peux-tu poster ton type struct avec lequel tu gères une pile de char, stp ?
Tu dois aussi avoir des fonctions de manipulation de la pile, qui te permettent d'ajouter un élément, de retirer, retourner le nombre d'éléments de la pile, etc. Mais voyons déjà quelle tête a ton type.
typedef struct Element Element; struct Element{ int nombre; Element *suivant; }; typedef struct Pile Pile; struct Pile{ Element *sommet; }; void empiler_char(Pile *pile,char& carac){ Element *nouveau = malloc(sizeof(*nouveau)); if (pile == NULL || nouveau == NULL) exit(EXIT_FAILURE); nouveau->nombre = carac; nouveau->suivant = pile->sommet; pile->sommet = nouveau; }
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
J’ai une petite piste esceque on doit faire tant que on a pas fini de parcourir la chaîné de caractère,on ajoute le caractère dans la pile en faisant appel à empiler_char?
Salut Theo_0055,
OK, 2 remarques sur ton code avant d'entrer dans le vif du sujet : ton membre nombre est de type int, alors que tu veux y stocker des char ; deuxièmement dans ton prototype
Tu peux rendre ton code plus générique en mettant le type géré dans un typedef.
Ton idée dans ce que tu postes est de stocker la donnée dans le maillon, mais en utilisant directement le type char dans les paramètres de ta fonction. En faisant cela, ton code d'ajout devient spécifique aux données traitées.
Une autre approche serait de rendre ton code plus générique pour que ta pile puisse traiter n'importe quel type de données avec un minimum de changements.
Ce code devrait gérer une pile de char en copiant le char passé en tant que type Donnee dans la pile.
Ensuite, il suffit de changer
Cela fonctionne car, dans
Si tu veux que ta liste gère une copie des données passées, stockée sous la forme de tableau de char dans la pile, alors tu peux le faire aussi, mais il faut ruser car l'opérateur d'affectation
Dans
OK, 2 remarques sur ton code avant d'entrer dans le vif du sujet : ton membre nombre est de type int, alors que tu veux y stocker des char ; deuxièmement dans ton prototype
void empiler_char(Pile *pile,char& carac)la partie
char& caracn'est pas du C (cela ressemble à une référence C++).
Tu peux rendre ton code plus générique en mettant le type géré dans un typedef.
Ton idée dans ce que tu postes est de stocker la donnée dans le maillon, mais en utilisant directement le type char dans les paramètres de ta fonction. En faisant cela, ton code d'ajout devient spécifique aux données traitées.
Une autre approche serait de rendre ton code plus générique pour que ta pile puisse traiter n'importe quel type de données avec un minimum de changements.
typedef char Donnee; typedef struct Element Element; struct Element{ Donnee donnee; Element *suivant; }; void empiler_donnee(Pile *pile, Donnee donnee){ if (pile == NULL) exit(EXIT_FAILURE); Element *nouveau = malloc(sizeof(*nouveau)); if (nouveau == NULL) exit(EXIT_FAILURE); nouveau->donnee = donnee; nouveau->suivant = pile->sommet; pile->sommet = nouveau; }
Ce code devrait gérer une pile de char en copiant le char passé en tant que type Donnee dans la pile.
Ensuite, il suffit de changer
typedef char Donnee;en
typedef char * Donnee;pour gérer une liste de pointeurs sur char où tu stockes des pointeurs sur char passés à la fonction empiler_donnees().
Cela fonctionne car, dans
empiler_donnee, l'opérateur d'affectation dans
nouveau->donnee = donnee;va simplement affecter un pointeur.
Si tu veux que ta liste gère une copie des données passées, stockée sous la forme de tableau de char dans la pile, alors tu peux le faire aussi, mais il faut ruser car l'opérateur d'affectation
=ne permet pas l'affectation de types tableaux en langage C. En revanche, il peut gérer les struct. Donc, en rusant, tu peux réutiliser le même code en changeant ton type Donnee comme ceci :
#define MAX_LEN 500 typedef struct Donnee Donnee; struct Donnee { char str[MAX_LEN]; };
Dans
empiler_donnee(), l'opérateur d'affectation à la ligne
nouveau->donnee = donnee;va alors copier le contenu de la struct (en faisant une opération équivalente à un memcpy()).
1.Pour le char& carac en fait c’était une erreur de frappe c’était char carac tout court sans &
2.Si j’ai bien compris
typedef char Donnee donnee =définition du type Donnee (qui est un char)
3.votre dernier Donnee il est censé gérer les chaînes de caractères c’est ça?
4.J’ai essayé plusieurs fois d’écrire un code pour gérer n’importe quel type de Donnee (char,int,double,..) mais le problème je sais pas comment m’y prendre
Car créer à chaque fois une fonction qui dépile int,une autre des char.. c’est un peu répétitif et j’aimerais créer une seule qui gère tous les types
2.Si j’ai bien compris
typedef char Donnee donnee =définition du type Donnee (qui est un char)
3.votre dernier Donnee il est censé gérer les chaînes de caractères c’est ça?
4.J’ai essayé plusieurs fois d’écrire un code pour gérer n’importe quel type de Donnee (char,int,double,..) mais le problème je sais pas comment m’y prendre
Car créer à chaque fois une fonction qui dépile int,une autre des char.. c’est un peu répétitif et j’aimerais créer une seule qui gère tous les types
2.Si j’ai bien compris
typedef char Donnee donnee =définition du type Donnee (qui est un char)
oui
3.votre dernier Donnee il est censé gérer les chaînes de caractères c’est ça?
J'en au proposé deux qui sont susceptibles permettre au code gérant la liste de gérer des chaînes de caractères. Le dernier est l'un d'eux.
4.J’ai essayé plusieurs fois d’écrire un code pour gérer n’importe quel type de Donnee (char,int,double,..) mais le problème je sais pas comment m’y prendre
Car créer à chaque fois une fonction qui dépile int,une autre des char.. c’est un peu répétitif et j’aimerais créer une seule qui gère tous les types
Je viens de t'indiquer une façon de faire, le seul changement à faire étant sur le typedef qui définit le type de tes données.
typedef char Donnee donnee =définition du type Donnee (qui est un char)
oui
3.votre dernier Donnee il est censé gérer les chaînes de caractères c’est ça?
J'en au proposé deux qui sont susceptibles permettre au code gérant la liste de gérer des chaînes de caractères. Le dernier est l'un d'eux.
4.J’ai essayé plusieurs fois d’écrire un code pour gérer n’importe quel type de Donnee (char,int,double,..) mais le problème je sais pas comment m’y prendre
Car créer à chaque fois une fonction qui dépile int,une autre des char.. c’est un peu répétitif et j’aimerais créer une seule qui gère tous les types
Je viens de t'indiquer une façon de faire, le seul changement à faire étant sur le typedef qui définit le type de tes données.
Tu ne peux pas écrire cela, car cela revient à tenter de redéfinir un alias de type. Ma suggestion d'une modification minimale de ton code pour gérer un autre type de données que le char était que tu définisses ton alias de type Donnee avec le type de données que tu veux gérer dans ta pile. Ton code générique gérera ce type de données.
Maintenant tu sembles avoir un besoin différent. Si dans chaque maillon tu veux stocker un char et un int, tu peux créer un type Donnee qui soit une struct avec ces deux membres. Si dans chaque maillon tu veux stocker un char ou un int, tu peux créer une struct qui contient une union dans l'un de ses membres avec ces deux types et l'autre membre qui stocke le type (la façon courante de le faire est avec un enum).
Une autre façon de rendre ta pile générique est de stocker des
Maintenant tu sembles avoir un besoin différent. Si dans chaque maillon tu veux stocker un char et un int, tu peux créer un type Donnee qui soit une struct avec ces deux membres. Si dans chaque maillon tu veux stocker un char ou un int, tu peux créer une struct qui contient une union dans l'un de ses membres avec ces deux types et l'autre membre qui stocke le type (la façon courante de le faire est avec un enum).
Une autre façon de rendre ta pile générique est de stocker des
void *dans ta pile et laisser le soin aux fonctions appelantes de passer le pointeur void et le transtyper lorsqu'il est récupéré. Tu avais posté un message où tu posais des questions sur les
void *et qui a été supprimé (auquel j'avais répondu... ce qui fait que ma réponse a aussi été supprimée...). Cependant, tu ne pourras pas mélanger les types dans un même programme, à moins de stocker aussi dans une struct l'indication du type, car sinon la fonction appelante ne saura pas comment exploiter le pointeur.
Par exemple ,esce qu’on peut écrire
Et on met
Le void * va pointer sur n’importe quel type de donnée
Bon après vous avez dit que ça peut causer problème si le type n’est pas indiqué
Comment retranstyper?
Le void * ,m’a question est plus une question de curiosité qu’autre chose car en classe on l’a jamais utilisé
typedef void * Donnee; typedef struct Element Element; struct Element{ Donnee donnee; Element *suivant;
Et on met
void empiler_donnee(Pile *pile, Donnee donnee){
Le void * va pointer sur n’importe quel type de donnée
Bon après vous avez dit que ça peut causer problème si le type n’est pas indiqué
Comment retranstyper?
Le void * ,m’a question est plus une question de curiosité qu’autre chose car en classe on l’a jamais utilisé
Voilà une illustration d'une struct comprenant une union et un membre permettant de conserver le type de la donnée, en utilisant un enum pour codifier les types.
Lorsque tu dépiles, tu consultes d'abord le type récupéré, et, en fonction du type, tu accèdes à la valeur récupérée à travers l'union récupérée.
Dal
#include <stdlib.h> enum type_donnee { CHAR, INT, DOUBLE, PCHAR, MAX_TYPES }; union val { char c; int i; double d; char * s; }; typedef struct Donnee Donnee; struct Donnee { union val val; enum type_donnee type; }; typedef struct Element Element; struct Element{ Donnee donnee; Element *suivant; }; typedef struct Pile Pile; struct Pile{ Element *sommet; }; Pile * init_pile(void) { Pile * p = malloc(sizeof(*p)); p->sommet = NULL; return p; } void empiler_donnee(Pile *pile, Donnee donnee){ if (pile == NULL) exit(EXIT_FAILURE); Element *nouveau = malloc(sizeof(*nouveau)); if (nouveau == NULL) exit(EXIT_FAILURE); nouveau->donnee = donnee; nouveau->suivant = pile->sommet; pile->sommet = nouveau; } int main(void) { Pile * p = init_pile(); Donnee donnee; donnee.val.c = 'A'; donnee.type = CHAR; empiler_donnee(p, donnee); donnee.val.i = 123; donnee.type = INT; empiler_donnee(p, donnee); donnee.val.d = 123.45; donnee.type = DOUBLE; empiler_donnee(p, donnee); donnee.val.s = "saperlipopette"; donnee.type = PCHAR; empiler_donnee(p, donnee); return 0; }
Lorsque tu dépiles, tu consultes d'abord le type récupéré, et, en fonction du type, tu accèdes à la valeur récupérée à travers l'union récupérée.
Dal
Si tu ne gardes pas trace du type, lorsque tu dépiles, tu ne sais pas comment accéder aux données stockées dans l'union pour qu'elle soient interprétées selon le bon type.
Comme je le disais :
Lorsque tu dépiles, tu consultes d'abord le type récupéré, et, en fonction du type, tu accèdes à la valeur récupérée à travers l'union récupérée.
Comme je le disais :
Lorsque tu dépiles, tu consultes d'abord le type récupéré, et, en fonction du type, tu accèdes à la valeur récupérée à travers l'union récupérée.
Considère le code suivant :
Comment vais-je l'exploiter ?
Il me faut stocker le type pour garder cette information.
Si le type que je stocke correspond à l'enum PCHAR et que, par convention, PCHAR désigne un pointeur sur char permettant d'accéder à une chaîne C, alors, je pourrais écrire ceci :
/* je mets à zéro la struct, car je vais faire des trucs funky */ Donnee donnee = { 0 }; char str[] = "saperlipopette"; donnee.val.s = str; /* maintenant, disons que je récupère donnee de la Pile sans * information sur le type, tous ces printf sont du C "valide" * mais un seul restitue correctement l'information stockée */ printf("donnee est-elle une chaîne %s\n", donnee.val.s); printf("donnee est-elle un char %c\n", donnee.val.c); printf("donnee est-elle un entier %d\n", donnee.val.i); printf("donnee est-elle un double %f\n", donnee.val.d);
Comment vais-je l'exploiter ?
Il me faut stocker le type pour garder cette information.
Si le type que je stocke correspond à l'enum PCHAR et que, par convention, PCHAR désigne un pointeur sur char permettant d'accéder à une chaîne C, alors, je pourrais écrire ceci :
Donnee donnee; char str[] = "saperlipopette"; donnee.val.s = str; donnee.type = PCHAR; /* maintenant, disons que je récupère donnee de la Pile avec * information sur le type. Je vais pouvoir déterminer comment * adapter mon printf selon le cas */ switch (donnee.type) { case PCHAR: printf("donnee est une chaîne %s\n", donnee.val.s); break; case CHAR: printf("donnee est un char %c\n", donnee.val.c); break; case INT: printf("donnee est un entier %d\n", donnee.val.i); break; case DOUBLE: printf("donnee est un double %f\n", donnee.val.d); break; default: printf("Erreur : type non géré\n"); }