Pile en C

AviateurRex -  
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour à tous,
J'ai quelque modifications à apporter à un scripte mais je n'y arrive pas. Le but de mon projet est de créer une pile en C au format LIFO ( last in first out ) consistant donc a ajouter / supprimer des éléments, le seul élément avec lequel on peut interagir étant celui se trouvant au sommet de la pile.

J'ai donc les scripts suivants:

//   	
// Fichier pile.h
//

#include <stdio.h>
#include <stdlib.h>
typedef float Element;

struct SCellule {
Element info;
struct SCellule *psuiv;
};

typedef struct SCellule *Cellule;

struct SPile{
struct SCellule *sommet;
int nbElements;
};

typedef struct SPile *Pile; Pile

PileVide();

Pile pileAjouter(Pile p, Element e);

Pile pileSupprimer(Pile p);

Element *pileSommet(Pile p);

int pileLongueur(Pile p);


//   	
// Fichier pile.c
//

#include "pile.h"

Pile pileVide(){
Pile p;

p=(Pile)malloc(sizeof(struct SPile));
p->nbElements = 0;
p->sommet = (Cellule) NULL;
return (p);
}

Pile pileAjouter(Pile p, Element e){
Cellule newSommet;

newSommet = (Cellule)malloc(sizeof(struct SCellule));
newSommet->info = e;
newSommet->psuiv = p->sommet;
p->sommet = newSommet;
p->nbElements=p->nbElements + 1;
return (p);
}


Pile pileSupprimer(Pile p){
Cellule tmp;

if(p->nbElements == 0){
return ((Pile)NULL);
}
tmp=p->sommet;
p->sommet = tmp->psuiv;
free(tmp);
p->nbElements = p->nbElements - 1;
return (p);
}

Element *pileSommet(Pile p){
if(p->nbElements == 0){
return ((Element*)NULL);
}
return &(p->sommet->info);
}

int pileLongueur(Pile p){

return p->nbElements;
}


[code]//
// Fichier main.c
//

#include "pile.h"

int main(){
Pile p; Element *elem;
int estSommet=0;

p=pileVide();
pileAjouter(p,1);
pileAjouter(p,2);
pileAjouter(p,3);

while(pileLongueur(p)>0){

if(estSommet == 0){
printf("\nLe sommet de la pile est %0.2f\n\n",*pileSommet(p));
estSommet=1;
}
printf("| %0.2f |\n", *pileSommet(p));
printf("------------\n");
pileSupprimer(p);
}

return (0);

}
[/code]


#   	
# Fichier Makefile
#

BIN = piles
OBJECTS = main.o pile.o
CC = gcc

all: $(OBJECTS)
$(CC) $(OBJECTS) -o $(BIN)

main.o: main.c pile.h
$(CC) -c main.c

vitesse.o : pile.h pile.c
$(CC) -c pile.c

clean:
rm -f $(OBJECTS) $(BIN) *~



J'obtient donc avec ce code :

//   	
// Résultat
//

Le sommet de la pile est 3.00

| 3.00 |
----------
| 2.00 |
----------
| 1.00 |
--------


Ce qui est correcte. Maintenant il faudrait que je remplace les élements 1,2,3 de ma pile par : (‘’fonction#1’’, 0x7F543210, ‘’Ok’’) a la place du 1, (fonction#2’’, 0x7F543220, ‘’987654’’) a la place du 2 et (‘’fonction#3’’, 0x7F543230, ‘’123456’’) a la place du 3. Mon code ne compilant que des éléments de type float j'ai essayé de convertir chaque ligne de type str en float avec la fonction strtof() mais celle ci ne converti que les nombres englobé dans dans "".

J'ai pensé a modifier la structure de l'élément de la façon suivante :

typedef struct {
char *first_string;
int integer_value;
char *second_string;
} Element;


Mais toujours rien.

Je dois donc avoir au final l'ordre d'execution suivant:

pileAjouter (‘’fonction#1’’, 0x7F543210, ‘’Ok’’) ;
pileAjouter (‘’fonction#2’’, 0x7F543220, ‘’987654’’) ;
pileAjouter (’fonction#3’’, 0x7F543230, ‘’123456’’) ;
pilelongueur (Pile) ;
pileafficher (Pile) ;
pileSupprimer (Pile) ;
pilelongueur(Pile) ;
pileafficher (Pile) ;

Merci pour votre aide !



Configuration: Windows / Chrome 94.0.4606.61
A voir également:

24 réponses

AviateurRex
 
Donc au final j'obtiens:

 struct SCellule  * c = p->sommet;
 Element el=c->info;
 c=c->psuiv

printf("%s,0x%X,%x\n",el.first_string,el.integer_value,el.second_string); 


Mais pour le résultat je n'obtient que les sommets et pas la pile en entière :

/// Résultat ///
Affichage des 3 élement(s) de la pile:
fonction#3,0x7F543230,12456
Affichage des 2 élement(s) de la pile:
fonction#2,0x7F543230,987654
1
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Poste ton code entier pour ta fonction
void pileAfficher(Pile p)
, car ton affichage ne correspond pas au code que tu postes.

Fais le seulement après avoir fait l'effort de réfléchir par toi même à ce que tu fais et avoir tenté de déboguer ton code, au lieu de poster un truc approximatif toutes les 5 minutes avec une réflexion superficielle.

Je dois m'absenter pendant plusieurs heures.

A toi de jouer.
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Je te souhaite une bonne soirée ! En espérant que j'aurai bien avancé d'ici ton retour x)
0
AviateurRex
 
Au moins a force de rester en face de mon pc j'ai enfin fini par trouver quelque chose qui marche xD !

Avec les fichiers suivants :

///            ///
///main.c ///
///           ///
include "pile.h"

int main()

{


        Pile p;
        Element *elem;
        int estSommet=0;

        p=pileVide();

        struct Element el1;

        el1.first_string="fonction#1";
        el1.integer_value=0x7F543210;
        el1.second_string="Ok";

        struct Element el2;

        el2.first_string="fonction#2";
        el2.integer_value=0x7F543220;
        el2.second_string="987654";

        struct Element el3;

        el3.first_string="fonction#3";
        el3.integer_value=0x7F543230;
        el3.second_string="123456";

        pileAjouter(p,el1);
        pileAjouter(p,el2);
        pileAjouter(p,el3);

        printf("\n-----------------DEBUT-----------------\n\n");
        printf("1. Initialisation d'une pile\n");
        pileAfficher(p);

        printf("\n2. On dépile un élement de la pile\n");

        pileSupprimer(p);
        pileAfficher(p);

        printf("\n-----------------FIN-----------------\n");

}


et

#include "pile.h"

//
// Fichier piles.c
//


Pile pileVide(){
        Pile p;

        p=(Pile)malloc(sizeof(struct SPile));
        p->nbElements = 0;
        p->sommet = (Cellule) NULL;
        return (p);
}

Pile pileAjouter(Pile p, Element e){
        Cellule newSommet;

        newSommet = (Cellule)malloc(sizeof(struct SCellule));
        newSommet->info = e;
        newSommet->psuiv = p->sommet;
        p->sommet = newSommet;
        p->nbElements=p->nbElements + 1;
        return (p);
}


Pile pileSupprimer(Pile p){
        Cellule tmp;

        if(p->nbElements == 0){
                return ((Pile)NULL);
        }
        tmp=p->sommet;
        p->sommet = tmp->psuiv;
        free(tmp);
p->nbElements = p->nbElements - 1;
        return (p);
}

Element pileSommet(Pile p){ 
        if(p->nbElements == 0){
                return ((Element)NULL);
        }
        return &(p->sommet->info);
}

int pileLongueur(Pile p){

        return p->nbElements;
}

void pileAfficher(Pile p){

        int nbElements=p->nbElements;

        if(p==NULL)
        {
                exit(EXIT_FAILURE);
        }

        if(nbElements<1)
        {
                printf("La pile est vide rien à afficher \n");
                return;
        }

        printf("\nEtat de la pile:\n");
        printf("\nAddresse de la pile: 0x%p\n",p);

        printf("Affichage des %d élément(s) de la pile:\n\n", nbElements);
struct SCellule *c=p->sommet;

        while(c != NULL)
        {
                Element el= c->info;
                c=c->psuiv;
                printf("%s,0x%X,%s\n",el.first_string,el.integer_value,el.second_string);
        }
}


J'obtiens le résultat attendu :

/// Résultat ///
------------------- DEBUT------------------------------

1. Initialisation d'une pile

Etat de la pile:

Addresse de la pile: 0x0x55763dc802a0
Affichage des 3 élément(s) de la pile:

fonction#3,0x7F543230,12456
fonction#2,0x7F543230,987654
fonction#1,0x7F543210,Ok

2. On dépile un élément de la pile

Etat de la pile:

Addresse de la pile: 0x0x55763dc802a0
Affichage des 2 élement(s) de la pile:

fonction#2,0x7F543230,987654
fonction#1,0x7F543210,Ok

------------------- FIN------------------------------


Vraiment merci d'avoir pris autant de ton temps pour m'aider et désolé si parfois je mettais t'as patience à rude épreuve … J'ai appris plus avec toi en une semaine qu'avec un professeur que j'ai depuis plus d'un semestre alors merci encore!
1
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Salut AviateurRex,

Pas de problème. Je suis content si tu as appris des choses grâce à nos échanges.

Bonne continuation
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Salut AviateurRex,

Ce n'est pas un "script", car le C est un langage compilé, et non un langage de script interprété.

Mon code ne compilant que des éléments de type float

Est-ce bien ton code que tu montres ?

j'ai essayé de convertir chaque ligne de type str en float avec la fonction strtof() mais celle ci ne converti que les nombres englobé dans dans "".

Cela ne peut pas marcher. De plus tu as 3 éléments. Il faut bien une struct pour en faire un élément.

J'ai pensé a modifier la structure de l'élément de la façon suivante :

typedef struct {
char *first_string;
int integer_value;
char *second_string;
} Element;

Mais toujours rien.


Que veux-tu dire par "Mais toujours rien" ? Peux-tu montrer ton code adapté pour stocker des struct dans ta pile ? Autrement, on ne sait pas quel est réellement ton problème.

Dal
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
D'autre part, dans ton pile.h, je pense qu'il y a un problème à la ligne 31, où tu indiques un prototype
PileVide();
ne correspondant pas à la fonction
Pile pileVide()
définie dans pile.c

Le C est un langage sensible à la casse.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
La seule modification à faire au module pile (le couple pile.c et pile.h) est en pile.h :
  • le typedef pour Element, qu'il faut remplacer par celui que tu mentionnes
  • un prototype PileVide(); qu'il faut orthographier correctement avec un p minuscule


Ensuite, il faut, bien sûr des changements au main.c, puisqu'il faut :
  • initialiser des struct avec les Elements gérés
  • insérer les struct dans la pile
  • afficher les informations les concernant correctement


et c'est tout.

à quel stade as-tu un problème ?

Dal
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
AviateurRex
 
Déjà merci énormément de prendre de votre temps pour me répondre vous imaginez même pas a quel point vous m'aider. Le langage C est un nouveau langage et j'avoue que j'arrive à être bloquer assez vite dessus. Pourtant j'essaye de comprendre en lisant des cours / ex sur les piles mais j'ai du mal.

En fait le soucis que j'ai c'est qu'une fois que j'ai adopté la structure :

typedef struct {
char *first_string;
int integer_value;
char *second_string;
} Element;


Je n'arrive pas à initialiser les éléments dans le format de ma nouvelle structure ( dans mon main.c donc ) et par conséquent je n'arrive pas non plus à effectuer la liste d'instruction qui suit avec ajouter,supprimer etc.
0
Dalfab Messages postés 706 Date d'inscription   Statut Membre Dernière intervention   101
 
Bonjour,

Je te propose de simplifier le code en utilisant plutôt comme structure:
typedef struct {
    char first_string[30];
    int integer_value;
    char second_string[30];
} Element;
Celle-ci est moins souple mais te permettra d'éviter de passer par des
malloc()
.

Ensuite après avoir modifié l'interface de
Pile pileAjouter(Pile p, ....)
pour qu'elle corresponde à ton besoin, il ne reste qu'à appliquer ce que t'a indiqué Dal. C'est très peu de choses.
0
AviateurRex
 
Bonjour Dalfab, merci pour t'as réponse !

Pourquoi le fait de renseigner "[30]" me dispense d'utiliser la fonction "malloc()"?

Je vais essayer de modifier tout ça alors, merci encore.
0
AviateurRex
 
Du coup, j'ai bien corrigé mon erreur dans le pile.h pour la fonction Pile pileVide(); que j'avais mal saisie comme l'a mentionné Dal, j'ai modifié la structure de l'élément comme l'a suggéré Dalfab. J'ai aussi supprimé tous les malloc() du pile.c. J'ai essayé de modifier mon main.c pour ajouter mes éléments avec leurs nouvelle structure mais je n'y arrive toujours pas, j'essaye de déclarer mes variables mais j'ai encore pleins d'erreurs :

gcc -c main.c
main.c: In function ‘main’:
main.c:12:2: error: ‘val_1’ undeclared (first use in this function)
12 | val_1=("fonction#1", 0x7F543210, "Ok");
| ^~~
main.c:12:2: note: each undeclared identifier is reported only once for each function it appears in
main.c:13:2: error: ‘val_2’ undeclared (first use in this function)
13 | val_2=("fonction#2", 0x7F543220, "987654");
| ^
main.c:14:2: error: ‘val_3’ undeclared (first use in this function)
14 | val_3=("fonction#3", 0x7F543230, "123456");
| ^
main.c:23:43: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘Element’ {aka ‘struct <anonymous>’} [-Wformat=]
23 | printf("\nLe sommet de la pile est %0.2f\n\n",*pileSommet(p));estSommet=1;
| ^ ~~
| | |
| double Element {aka struct <anonymous>}
main.c:27:17: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘Element’ {aka ‘struct <anonymous>’} [-Wformat=]
27 | printf("| %0.2f |\n", *pileSommet(p));
| ^ ~~~~
| | |
| double Element {aka struct <anonymous>}
0
AviateurRex
 
J'ai continué et je suis désolé d'avoir été autant largué ! J'ai bien suivis vos conseils et j'approche enfin de quelque chose mais une erreur me bloque... j'ai donc finalement repris la structure:
typedef struct {
char *first_string;
int integer_value;
char *second_string;
} Element;


Je ne sais pas pourquoi celle que Dalfab avait renseigné ne marchait pas. J'ai donc rajouter à mon main.c les lignes suivantes pour pouvoir définir mes élements :

        struct Element fonction1; 

fonction1.first_string= "Fonction#1";
fonction1.integer_value=0x7F543210;
fonction1.second_string= "Ok";

struct Element fonction2;

fonction1.first_string= "Fonction#2";
fonction1.integer_value=0x7F543220;
fonction1.second_string= "987654";

struct Element fonction3;

fonction1.first_string= "Fonction#3";
fonction1.integer_value=0x7F543230;
fonction1.second_string= "123456";

pileAjouter(p,fonction1);
pileAjouter(p,fonction2);
pileAjouter(p,fonction3);


Mais pour les 3 fonctions, j'ai la même erreur : storage size of "fonction " isn't known. Jj'ai vu que ce problème venait souvent par la déclaration des structures pourtant la mienne respecte bien la forme struct NomDeLaStructure NomDeL'argument .
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Bonjour AviateurRex,

Merci de finalement montrer un bout de code. Si tu ne le fais pas on en est réduits aux suppositions sur la nature de tes problèmes, même si certains messages d'erreurs peuvent nous renseigner.

Tout d'abord, ne supprime pas les malloc() dans pile.c

L'indication de Dalfab portait sur ton code dans main.c : pour te faciliter la vie dans ton code et t'éviter d'avoir à gérer des pointeurs et une allocation dynamique éventuellement nécessaire pour stocker tes chaînes.

Ensuite, s'agissant de ton erreur, elle vient du fait que tu déclares tes variables avec un type non connu.

Avec le code suivant :

typedef struct {
    char *first_string;
    int integer_value;
    char *second_string;
} Element;


tu fais 2 choses :
  • tu crées une struct anonyme (qui n'a pas d'étiquette après le mot clef struct)
  • et tu crées un type qui est un alias de cette struct et que tu nommes Element.


Si tu veux utiliser ce type, tu dois utiliser l'alias en tant que type, comme ceci :
Element fonction1;
...

Si tu avais défini un type struct avec son étiquette, comme il se doit, tu pourrais utiliser le type struct pour définir tes variables.

struct Element {
    char *first_string;
    int integer_value;
    char *second_string;
};


tu utilises le type struct Element comme ceci :
struct Element fonction1;
...

Si tu veux pouvoir définir tes variables soit avec l'alias typedef, soit avec le nom de la struct, tu peux définir ton type comme ceci :

typedef struct Element {
    char *first_string;
    int integer_value;
    char *second_string;
} Element;
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
attention aussi à tes copier-collers.

Si tu initialises 3 fois les valeurs internes à la struct pour la même variable "fonction1" comme tu le fais, en oubliant de faire changer le nom des variables que tu est censé initialiser ensuite en "fonction2" et "fonction3", ces dernières ne sont pas initialisées et contiendront quelque chose qui ne conviendra pas.

(en passant, tu devrais vraiment choisir un autre nom, car appeler un élément d'une liste "fonction" est très moyen, par exemple el1, el2, el3 auraient ma préférence et feraient mieux l'affaire)
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
autre remarque, dans ton message d'origine, tu disais :

il faudrait que je remplace les élements 1,2,3 de ma pile par : (‘’fonction#1’’, 0x7F543210, ‘’Ok’’) a la place du 1, (fonction#2’’, 0x7F543220, ‘’987654’’) a la place du 2 et (‘’fonction#3’’, 0x7F543230, ‘’123456’’) a la place du 3

Si tu mets dans ton champ first_string de chaque variable un pointeur vers des chaînes "Fonction#1", "Fonction#2" et "Fonction#3" avec un "F" et non pas un "f" tu ne fais peut-être pas que qu'on te dit de faire ... enfin, c'est toi qui vois ce que tu dois faire :-)
0
AviateurRex
 
Merci énormément pour toute ton aide Dal ! Je vais m'y remettre et je vous tiendrai au courant de mon avancé.
0
AviateurRex
 
EDIT

J'ai donc modifié ma structure comme tu l'as dis et j'ai aussi changé mon main.c et j'obtiens au final :

#include "pile.h"

int main(int argc, char *argv[])

{

printf("1. INITIALISATION DE LA PILE");
Pile p;
Element *elem;
int estSommet=0;

p=pileVide();

struct Element el1;

el1.first_string="fonction#1";
el1.integer_value=0x7F543210;
el1.second_string="Ok";

struct Element el2;

el2.first_string="fonction#2";
el2.integer_value=0x7F543220;
el2.second_string="987654";

struct Element el3;

el3.first_string="fonction#3";
el3.integer_value=0x7F543230;
el3.second_string="123456";

pileAjouter(p,el1);
pileAjouter(p,el2);
pileAjouter(p,el3);

while(pileLongueur(p)>0){

if(estSommet == 0){
printf("\nLe sommet de la pile est %0.2f\n\n",*pileSommet(p));estSommet=1;

}

printf("| %0.2f |\n", *pileSommet(p));
printf("---------\n");
pileSupprimer(p);
}

return (0);

}


Bonne nouvelle, je n'ai plus d'erreur en compilant, mauvais nouvelle la pile que je reçois est :



Le sommet de la pile est 0.00

| 0.00 |
----------
| 0.00 |
----------
| 0.00 |
--------
0
AviateurRex
 
Lors de l'exécution tout à l'heure aucune erreur et la j'en ai, elles n'apparaissent pas à chaque compilage.

J'ai donc les erreurs suivantes :

gcc -c main.c
main.c: In function ‘main’:
main.c:39:41: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘Element’ {aka ‘struct Element’} [-Wformat=]
39 | printf("Le sommet de la pile est %0.2f\n\n",*pileSommet(p));estSommet=1;
| ~~^ ~~
| | |
| double Element {aka struct Element}
main.c:43:17: warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘Element’ {aka ‘struct Element’} [-Wformat=]
43 | printf( "|%0.2f|\n", *pileSommet(p));
| ^ ~~~~
| | |
| double Element {aka struct Element}


Ce qui me semble cohérent puisque c'est l'affichage qui me pose problème.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Salut,

Ce que tu postes sont des avertissements et non des erreurs. Cela signifie que ton code est syntaxiquement correct et peut générer un exécutable, en raison de la souplesse du langage C, mais que ce que écris n'a pas beaucoup de sens à moins que tu saches très exactement ce que tu fais et que dans 90% des cas c'est très certainement erroné.

Tu devrais toujours compiler avec les warnings en mettant au minimum l'option
-Wall
systématiquement, et toujours prendre en compte ce qu'ils disent.

Ensuite, tu dois compiler non seulement main.c, mais aussi pile.c, qui est le module dont tu utilises les fonctions accessibles par l'entête pile.h.

Enfin, l'option de ligne de commande -c sert juste à compiler, et pas à générer un exécutable.

Ta ligne de commande devrait être pour compiler les fichiers utiles et les lier pour produire un exécutable :
gcc -Wall main.c pile.c


Si tu es sous Linux et que la compilation réussit, tu devrais avoir un fichier créé sous le nom par défaut
a.out
que tu peux lancer un ligne de commande en tapant
./a.out
. SI tu es sous Windows, c'est un .exe qui est créé.

Si tu veux choisir un autre nom d'exécutable, tu l'indiques en ligne de commande avec l'option
-o
. Par exemple, sous Linux pour avoir un exécutable dénommé simplement "piles" :

gcc -Wall main.c pile.c -o piles


Maintenant, que te disent les warnings.

Tu as un conflit de types, car ton printf() comporte un spécificateur pour afficher un nombre flottant, alors que tu passes en argument une struct.

Que veux tu afficher réellement ?
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Le seul soucis que j'ai du coup c'est les printf, je veux afficher les éléments de ma structure (el1,el2,el3). J'ai pensé à faire :

printf( " fonction1 = %s\n", el1.first_string);
printf( " 0x7F543210 = %s\n", el1.integer_value);
printf( " Ok = %s\n", el1.second_string);


Mais je n'y arrive pas.

Du coup il faudrait que j'arrive à :


- ajouter mes éléments ( ce qui est fait avec les el1,el2,el3)

- afficher tous mes éléments et mettre en évidence le sommet de la pile

- supprimer le dernier élément

- afficher la pile avec les éléments et le nouveau sommet
0
AviateurRex
 
EDIT

Pour te donner une idée du résultat je devrai obtenir quelque chose qui ressemble à ça :

1.1 Affichage de la pile

Le sommet de la pile est "fonction#3’’, 0x7F543230, ‘’123456’’

|"fonction#3’’, 0x7F543230, ‘’123456’’|
--------------------------------------------------------------
|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
-------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------

1.2 Affichage de la pile (le dernier élément supprimé )

Le sommet de la pile est ‘’fonction#2’’, 0x7F543220, ‘’987654’’

|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Tu as deux difficultés. La première est de trouver le bon spécificateur de format pour ce que tu veux afficher.
  • Tu dois afficher deux chaînes, pour elles le spécificateur de format de printf() est bien %s
  • Tu dois afficher un entier en base hexadécimale avec des lettres majuscules précédé de 0x. Pour afficher cela, tu ne peux pas utiliser %s comme tu le proposes, qui est réservé aux chaînes C.


https://www.cplusplus.com/reference/cstdio/printf/

Selon cette documentation, qui donne des exemples comprenant presque exactement ce même cas, tu dois pouvoir utiliser un spécificateur %#X pour avoir des résultats comme 0X7F543230 ou %#x pour avoir des résultats comme 0x7f543230. A toi de voir si l'un des deux peut convenir.

Le C peut gérer le préfixage automatique de 0X ou 0x pour toi, mais pas de la façon exacte attendue 0x7F543230 (avec un 0x minuscule et des lettres majuscules dans le nombre hexa).

Si tu veux effectivement 0x7F543230 tu peux simplement utiliser le spécificateur %X pour disposer d'un affichage de type 7F543230 et précéder ce spécificateur des caractères 0x, donc : 0x%X, ce qui affiche la suite de caractères exactement voulue.

Plus qu'une difficulté, c'est accéder aux différents membres de la struct à partir de ce que te renvoie pileSommet(p).

Le prototype de cette fonction est
Element *pileSommet(Pile p)
, elle renvoie donc un pointeur vers Element, c'est à dire, dans notre cas, un pointeur sur une struct.

Si tu te fies à l'exemple initial dont tu disposes, tu devrais donc :
  • déréférencer ce pointeur avec l'opérateur
    *
    pour accéder à l'élément
  • utiliser l'opérateur
    .
    pour accéder au membre souhaité


mais tu dois aussi prendre en compte les règles de préséance et associativité des opérateurs en C pour l'opérateur
.
et
*
...

https://en.cppreference.com/w/c/language/operator_precedence

Il y a aussi un moyen plus simple de déréférencer un pointeur sur une struct pour accéder à un de ses membres, c'est d'utiliser l'opérateur
->
qui évite de se prendre la tête avec les deux opérateurs précédents, qui ne discutent pas bien ensemble. C'est un raccourci bien pratique créé par le langage C car il est fréquent de devoir déréférencer un pointeur sur une struct pour accéder à un de ses membres.

Tu as tous les éléments désormais. A ton avis comment faut-il écrire un printf() pour afficher, par exemple le membre first_string à partir de ce que te renvoie pileSommet(p) ?
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Pour le problème d'affichage de la base hexadécimale j'ai bien compris de quoi il était question, par contre pour le second j'avoue que je saisie pas très bien l'histoire de déréférencement ... Je vois pas vraiment la structure que le printf peut avoir.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
  • si tu ne sais pas ce que signifie "déréférencer un pointeur", c'est probablement que tu ne sais pas ce qu'est un pointeur, ni comment l'utiliser

ton code d'origine déréférence le pointeur sur.float renvoyé par pileSommet(p) en faisant
*pileSommet(p)
c'est à dire avec l'opérateur
*
dans la ligne
printf("| %0.2f |\n", *pileSommet(p));
...

Tu devrais vraiment regarder ton manuel de C sur les pointeurs ou ton cours. C'est très gênant, en C, de ne pas savoir utiliser les pointeurs.
  • regarde aussi, ensuite, les pointeurs sur les struct et la notation spéciale
    ->


Si tu veux une explication générale sur les pointeurs, je peux te la donner, mais cela m'étonne beaucoup que tu n'en disposes pas déjà quelque part.

Le but de mon projet est de créer une pile en C au format LIFO ( last in first out ) consistant donc a ajouter / supprimer des éléments, le seul élément avec lequel on peut interagir étant celui se trouvant au sommet de la pile.

dans quel contexte fais tu ce projet ?
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
C'est un devoir à rendre, je suis en licence informatique et je dois rendre ce devoir pour mardi au plus tard. Ce devoir c'est vraiment le 1er code que je fais en C, et pour ce qui est du cours je n'en n'ai pas, c'est bien pour ça que j'ai du mal à intégrer toutes ces nouvelles notions. J'ai appris bien plus sur ce forum qu'avec mon professeur qui ne nous communique pas grand chose.

Le code que j'avais au départ, c'est un code que j'ai plus ou moins fait en me basant sur divers exemple sur internet, je ne savais même pas au départ que je devais créer un fichier .h pour définir mes structures donc autant dire que je viens de loin ... Dans l'ensemble j'ai assez bien compris l'élaboration des fonctions et l'implémentation des structures dans moi main mais pour l'affichage la j'ai du mal.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
OK, c'est étonnant qu'on ne t'explique pas les pointeurs en C, ou qu'on ne te donne pas un cours ou un manuel, ouvrage ou de site de référence auquel tu puisse te référer.

Voilà une explication très générale sur les pointeurs en C.

Un pointeur est juste un moyen en langage C d'accéder indirectement à un contenu d'un certain type stocké en mémoire au moyen de son adresse mémoire. C'est tout.

Un type
Element *
signifie "un pointeur vers un contenu de type
Element
".

Dans le code d'origine pileSommet() renvoie un pointeur sur float et le printf() utilise le contenu retourné par cette fonction en la précédant de l'opérateur
*
qui est l'opérateur d'indirection du C, permettant de déréférencer l'adresse mémoire et d'accéder au contenu pointé par cette adresse. Au final, ce qui est passé en argument de printf() est le float (auquel on a accédé indirectement) et comme cela correspond bien au spécificateur de printf()
%f
, l'affichage est correct.

Vois :

https://zestedesavoir.com/tutoriels/755/le-langage-c-1/1043_aggregats-memoire-et-fichiers/4277_les-pointeurs/

puis :

https://zestedesavoir.com/tutoriels/755/le-langage-c-1/1043_aggregats-memoire-et-fichiers/4279_structures/#2-structures-et-pointeurs

où tu verras qu'il est préférable, pour les pointeurs sur struct, de ne pas utiliser l'opérateur d'indirection
*
en raison des complications de syntaxe qu'il suppose utilisé conjointement avec
.
et d'utiliser l'opérateur
->
et qui est beaucoup plus pratique pour déréférencer un pointeur sur une struct lorsqu'on veut accéder à un de ses membres.

Si tu es en licence informatique, tu as dû apprendre à maîtriser plusieurs langages et tu dois être en mesure de saisir le fonctionnement d'autres langages avec des paradigmes similaires par tes propres efforts en consultant des documents de référence comme ceux que tu trouves sur les liens que je t'ai donnés :

https://www.cplusplus.com/reference/cstdio/printf/
https://en.cppreference.com/w/c/language/operator_precedence

Ou en suivant des tutoriels simples comme celui de ZdS qui est bien fait pour mettre le pied à l'étrier de débutants complets en programmation, qui devrait donc être très largement à ton niveau :-)
0
AviateurRex
 
Je commence enfin à en voir la fin de ce code ! x) Bon c'est toujours pas fini mais déjà les pointeurs ne me semble plus inconnu. Pour l'instant j'arrive juste à afficher :

Le sommet de la pile est 


|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
--------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
-------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------


J'arrive pas à comprendre comment structurer mon code avant la fonction Pilesommet(p) en fait.

Par exemple dans cette partie la :

while(pileLongueur(p)>0){

if(estSommet == 0){
printf("\nLe sommet de la pile est "mettre les données de el3"\n\n",*pileSommet(p));estSommet=1;


Je ne comprend pas comment mettre les données de el3. Parceque la, la fonction Pilesommet(p) a un pointeur * vers mon Element qui est à la structure char,int,char. je dois forcément mettre %s,0x%x,%s ,el3.first_string,el3.ineger_value,el3.second_string dans mon print non ?

Et pour l'affichage des el1,el2,el3 je pense qu'il ne marche pas à cause de Pilesommet(p).

J'ai le code suivant pour l'instant :

while(pileLongueur(p)>0){

if(estSommet == 0){
printf("Le sommet de la pile est \n\n",*pileSommet(p)); estSommet=1;

}

printf( "|%s,0x%x,%s|\n",el1.first_string,el1.integer_value,el1.second_string) ;
printf("---------\n");

pileSupprimer(p);
}

return (0);

}
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
le but du while est de faire fonctionner la pile, en :
  • utilisant une fonction qui renvoie l'élément au sommet
  • utilisant une fonction qui dépile cet élément pour passer au suivant
  • tant qu'il y a quelque chose dans la pile


tu ne dois donc pas y utiliser les variables el1, el2 ou el3, dont le contenu est déjà accessible par la pile.

Comme dans ton code de départ, tu dois utiliser ce qui est renvoyé par pileSommet()
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Dans mon code initial, la méthode utilisé dans le printf() était avec %0.2f était utilisé avec 0.2 pour donner la précision voulue et f pour le type de donnée utilisée. pileSommet() pointe la
structure, donc pourquoi quand je renseigne :

printf("Le sommet de la pile est %s,0x%x,%s \n\n",*pileSommet(p)); estSommet=1;


j'ai une erreur :

main.c:39:39: warning: format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘Element’ {aka ‘struct Element’} [-Wformat=]
39 | printf("Le sommet de la pile est %s,0x%x,%s\n\n",pileSommet(p)); estSommet=1;
| ~^ ~~~~~~
| | |
| char * Element {aka struct Element}
main.c:39:44: warning: format ‘%x’ expects a matching ‘unsigned int’ argument [-Wformat=]
39 | printf("Le sommet de la pile est %s,0x%x,%s\n\n",*pileSommet(p)); estSommet=1;
| ~^
| |
| unsigned int
main.c:39:47: warning: format ‘%s’ expects a matching ‘char ’ argument [-Wformat=]
39 | printf("Le sommet de la pile est %s,0x%x,%s\n\n",pileSommet(p)); estSommet=1;
| ~^
| |
|


L'erreur me dit bien que pileSOmmet() pointe vers Element alors pourquoi n'arrive t'il pas a afficher les elements de la structure ?
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
Parce qu'à chacun des 3 spécificateurs de printf() que tu indiques %s,0x%x,%s doit correspondre un argument passé à la suite d'un type compatible, donc 3 arguments : un chaîne, un entier et une chaîne, et là tu passes 1 seul argument qui est de type struct.

Le compilateur ne sait pas "magiquement" afficher le contenu de la struct, tu dois lui passer le contenu individuel de chaque membre de la struct correspondant au spécificateur d'affichage qui lui correspond.
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
c'est à dire qu'il faut que je fasse une sorte de :

 first_string -> addresse =%s;
value_integer->valeur= 0x%x;
second_string-> chaine="%s;


en amont dans mon main ?
0
AviateurRex
 
Je ne comprend pas où renseigner les arguments, ça va faire 1H que je cherche mais je n'y arrive pas. Peu importe où je les renseigne dans le printf j'ai toujours une erreur qui suit avec pileSommet().

Comment placer les arguments pour que tout s'affiche donc ? :3
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Voilà comment tu peux écrire la ligne donnant l'information sur le sommet de la pile en affichant, par exemple, seulement "Fonction#3".

printf("\nLe sommet de la pile est %s\n\n", pileSommet(p)->first_string);


Est-ce que tu arrives à relier les points maintenant ?

Je pense que tu n'as pas (bien) lu les 2 liens vers le tutoriel de ZdS sur les pointeurs et les struct que je t'ai adressés, avec le cas des pointeurs de struct.

Vois : https://zestedesavoir.com/tutoriels/755/le-langage-c-1/1043_aggregats-memoire-et-fichiers/4277_les-pointeurs/

puis : https://zestedesavoir.com/tutoriels/755/le-langage-c-1/1043_aggregats-memoire-et-fichiers/4279_structures/#2-structures-et-pointeurs

Comprendre ces deux chapitres est important pour comprendre pourquoi on fait comme cela. Tu pourrais aussi prendre le tutoriel dès le début et pratiquer chaque chapitre avec des exercices beaucoup plus simples que celui auquel tu t'attaques ... cela ne peut pas faire de mal :-)
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Depuis le début je laissait le pointeur * sur Pilesommet() ... forcément ça allait avoir du mal à fonctionner x)
Pour l'instant j'ai donc :

1.1 Affichage de la pile

Le sommet de la pile est "fonction#3’’, 0x7F543230, ‘’123456’’

|"fonction#3’’, 0x7F543230, ‘’123456’’|
--------------------------------------------------------------
|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
-------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------


Ce qui est carrément bon ! (grâce a 200% à toi) maintenant manque plus que la phase dépilage et c'est fini. Je m'y met de suite.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
pour déréférencer le pointeur sur struct retourné par ta fonction et accéder à un de ses membres, tu peux écrire :
  • (*pileSommet(p)).first_string
    ou alors
  • pileSommet(p)->first_string
    qui est plus lisible


l'opérateur
->
a été créé en C pour signifier les deux actions de déréférencement de pointeur sur struct et d'accès à un membre de la struct, car sinon les règles de préséance des opérateurs
*
et
.
imposent une syntaxe complexe avec des parenthèses qui est peu commode.

Le tutoriel de ZdS le dit très clairement :

l’opérateur . s’applique prioritairement à l’opérateur *. (...)
Pour résoudre ce problème, nous devons utiliser des parenthèses afin que l’opérateur . soit appliqué après le déréférencement, ce qui donne la syntaxe suivante.

(*p).heures = 1;

Cette écriture étant un peu lourde, le C fourni un autre opérateur qui combine ces deux opérations : l’opérateur ->.

p->heures = 1;
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
J'avais bien regardé cet exemple justement, dans leur exemple le "p" est définit dans une structure ce qui était différent de mon cas puisque la fonction Pilesommet() était définit par un Elément lui même définit par une structure. C'est pour ça que je n'arrivais pas à faire le parallèle mais finalement c'est le même fonctionnement.
0
AviateurRex
 
Pour changer je bloque encore xD, bon la fin n'est plus très loin je vais pas arrêter la. Donc, pour dépiler, j'utilise ma fonction pileSupprimer() qui m'enlève -1 à mon compteur d'élément. J'ai donc testé de le mettre à la suite du main simplement après l'exécution de la 1ère phase de la pile ( toujours dans la boucle while donc ) mais ce n'est pas trop concluant. J'arrive bien a dépiler :

Etat de la pile:
Le sommet de la pile est fonction#3,0x7f543230,123456

|fonction#3,0x7f543230,123456|
------------------------------
2. ON DEPILE UN ELEMENT DE LA PILE
|fonction#2,0x7f543220,987654|
------------------------------
|fonction#2,0x7f543220,987654|
------------------------------
2. ON DEPILE UN ELEMENT DE LA PILE
|fonction#1,0x7f543210,Ok|
------------------------------
|fonction#1,0x7f543210,Ok|
------------------------------
2. ON DEPILE UN ELEMENT DE LA PILE


Mais je dépile jusqu'à tout supprimer. J'ai donc essayer de rajouter un if a la suite qui aurait comme condition estSommet == 3 avec une suite d'instruction pour dépiler uniquement quand la pile atteint 3 éléments mais la aussi ça ne marche pas
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Quand tu demandes de l'aide sur un forum, quel qu'il soit :

1. poste ton code
2. indique le résultat que tu obtiens
3. indique le résultat que tu voudrais obtenir
4. explique en quoi ce que tu obtiens te paraît erroné, ce que tu ne comprends pas ou sur quoi tu "bloques" exactement

Notes importantes sur CCM :
  • quand tu postes un affichage d'écran, tu peux le faire sur le forum CCM comme tu le fais avec les balises de code simples en cliquant sur bouton code du forum qui insère les balises génériques.
  • en revanche, quand tu postes du code dans un certain langage, utilise la flèche ▼ à droite du bouton, et sélectionne le langage (ici "c") pour disposer de balises qui vont correctement colorer syntaxiquement ton code lors de son affichage sur le forum et numéroter les lignes.


c'est plus agréable, et cela permet de te dire, telle ligne tu fais ceci etc.
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Désolé pour les balises, je n'avais pas vu qu'on pouvait spécifier le type de langage qu'on utilisait .

Mon main.c:

#include "pile.h"

int main()

{

        printf("1. INITIALISATION DE LA PILE\n");

        Pile p;
        Element *elem;
        int estSommet=0;

        p=pileVide();

        struct Element el1;

        el1.first_string="fonction#1";
        el1.integer_value=0x7F543210;
        el1.second_string="Ok";

        struct Element el2;

        el2.first_string="fonction#2";
        el2.integer_value=0x7F543220;
        el2.second_string="987654";

        struct Element el3;

        el3.first_string="fonction#3";
        el3.integer_value=0x7F543230;
        el3.second_string="123456";

        pileAjouter(p,el1);
        pileAjouter(p,el2);
        pileAjouter(p,el3);

        printf("\n Etat de la pile:");
[02:31]
while(pileLongueur(p)>0){

                if(estSommet == 0){
                        printf("\nLe sommet de la pile est  %s,0x%x,%s\n\n", pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string); estSommet=1;

                }

                printf( "|%s,0x%x,%s|\n",pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string) ;
                printf("------------------------------\n");
                 pileSupprimer(p);


                printf("2. ON DEPILE UN ELEMENT DE LA PILE\n");
                printf( "|%s,0x%x,%s|\n",pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string) ;
                printf("------------------------------\n");


        }

        return (0);



Mon résultat :

Etat de la pile:
Le sommet de la pile est fonction#3,0x7f543230,123456

|fonction#3,0x7f543230,123456|
------------------------------
2. ON DEPILE UN ELEMENT DE LA PILE
|fonction#2,0x7f543220,987654|
------------------------------
|fonction#2,0x7f543220,987654|
------------------------------
2. ON DEPILE UN ELEMENT DE LA PILE
|fonction#1,0x7f543210,Ok|
------------------------------
|fonction#1,0x7f543210,Ok|
------------------------------
2. ON DEPILE UN ELEMENT DE LA PILE
0
AviateurRex > AviateurRex
 
Le résultat attendu :

1.1 Affichage de la pile

Le sommet de la pile est "fonction#3’’, 0x7F543230, ‘’123456’’

|"fonction#3’’, 0x7F543230, ‘’123456’’|
--------------------------------------------------------------
|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
-------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------

2 ON DEPILE UN ELEMENT DE LA PILE

Le sommet de la pile est ‘’fonction#2’’, 0x7F543220, ‘’987654’’

|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------


La ou je bloque :


Seulement retirer le dernier élément de la pile une seule et unique fois et pas jusqu'à la suppression de la pile.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
Tu n'as donc pas besoin d'une boucle while.

Edit: je viens de voir ton 2ème message
en fait tu veux pouvoir afficher le contenu de toute la pile sans dépiler ?
cela me semble aller à l'encontre à l'idée de pile ... où par définition tu n'accèdes qu'au sommet ...
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
En fait il y a 2 parties si on veut. La partie pour laquelle tu m'as montré comment faire pointer Pilesommet(), donc simplement afficher tous mes éléments et son sommet. Et la seconde partie, qui s'exécute à la suite directement, enlève le dernier élément ajouté (ici el3 ) pour encore afficher la pile mais cette fois avec un nouveau sommet forcément puisqu'on à supprimé el3 qui sera remplacé par el2.

Le résultat attendu :


Le sommet de la pile est "fonction#3’’, 0x7F543230, ‘’123456’’

|"fonction#3’’, 0x7F543230, ‘’123456’’|
--------------------------------------------------------------
|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
-------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------

2 ON DEPILE UN ELEMENT DE LA PILE

Le sommet de la pile est ‘’fonction#2’’, 0x7F543220, ‘’987654’’

|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
------------------------------------------------------------
|‘’fonction#1’’, 0x7F543210, ‘’Ok’’ |
------------------------------------------------------------


S'obtient en une seule exécution du code.
0
AviateurRex
 
EDIT

Comme d'habitude je rame mais c'est pas grave x). J'ai essayé plusieurs choses. Tout d'abord je me suis dis que la fonction pileSupprimer() s'exécutait jusqu'à supprimer tous les éléments alors que moi je n'ai besoins qu'elle ne supprime que le sommet de la pile. J'ai donc essayé de rajouter des break pour contraindre le pileSupprimer() à enlever un seul élément.

Avec ce code :

while (pileLongueur(p)>0){
                if(estSommet == 0){
                        printf("\nLe sommet de la pile est  %s,0x%x,%s\n\n", pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string); estSommet=1;


                printf( "|%s,0x%x,%s|\n",pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string) ;
                printf("------------------------------\n");


                pileSupprimer(p);

                printf("2. ON DEPILE UN ELEMENT DE LA PILE\n");
                printf("\nLe sommet de la pile est  %s,0x%x,%s\n\n", pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string); estSommet=1;
                printf( "|%s,0x%x,%s|\n",pileSommet(p)->first_string,pileSommet(p)->integer_value,pileSommet(p)->second_string) ;
                printf("------------------------------\n");

                }
                break;


J'obtiens :



1. Initialisation d'une pile


Le sommet de la pile est "fonction#3’’, 0x7F543230, ‘’123456’’

|"fonction#3’’, 0x7F543230, ‘’123456’’|
--------------------------------------------------------------


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

2. ON DEPILE UN ELEMENT DE LA PILE

Le sommet de la pile est ‘’fonction#2’’, 0x7F543220, ‘’987654’’

|‘’fonction#2’’, 0x7F543220, ‘’987654’’|
------------------------------------------------------------


Ce qui revoit du coup les bons sommets mais pas les piles en entières.
0
AviateurRex
 
EDIT
J'ai réussi à afficher le nombre d'éléments de la pile avec la ligne :

printf("\n Nombre d'élements: %i,pileLongueur(p) );


Même si j'ai un avertissement me disant que %i est de type int et pileLongueur(p) est de type int *. Pour pouvoir utiliser pileLongueur j'ai modifié sa structure en tant que

int *pileLongueur(Pile p) 


afin de récupérer les informations de la pile.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Pour pouvoir utiliser pileLongueur j'ai modifié sa structure en tant que
int *pileLongueur(Pile p)
afin de récupérer les informations de la pile.


Non, laisse la en
int pileLongueur(Pile p);
, elle retourne un int qui est la seule information qu'il te faut.

Par ailleurs, le simple fait de changer son prototype (et non sa "structure") ne va pas magiquement faire que la fonction va retourner autre chose que ce qu'elle fait. Tu crées juste une incohérence dans le type de ce qu'elle retourne.

J'ai donc essayé de rajouter des break pour contraindre le pileSupprimer() à enlever un seul élément. Avec ce code :
while (pileLongueur(p)>0){
(...)


Après avoir rempli ta pile avec les 3 éléments Ton code d'origine (que tu essayes de bidouiller) fait , en gros :

tant que la pile n'est pas vide
pileAfficheSommet(Pile);
pileSupprimer(Pile) ;
fin tant que

Alors que, si je comprends bien, ton travail consiste à fournir à l'écran les résultats successifs des appels suivants après avoir rempli ta pile avec les 3 éléments :

pilelongueur (Pile) ;
pileafficher (Pile) ;
pileSupprimer (Pile) ;
pilelongueur(Pile) ;
pileafficher (Pile) ;


C'est juste une séquence d'opérations. Comme je le disais plus haut, tu n'as pas besoin d'un while qui dépile la pile tant qu'elle n'est pas vide, puisque ce n'est pas ce que tu veux faire.

Là pour le coup ce n'est plus un problème de compréhension du langage C, mais d'algorithmique, car tu trouves ce type de boucle dans tous les langages.

Tu n'as pas besoin de ce while, par contre tu as besoin d'une fonction
void pileAfficher(Pile p);
.

Relis mon post https://forums.commentcamarche.net/forum/affich-37364731-pile-en-c#41 à partir de "Enfin, si tu dois vraiment afficher le contenu de la pile sans dépiler, tu ne dois pas utiliser un while comme dans ton code qui dépile toute la pile en n'affichant que le sommet à chaque itération." et mes posts suivants.
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Tu as bien compris l'ordre d'execution des fonctions. Je vais enlever le while et voir ce que je peux faire. Lorsqu'on élabore une fonction void celle-ci ne renvoit à rien non ? Je dois L'implémenter dans pile.c à la place de la fonction qui y est déjà ? En attendant je vais déjà essayer de voir la séquence d'empilage/dépilage.
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
Oui, une fonction
void pileAfficher(Pile p);
ne renvoie rien. Mais c'est à toi de juger si cette proposition te convient.

Par exemple, tu pourrais décider que ta fonction a un prototype
int pileAfficher(Pile p);
et renvoie un code d'erreur ou de succès, ou autre chose. Cela ne semble pas pertinent, par contre, de lui faire retourner la Pile p comme les fonctions
Pile pileAjouter(Pile p, Element e);
et
Pile pileSupprimer(Pile p);
car, contrairement à ces fonctions, la tienne ne vas rien changer au contenu de la Pile.

Je dois L'implémenter dans pile.c à la place de la fonction qui y est déjà ?

A la place de quelle fonction ? Cette fonction ne remplace aucune "qui y est déjà". C'est une fonction nouvelle que tu dois créer car tu ne disposes d'aucune fonction dans ton module te permettant de parcourir le contenu d'une Pile sans dépiler pour afficher ce contenu. Ce dont tu disposes c'est de fonctions permettant de retourner le sommet de la pile et de dépiler.

Que tu la mettes dans ton main.c ou dans ton module, c'est à toi de voir.

Si tu n'es pas l'auteur de ce module, comme je le pense, tu devrais créditer l'auteur de celui-ci et identifier tes changements dans des commentaires.
0
AviateurRex
 
Si je comprend bien, je dois créer une nouvelle dans ce style là ?

void pileAfficher(Pile p)
{
    if (p== NULL)
    {
        exit(EXIT_FAILURE);
    }
    Element *actuel = pile->premier;

    while (actuel != NULL)
    {
        printf("%s,0x%x,%s\n", actuel->first_string,actuel->integer_value,actuel->second_string);
        actuel = actuel->suivant;
    }

    printf("\n");
}
0
AviateurRex
 
Module basé sur le code de Range Gonnage, OpenClassRooms, section pile et file
0
AviateurRex
 
EDIT

ça fait un petit moment déjà que je suis sur cette fonction void et je pense être sur la bonne voie.

J'ai la fonction suivante :

void pileAfficher(Pile p){
        if(p==NULL)
        {
                exit(EXIT_FAILURE);
        }
        Element *actuel = p->sommet;

        while (actuel != NULL)
        {
                printf("%s,0x%x,%s\n",actuel->first_string,actuel->integer_value,actuel->second_string);
                actuel = actuel->psuiv;
        }

        printf("\n");
}


Qui me renvoie une erreur et un avertissement :

pile.c: In function ‘pileAfficher’:
pile.c:59:20: warning: initialization of ‘Element *’ {aka ‘struct Element *’} from incompatible pointer type ‘struct SCellule *’ [-Wincompatible-pointer-types]
59 | Element *actuel = p->sommet;
| ^
pile.c:64:18: error: ‘Element’ {aka ‘struct Element’} has no member named ‘psuiv’
64 | actuel = actuel->psuiv;
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
As tu bien lu mon post https://forums.commentcamarche.net/forum/affich-37364731-pile-en-c#41 à partir de "Enfin, si tu dois vraiment afficher le contenu de la pile sans dépiler, tu ne dois pas utiliser un while comme dans ton code qui dépile toute la pile en n'affichant que le sommet à chaque itération." (et mes posts suivants).

Quel est le type de Pile, que contient-il, quel est le type des éléments qu'il contient ?

Tu ne peux pas faire "au hasard, en aveugle".
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
c'est la 3ème fois que je t'alerte sur ces informations. Au bout de 3 fois j'ai atteint mon quota et je ne me répète plus :-)
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Je ne veux pas te faire un affront loin de là x).

Le type de Pile est un pointeur vers SPile composé du nombre d'élements et de sommet qui est un pointeur sur SCellule.

Jusqu'ici c'est ça non ?
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105 > AviateurRex
 
oui, donc, si
p->sommet
est un pointeur sur SCellule, tu ne peut par le stocker dans une variable de type Element *

Sois rigoureux et remonte le fil des types jusqu'à arriver aux données qui t'intéressent.

Sinon, au temps pour moi, contrairement à ce que j'ai dit dans mon post précédent, il semble que l'implémentation pile.c ne mette pas psuiv à NULL pour la dernière Cellule (ce qui est quand même très usuel pour une liste chaînée, mais bon). Tu dois donc exclusivement te baser sur le nombre d'éléments pour savoir quand tu t'arrêtes, que tu peux obtenir de différentes façons.

Le module n'est pas forcément codé très rigoureusement, mais c'est un truc rapide "qui marche" :-)

Essaye déjà d'accéder aux données du sommet de cette façon, ensuite tente de construire ta boucle qui passe à psuiv tant que le nombre d'éléments te permet de te fier à l'adresse mémoire que tu trouveras dans le pointeur.
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Il y a quelque chose que je ne comprend pas.

Par exemple la ligne ou je définis l'élément actuel :

Element *actuel = p->sommet


Je ne peux pas écrire ça puisque actuel est de type Element et sommet de type SCellule. Mais c'est pourtant cette donnée qui m'intéresse non ?

Ecrire :

Element *actuel = p->sommet->info


Serait juste mais ne m'avancerai à rien puisque j'ai besoin que l'élément actuel soit le premier donc le sommet de la pile.

Même soucis pour passer à l'element suivant.

Je pourrai écrire :

actuel = p->sommet->info


Pourtant j'ai besoin de l'élément suivant mais celui ci est aussi de type SCellule.
0
AviateurRex
 
Je vois vraiment pas comment finir ce void x(. Je t'assure que j'ai passé la journée dessus mais rien. Je dois surement mal réfléchir et mal chercher mais la vraiment je vois pas comment faire.

Je suis obligé de définir mon element "actuel" en le pointant vers Element pour en définir sa structure. Comment accéder à une information, sommet ou psuiv qui sont par nature différente de la nature d'actuel. Et pour la boucle un
 if(estsommet==0)
serait correct non ?
0
[Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention   1 105
 
Fais les choses progressivement.

La liste d'éléments est, en fait une liste chaînée de Cellules, qui chacune contiennent "info" qui est de type Element et un pointeur vers la Cellule suivante dans la pile.

Vérifie que ton code compile sans erreurs ni avertissements, et que ce que tu écris a un sens avec les types réels de ton module que tu dois manipuler, pas en fonction de ce que tu penses que cela devrait être, mais en fonction de la réalité des types dont tu disposes.

/* RAPPEL DES TYPES PERTINENTS
struct SCellule {
     Element info;
     struct SCellule *psuiv;
};

typedef struct SCellule *Cellule;

struct SPile{
      struct SCellule *sommet;
      int nbElements;
};

typedef struct SPile *Pile; Pile
*/

void pileAfficher(Pile p){
    /* comme struct SPile * contient un membre nbElements, je le récupère
     * pour savoir combien d'éléments je dois afficher */
    int nbElements = p->nbElements;

    /* on traite d'abord des cas d'erreurs ou bien où on ne va rien faire */
    if (p==NULL) {
        exit(EXIT_FAILURE);
    }
    if (nbElements < 1) {
        printf("La pile est vide, rien à afficher\n");
        return;
    }

    /* arrivé ici, on a quelque chose à afficher */
    printf("Affichage des %d élément(s) de la pile :\n", nbElements);

    /* je récupère la cellule qui est au sommet, un nom court comme c sera
     * pratique pour la suite ... jusqu'ici rien de difficile, non ? */
    struct SCellule  * c = p->sommet;

    /* TODO: à partir de cette cellule (qui est un pointeur sur struct), 
     * accéder au membre info de la cellule, qui est une struct de type 
     * Element, et accéder à ses membres first_string, integer_value et 
     * pour les afficher second_string */
    printf("%s,0x%x,%s\n", cXXXXfirst_string, cXXXXinteger_value, cXXXXecond_string);
}
0
AviateurRex > [Dal] Messages postés 6205 Date d'inscription   Statut Contributeur Dernière intervention  
 
Okay je comprend mieux l'approche que je dois avoir. Mais la encore la logique m'échappe.
Si j'initialise c comme étant un pointeur sur une struct SCellule, comment recueillir par la suite des infos de type Element ?

écrire :
c=c->info 
est incorrect. J'ai du mal à voir comment organiser des pointeurs pour que 2 éléments qui à la base ont une structure différente puisse "communiquer". Partir de c pour arriver à info c'est bien ça le but non ?
0