Partage
  • Partager sur Facebook
  • Partager sur Twitter

verification d'une chaine a l'aide d'une pile

verification d'une chaine de caractaires a l'aide d'une pile

    1 mai 2023 à 15:00:37

    salut tout le monde  je veux creer un programme en c qui permet de verifier  les parentaises d'une chaine de caractaires  en utilisant une pile : 
    #include <stdio.h>
    #include <stdlib.h>
    #include<cstring> 
    #ifndef PILE_
    #define PILE_
    
    typedef struct Place Place;
    struct Place{
    Place *prec;
    int val;
    };
    typedef struct Place *Pile;
    
    #endif /*PILE_*/
    
    Pile empiler(Pile mapile,int donnee)
    {
    Pile      temp=(Pile)malloc(sizeof(Pile));
         temp->val=donnee;
         temp->prec=mapile;//on fait pointer le precedent de ce nouveau sur le sommet
         mapile=temp;//et le sommet deveint le nv element;
         return mapile;
    } 
    
    int sommet (Pile p ) {
    	if (p==NULL) {	
    	return NULL ;
    	}
    
    	return p->val;
    	
    }
    bool verification(char s){
    	Pile p =NULL;
    	for (int i=0;i<strlen(s);i++){
    	
    	   if ((s[i] == '(' || s[i] == '[' || s[i] == '{')){
    	   
    	empiler(p,i);
    	} else if (s[i] == ')' || s[i] == ']' || s[i] == '}') {
                if ( (sommet (p) == '(' && s[i] != ')') || (sommet (p) == '[' && s[i] != ']') || (sommet (p) == '{' && s[i] != '}')) {
                    return false;
                }
                
    }
    return true;
    }}
    int main(int argc, char **argv) {
    	 FILE* fichier = NULL;
    	 char c;
         fichier = fopen("test.txt", "r+");
         while((c=fgetc(fichier))!=EOF){
            printf("%c",c);  
        if (verification(c)==false) {  
    	printf("la chaine n 'est pas valide ");
    	}
    
       
        printf("la chaine est  valide ") ;
            
        }
           
       return 0 ; 
    }
    j'ai une erreur le code ne fait pas la verification il lit seulement la phrase qui est  dans le fichier

    -
    Edité par AbcAbc6 1 mai 2023 à 15:14:19

    • Partager sur Facebook
    • Partager sur Twitter
      1 mai 2023 à 15:16:23

      Bonjour, je viens de modifier votre titre en fonction de votre sous titre, en effet "pile" n'est pas suffisamment descriptif comme titre. 

      La modération.

      Liens conseillés

      • Partager sur Facebook
      • Partager sur Twitter
        1 mai 2023 à 15:18:22

        D'abord, tu utilises cstring au lieu de string.h
        Ensuite:
             temp->prec=mapile;//on fait pointer le precedent de ce nouveau sur le sommet
        On doit faire pointer le nouveau vers le premier de la pile et le sommet vers le nouveau.
        • Partager sur Facebook
        • Partager sur Twitter

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

          1 mai 2023 à 17:17:40

          j'ai corrige les erreurs mais le code m'affiche dans tout les cas que la chiane est valide meme si elle n'est pas valide
          #include <stdio.h>
          #include <stdlib.h>
          #include<string.h>
          #ifndef PILE_
          #define PILE_
          
          typedef struct Place Place;
          struct Place{
          Place *prec;
          int val;
          };
          typedef struct Place *Pile;
          
          #endif /*PILE_*/
          
          Pile empiler(Pile mapile,int donnee)
          {
          Pile temp=(Pile)malloc(sizeof(Pile));
               temp->val=donnee;
               temp->prec=mapile;//on fait pointer le precedent de ce nouveau sur le sommet
               mapile=temp;//et le sommet deveint le nv element;
               return mapile;
          } 
          
          int sommet (Pile p ) {
          	if (p==NULL) {	
          	return NULL ;
          	}
          
          	return p->val;
          	
          }
          bool verification(char *s){
          
          	Pile p =NULL;
          	for (int i=0;i<strlen(s);i++){
          	
          	   if ((s[i] == '(' || s[i] == '[' || s[i] == '{')){
          	   
          	empiler(p,i);
          	} else if (s[i] == ')' || s[i] == ']' || s[i] == '}') {
                      if ( (sommet (p) == '(' && s[i] != ')') || (sommet (p) == '[' && s[i] != ']') || (sommet (p) == '{' && s[i] != '}')) {
                          return false;
                      }
                      
          }
          return true;
          }}
          int main(int argc, char **argv) {
          	 FILE* fichier = NULL;
          	 char c;
               fichier = fopen("test.txt", "r+");
               while((c=fgetc(fichier))!=EOF){
                  printf("%c",c);  
          }
              if (verification(&c)==true)
          	
          	printf("la chaine est  valide ");
          	else 
          
             
              printf("la chaine n'est pas valide " );
                  
             
                 
             return 0 ; 
          }
          
             
              

          -
          Edité par FatihaChaibi 1 mai 2023 à 17:18:45

          • Partager sur Facebook
          • Partager sur Twitter
            1 mai 2023 à 17:44:27

            Tu appelles ta fonction verification une seule fois après avoir lu tout ton fichier.
            Dans verification, tu es censé avoir une chaîne en entrée. Affiches cette chaîne.

            Tu empiles les '(', '{', '[' mais tu dois dépiler quand tu rencontres leur équivalent complémentaire.

            Comment valides-tu la chaîne  ({[]}  ?)

            -
            Edité par PierrotLeFou 1 mai 2023 à 17:54:50

            • Partager sur Facebook
            • Partager sur Twitter

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

              1 mai 2023 à 18:04:19

              Attention à ton indentation !

              Dans ta boucle for de la fonction verification, tu fais un return direct (ligne 47) ce qui signifie que ta boucle ne va par reboucler.

              • Partager sur Facebook
              • Partager sur Twitter
              ...
                1 mai 2023 à 18:18:03

                Autre détail, quand tu dépiles, tu peux te retrouver avec une pile vide si ta chaîne n'est pas jumelée correctement.
                On peut tester si la chaîne est vide et retourner '\0' dans ce cas.

                Et la pile doit être vide à la fin de la validation.

                @rouIoude: je pense que c'est correct de quitter si le jumelage ne peut pas être fait.

                -

                Le test devrait plutôt être:
                        if(s[i] == ')' && sommet(p) != '(' || s[i] == '}' && sommet(p) != '{' || s[i] == ']' && sommet(p) != '[')
                            return false;
                        else
                            je dépile

                -
                Edité par PierrotLeFou 1 mai 2023 à 19:06:57

                • Partager sur Facebook
                • Partager sur Twitter

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

                  1 mai 2023 à 19:17:32

                  PierrotLeFou a écrit:

                  @rouIoude: je pense que c'est correct de quitter si le jumelage ne peut pas être fait.

                  Un return sans condition dans une boucle ça sort direct, la boucle ne sert à rien. C'est pour cela que je lui ai dit de faire attention à son indentation. Car une fois indenté on le voit de suite.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  ...
                    1 mai 2023 à 19:29:13

                    On trouve:
                        empiler(p,i);
                    je pensais qu'on devait empiler le caractère et non l'indice ...

                    -
                    edit:
                    C'est plus compliqué à gérer si on n'a pas de descripteur de liste. J'ai utilisé un pointeur vers un pointeur.
                    Je n'avais pas le goût de le faire avec un fichier. J'ai modifié le main pour lire directement à la console.
                    Ce n'est pas une bonne pratique que de faire un typedef avec un pointeur. C'est moins facile à suivre.
                    Comment as-tu pu compiler sans l'entête stdbool.h ?
                    Le ifndef, etc, n'étaient pas nécessaires ici.

                    Si on s'emmerde avec les pointeurs, on peut utiliser un tableau pour la pile.
                    Par exemple, si on connait la longueur maximum du tableau:
                    typedef struct Pile Pile;
                    struct Pile {
                        size_t empile;   // Nombre d'éléments dans la pile.
                        char pile[LONGUEUR];
                    };
                    Pour empiler:
                        p->pile[p->empile++] = c;
                    pour dépiler (tester si la pile n'est pas vide):
                        char c = p->pile[--p->empile];
                    le sommet est à:
                       char c = p->pile[p->empile-1];

                    -
                    #include <stdio.h>
                    #include <stdlib.h>
                    #include<string.h>
                    #include <stdbool.h>
                     
                    #ifndef PILE_
                    #define PILE_
                    typedef struct Pile Pile;
                    struct Pile {
                        Pile *prec;
                        char value;
                    };
                    #endif /*PILE_*/
                     
                    void empiler(Pile **p, char donnee) {
                        Pile *temp = malloc(sizeof(Pile));
                        temp->value = donnee;
                        temp->prec = *p;
                        *p = temp;
                    }
                     
                    char sommet (Pile **p ) {
                        if(*p == NULL)   return '\0';
                        return (*p)->value;
                    }
                     
                    char depiler(Pile **p) {
                        if(*p == NULL)   return '\0';
                        char c = (*p)->value;
                        *p = (*p)->prec;
                        return c;
                    }
                     
                    bool verification(char *s) {
                        Pile *q = NULL;
                        Pile **p = &q;
                        for(int i = 0; s[i]; i++) {
                            if(s[i] == '(' || s[i] == '[' || s[i] == '{')
                                empiler(p,s[i]);
                            else if(s[i] == ')' || s[i] == ']' || s[i] == '}')
                                if(s[i] == ')' && sommet(p) != '(' || s[i] == ']' && sommet(p) != '[' || s[i] == '}' && sommet(p) != '{')
                                    return false;
                                else
                                    depiler(p);   // Pas besoin de sauver la valeur retournée.
                        }
                        if(*p == NULL)
                            return true;
                        else
                            return false;
                    }
                     
                    int main(void) {
                        char c[1000];
                        puts("> ");
                        fgets(c, 1000, stdin);
                        if(verification(c))
                            printf("la chaine est  valide ");
                        else
                            printf("la chaine n'est pas valide " );
                        return 0 ;
                    }

                    -
                    Edité par PierrotLeFou 2 mai 2023 à 4:48:31

                    • Partager sur Facebook
                    • Partager sur Twitter

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

                      3 mai 2023 à 11:09:55

                      Y aurait pas des fuites mémoires ?

                      Bon, je rabâche, mais la représentation d'une pile par une liste chaînée, c'est emmerdant à programmer, et c'est épouvantable inefficace (ratio  charge utile/taille des machins alloués), surtout pour empiler un octet.

                      Une solution avec une pile de capacité fixe (dans un tableau)

                      #define CAPACITE_PILE 100
                      
                      enum Etat verif_parentheses(const char chaine[])
                      {
                          char pile[CAPACITE_PILE];
                          int taille = 0;
                      
                          for (const char *p = chaine; *p != '\0'; p++) {
                              if (est_ouvrant(*p)) {
                                  pile[taille++] = *p;
                              } else if (est_fermant(*p)) {
                                  if (taille == 0) {
                                      return P_EN_TROP;
                                  }
                                  char ouvrante = pile[--taille];
                                  if (! correspond(ouvrante, *p)) {
                                      return P_INCORRECTE;
                                  }
                              } else {
                                  // les autres caractères sont ignorés
                              }
                          }
                          if (taille != 0) {
                              return P_MANQUANTE;
                          }
                          return P_OK;
                      }

                      Avec

                      enum Etat {
                              P_OK,
                      	P_EN_TROP,
                      	P_MANQUANTE,
                      	P_INCORRECTE
                      };

                      et les tests unitaires

                      void tests() {
                          printf("# Tests\n");
                          assert(verif_parentheses("()")             == P_OK);
                          assert(verif_parentheses("[]")             == P_OK);
                          assert(verif_parentheses("[([]){{()[]}}]") == P_OK);
                          assert(verif_parentheses("({}")            == P_MANQUANTE);
                          assert(verif_parentheses("({}]")           == P_INCORRECTE);
                          assert(verif_parentheses("()]")            == P_EN_TROP);
                          printf("ok\n");
                      }
                      

                      (je laisse le reste en exercice, je fais pas vos devoirs)

                      Remarquez que 100 octets, ça représente à peu près 3 étages d'une pile avec liste chaînée - une pile de 3 octets - :-)

                      Avec une pile extensible allouée dynamiquement, il y a juste quelques lignes de plus :

                      #define CAPACITE_INITIALE 16
                      
                      enum Etat verif_parentheses(const char chaine[])
                      {
                          char *pile = malloc(CAPACITE_INITIALE_PILE);
                          int capacite_pile = CAPACITE_INITIALE_PILE;
                          int taille = 0;
                      
                          for (const char *p = chaine; *p != '\0'; p++) {
                              if (est_ouvrant(*p)) {
                                  if (taille == capacite_pile) {
                                      // c'est plein, on double la capacité
                                      capacite_pile *= 2;
                                      pile = realloc(pile, capacite_pile);
                                  }
                                  pile[taille++] = *p;
                              } else if (est_fermant(*p)) {
                                  if (taille == 0) {
                                      free(pile);
                                      return P_EN_TROP;
                                  }
                                  char ouvrante = pile[--taille];
                                  if (! correspond(ouvrante, *p)) {
                                      free(pile);
                                      return P_INCORRECTE;
                                  }
                              } else {
                                  // les autres caractères sont ignorés
                              }
                          }
                          if (taille != 0) {
                              return P_MANQUANTE;
                          }
                          free(pile);
                          return P_OK;
                      }





                      -
                      Edité par michelbillaud 3 mai 2023 à 14:00:09

                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 mai 2023 à 12:09:54

                        PierrotLeFou a écrit:

                        Comment as-tu pu compiler sans l'entête stdbool.h ?

                        Probablement son fichier est un .cpp

                        • Partager sur Facebook
                        • Partager sur Twitter
                        ...

                        verification d'une chaine a l'aide d'une pile

                        × 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