Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème avec les piles

fonction de type : int fonction(Stack stack_);

    31 août 2021 à 14:36:50

    Bonjour à tous, je sui débutant en c et je sui en train de créer un programme avec des structure de donner (des piles). 

    Voila mon code :


    J'ai d'abord créé ma structure de pile :

    typedef struct StackElement
    {
        int value;
        struct StackElement *next;
    }StackElement*Stack;

    Ensuite voila la fonction qui me permet de définir la valeur d'une pile vide : 

    Stack empty_stack(void)
    {
        return NULL;
    }

    Puis la fonction qui me permet de tester si la pile st vide (accompagner de la définition du type bool) :

    typedef enum
    {
        false,
        true
    }bool;
    bool is_stack_empty(Stack stack_)
    {
        if(stack_ == empty_stack()){
            return true;
        }

        return false;
    }
    Voila les fonction qui me permet d'ajouter ou de retirer des valeurs à ma pile :
    Stack push_stack(Stack stack_int pushed)
    {
        StackElement *element;

        element = malloc(sizeof(*element));

        if (element == NULL){
            fprintf(stderr, "Error whith dynamic allocation");
            exit(EXIT_FAILURE);
        }

        element->value = pushed;
        element->next = stack_;

        return element;

    }

    /*--------------------------------------------------------*/

    Stack pop_stack(Stack stack_)
    {
        StackElement *element;

        if (is_stack_empty(stack_)){
            return empty_stack();
        }
        element = stack_->next;
        free(stack_);

        return element;
    }

    Et maintenant voila les fonction qui pose problème (la première sert a donner la somme de toute les valeur de la pile, la seconde sert a donner le produit de toute les valeur de la pile) :

    int sum_of_stack_values(Stack stack_)
    {
        int sum = 0;

        if (is_stack_empty(stack_)){
            return sum;
        }

        do{
            sum = sum + stack_->value;
            stack_ = pop_stack(stack_);
        }
        while(!is_stack_empty(stack_));

        return sum;
    }

    /*--------------------------------------------------------*/

    int product_of_stack_values(Stack stack_)
    {
        int sum = 1;

        if (is_stack_empty(stack_)){
            return sum;
        }

        do{
            sum = sum * stack_->value;
            stack_ = pop_stack(stack_);
        }
        while(!is_stack_empty(stack_));

        return sum;
    }

    Finalement, voila le programme en lui même :

    int main(void)
    {
        Stack _ST_ = empty_stack();

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

        _ST_ = push_stack(_ST_, 10);
        _ST_ = push_stack(_ST_, 30);
        _ST_ = push_stack(_ST_, 21);
        _ST_ = push_stack(_ST_, 8);

        print_stack(_ST_);
        printf("\n");
        printf("s = %d\n"sum_of_stack_values(_ST_));
        printf("p = %d\n"product_of_stack_values(_ST_));

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

        _ST_ = clear_stack(_ST_);

        return 0;
    }

    Clear_stack est juste une répétition de pop_stack.

    Le problème est que lors de l'exécution du programme le premier printf("s = %d\n"sum_of_stack_values(_ST_)); fonctionne très bien mais a partir du deuxième (printf("p = %d\n"product_of_stack_values(_ST_));) le programme plante complètement. J'ai bien vérifier est j'ai trouver que c'est au niveau de la fonction pop_stack() que cela plante. Et plus précisément au niveau de la fonction free(stack_);

    (Pour trouver ça j'ai mis des printf("\n o \n"); entre chaque instruction.)

    Je comprend vraiment pas le problème est j'aimerai bien savoir ce qui ne vas pas avec mon code...

    En espérant avoir été assez claire...sinon n'hésitez pas a me demander de précision.

    • Partager sur Facebook
    • Partager sur Twitter
      31 août 2021 à 14:52:16

      Bonjour,

      en image c'est non seulement illisible mais aussi incopiable ni manipulable.

      Édita ton message en insérant ton code avec le bouton </> …

      • Partager sur Facebook
      • Partager sur Twitter
        31 août 2021 à 15:09:21

        Quand tu fais la somme, tu vides ta pile.
        Tu te retrouves donc avec une pile vide pour le produit.
        Je me trompe?
        Suis ton chaînage pour la somme et le produit sans faire de pop.
        • Partager sur Facebook
        • Partager sur Twitter

        Le Tout est souvent plus grand que la somme de ses parties.

          31 août 2021 à 16:15:25

          Zirconium40 a écrit:

          Et maintenant voila les fonction qui pose problème (la première sert a donner la somme de toute les valeur de la pile, la seconde sert a donner le produit de toute les valeur de la pile)...

          Edit : je n'avais pas compris son fonctionnement, car pour moi pop_stack retourne la valeur du sommet de la pile et le supprime de la pile..

          Donc pour ton problème quand tu fait l'addition tu vide ta pile. Et ensuite tu fait ta multiplication sur une pile vide. De plus quand tu enlève le dernier élément de ta pile avec pop_stack tu ne la déclares pas vide, ça part donc en vrille !

          PS : Utilises le bouton code </> du forum pour poster ton code ! (tu peux modifier ton post, lien modifier en haut à droite du post).

          -
          Edité par rouIoude 31 août 2021 à 17:49:47

          • Partager sur Facebook
          • Partager sur Twitter
          ...
            31 août 2021 à 17:41:39

            Ce n'est pas une bonne idée que de définir une structure avec pointeur (*stack). Tu risques de t'ajouter des problèemes.
            Pour le bool, il y a l'entête  stdbool.h
            Si tu veux faire des sommes et des produits, pourquoi ne pas utiliser des tableaux?
            On peut le faire avec des pop mais en construisant une autre pile qui sera à l'envers de la première (ce n'est sûrement pas ce que tu veux)
            Tu devras dépiler la seconde et empiler pour reconstruire la première.
            Si c'est uniquement pour un exercice, je n'ai pas de problème avec ça. Sinon, c'est hautement inefficace.

            Normalement, avec les structures chaînées, on a un descripteur de liste. Ici on n'en a pas. Encore heureux que ça marche (?)

            -
            Edité par PierrotLeFou 1 septembre 2021 à 2:08:40

            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              1 septembre 2021 à 16:06:50

              Merci de vos réponses. J'ai tester tout un tas de truc en rapport avec ce que vous avez dit et la solution de PierrotLeFou semble très bien marcher... J'ai remplacer la fonction :

              int sum_of_stack_values(Stack stack_)
              {
                  int sum = 0;
              
                  if (is_stack_empty(stack_)){
                      return sum;
                  }
              
                  do{
                      sum = sum + stack_->value;
                      stack_ = pop_stack(stack_);
                  }
                  while(!is_stack_empty(stack_));
              
                  return sum;
              }

              par la fonction :

              int sum_of_stack_values(Stack stack_)
              {
                  int sum = 0;
              
                  if (is_stack_empty(stack_)){
                      return sum;
                  }
              
                  while(!is_stack_empty(stack_)){
                      sum = sum + stack_->value;
                      stack_ = stack_->next;
                  }
              
                  return sum;
              }

              Et même chose pour la fonction product.

              Le problème est que j'ai peur que cette technique ne désalloue pas ma mémoire... 

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

              PierrotLeFou a écrit:

              Quand tu fais la somme, tu vides ta pile.
              Tu te retrouves donc avec une pile vide pour le produit.
              Je me trompe?


              J'ai tester d'afficher la pile avec la fonction trouver sur mon cours :

              void print_stack(Stack stack_)
              {
                  if (is_stack_empty(stack_)){
                      printf("Nothing to print, empty stack");
                  }
              
                  while(!is_stack_empty(stack_)){
                      printf("[%d]\n", stack_->value);
                      stack_ = stack_->next;
                  }
              }

              et j'ai aussi teste si la pile étais vide ou non...

              Etrangement, le programme disais que la pile n'était pas vide, mais lors de l'affichage la console renvoyait une infinité de valeurs aléatoire.

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

              PierrotLeFou a écrit:

              Ce n'est pas une bonne idée que de définir une structure avec pointeur (*stack). Tu risques de t'ajouter des problèmes.
              Pour le bool, il y a l'entête  stdbool.h
              Si tu veux faire des sommes et des produits, pourquoi ne pas utiliser des tableaux?
              On peut le faire avec des pop mais en construisant une autre pile qui sera à l'envers de la première (ce n'est sûrement pas ce que tu veux)
              Tu devras dépiler la seconde et empiler pour reconstruire la première.
              Si c'est uniquement pour un exercice, je n'ai pas de problème avec ça. Sinon, c'est hautement inefficace.

              Normalement, avec les structures chaînées, on a un descripteur de liste. Ici on n'en a pas. Encore heureux que ça marche (?)

              -
              Edité par PierrotLeFou il y a environ 14 heures

              J'ai essayais de refaire le programme sans pointeur dans la définition de la structure mais je n'y suis pas arriver, mes fonctions ne marchaient plus après leur modification...

              Quant à la bibliothèque <stdbool.h>  j'ai préféré créer mon propre booléen car cela m'aide à mieux comprendre comment fonctionne le langage c.

              Ensuite, par rapport a l'idée de retourner la pile je n'ai pas vraiment compris pourquoi. En tout cas j'avais déjà créé une fonction pour faire cela :

              Stack flip_stack(Stack stack_)
              {
                  StackElement *element;
                  element = empty_stack();
              
                  if (is_stack_empty(stack_)){
                      return empty_stack();
                  }
              
                  while(!is_stack_empty(stack_)){
                      element = push_stack(element, stack_->value);
                      stack_ = pop_stack(stack_);
                  }
              
                  return element;
              }
              Et exécutable de cette manière :
              _ST_ = flip_stack(_ST_);
              





              -
              Edité par Zirconium40 1 septembre 2021 à 16:47:27

              • Partager sur Facebook
              • Partager sur Twitter
                1 septembre 2021 à 17:56:22

                Dans tes fonctions, tu n'as pas besoin du if:
                    if (is_stack_empty(stack_)){
                        return sum;
                Ton while est suffisant
                > Le problème est que j'ai peur que cette technique ne désalloue pas ma mémoire
                Tu n'as pas une fonction clear_stack pour ça?
                Sans descripteur de liste que tu passes aux fonctions, c'est plus compliqué de s'y retrouver.
                J'ai pris la peine d'écrire ma propre version du problème et ça prend un pointeur sur pointeur pour sauver en tout temps la tête de pile.
                Normalement dans les problèmes de pile, on ne fait pas de parcours de la liste chaînée comme tu fais pour la somme et le produit.
                Je te donne mon code non coloré (je ne peux pas avec ma synthèse vocale)
                (tu peux retrouver l'indentation avec un copier-coller)
                Il empile les lettres de 'a' à 'z' et les dépile pour les empiler dans une autre pile et les dépile ensuite.
                Ça me donne une suite en ordre croissant.
                -
                #include <stdio.h>
                #include <stdlib.h>
                #include <stdbool.h>
                #include <errno.h>
                typedef char type;
                typedef struct Stack Stack;
                struct Stack {
                    type value;
                    Stack *next;
                };
                void *getArea(char *name, int size) {
                    void *area = malloc(size);
                    if(area) return area;
                    perror(name);
                    fprintf(stderr, "Required: %d\n", size);
                    exit(1);
                }
                Stack *emptyStack() {
                    return NULL;
                }
                bool isEmptyStack(Stack *stack) {
                    return stack == emptyStack();
                }
                type popStack(Stack **stack) {
                    if(isEmptyStack(*stack)) {
                        fprintf(stderr, "Error: empty stack\n");
                        exit(1);
                    }
                    Stack *head = *stack;
                    *stack = (*stack)->next;
                    type value = head->value;
                    free(head);
                    return value;
                }
                void pushStack(Stack **stack, type value) {
                    Stack *element = getArea("pushStack", sizeof(Stack));
                    element->value = value;
                    element->next = *stack;
                    *stack = element;
                }
                int main(void) {
                    Stack *pile = emptyStack();
                    for(type c='a'; c <= 'z'; c++) pushStack(&pile, c);
                    printf("Stack filled\n");
                    Stack *save = emptyStack();
                    while(!isEmptyStack(pile)) {
                        pushStack(&save, popStack(&pile));
                    }
                    while(!isEmptyStack(save)) {
                        printf("%c ", popStack(&save));
                    }
                    printf("\n");
                    return 0;
                }

                • Partager sur Facebook
                • Partager sur Twitter

                Le Tout est souvent plus grand que la somme de ses parties.

                Problème avec les piles

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown