Evaluer une expression mathématique

Soyez le premier à donner votre avis sur cette source.

Snippet vu 10 829 fois - Téléchargée 18 fois

Contenu du snippet

/* ce programme vérifie bien la saisie correcte de votre expression*/
/*idem, il prend en compte le signe de la puissane ^ , le signe de modulo %,*/
/* aisni que les opérations arithmétiques usuelles : addition +,soustraction -,multiplication* et division / */
/*une fonction spéciale est implémentée afin d'éviter la division sur zéro */
/*remarque importane : */
/*mon programme prend en compte, dans l'ordre de précédence, les signes suivants (dans l'ordre de priorité) :*/
/* ( ),[ ], { }, ^ (signe de la puissance), * , / , % , + et enfin l'opérateur - */
/*des fonctions spéciales sont implémentées afin de vérifier si tout opérateur possède ses opérandes*/
/*de même, j'ai implémenté des fonctions qui vérifient si toutes les opérandes possèdent leurs opérateurs mathématiques logiques*/
/*si jamais une parenthèse ouvrante ou fermante de type ( ), [ ], ou { } est omise, mon programme vous signalera l'erreur en question */
/*vous devez saisir votre expression naturellement et mon programme se chargera de sa convertion en une expression postfixée */
/*équivalente, juste après, le programme procède à son évaluation algébrique*/
/*de même, mon programme vous donnera la notation (la forme) postfixée de votre expression où N est une opérande quelconque*/
/*de votre expression suivis des opérateurs logiques que vous avez saisis*/
/*les opérandes N saisis seront affichés dans l'ordre dans une ligne à part lors de l'exécution du programme*/
/*le compilateur que j'ai utilisé est le Borland C++ version 4.5 SOUS DOS */
/* exemple : 7+2(8+5) ici mon programme vous signalera une erreur car on doit mettre un opérateur logique entre 2 et ( */
/* exemple2 : 5+2^2 = 5+(2^2) =9 */
/*Compilateur: Borland C++ 4.52*/
/*Console DOS */
/*pour toute question concernant ce code, contacter moi sur : b.beguer@yahoo.com*/
/*www.begueradj.com*/

Source / Exemple :

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<dos.h>
#include<math.h>

typedef struct noeud
{
 char val;
 noeud *suivant;
} noeud;

typedef struct noeud1
{
 long int val;
 noeud1 *suivant;
} noeud1;

#define pile noeud *

#define pile1 noeud1 *

/*dans cette partie, je vais déclarer quelques opérations nécessaires pour manipuler notre pile*/

/*fonction pour ajouter un élément*/
pile1 empiler1 (pile1 pil, long int v);

/*fonction pour supprimer le sommet de la pile*/
pile1 depiler1  (pile1 pil, long int &v);

/*fonction servant à retourner le sommet de la pile uniquement*/
void top1 (pile1 pil, long int &v);

/*fonction pour vider la pile */
pile1 mettreazero1 (pile1 pil);

/*fonction pour vérifier si la pile est vide */
int vide1 (pile1 pil);

/*fonction pour ajouter un élément à la pile */
pile empiler (pile pil, char v);

/*fonction pour supprimer le sommet de la pile*/
pile depiler  (pile pil, char &v);

/*fonction pour retourner le sommet de la pile uniquement*/
void top (pile pil, char &v);

/*fonction pour vider la pile*/
pile mettreazero (pile pil);

/*fonction pour vérifier si la pile est vide */
int vide (pile pil);

/* cette fonction servira à la saisie d'un caractère par caractère et l'empilement en meme temps


*  cette fonction force l'utilisateur à n'accepter que les caractères corrects*/

pile saisie(pile pil)
{
 textcolor(15);
 cprintf("Veuillez saisir votre expression (puis appuyez sur ENTREE) :  ");
 gotoxy(1,3);
 char ch;

 do
 {
  ch=getch();
  if (ch>=48 && ch<=57 || ch>=40 && ch<=43 || ch==37 || ch==45 || ch==47 || ch==91 || ch==93 || ch==94 || ch==123 || ch==125)
  {
   putch(ch);
   pil=empiler(pil,ch);
  }
  else if (ch !=8 && ch !=13)
  {
   sound(400);
   delay(250);
   nosound();
  }
  /*ici, on doit tenir compte de la saisie de l'espace blanc*/
  if (ch==8)
  { putch(ch);
   putch(' ');
   putch(ch);
   if (!vide(pil))
    pil=depiler(pil,ch);

  }
 }
 /* lorsque l'utilisateur tape sur ENTREE, je dois sortir de la boucle*/
 while (ch!=13);
 return(pil);
}

/* renverser la pile de caractères*/
pile renverser_pil(pile pil)
{
 char c;
 pile temp=NULL;
 while (!vide(pil))
 {
  pil=depiler(pil,c);
  temp=empiler(temp,c);
 }
 return(temp);
}

/* renverser  la pile de type long*/
pile1 renverser_pil1(pile1 pil)
{
 long int c;
 pile1 temp=NULL;
 while (!vide1(pil))
 {
  pil=depiler1(pil,c);
  temp=empiler1(temp,c);
 }
 return(temp);
}

/*fonction pour extraire les nombres saisis et les stoker comme étant des entiers long dans la pile long*/
pile remplirno(pile1 *no,pile pil)
{
 int i,j;
 long int x;
 char ch;

 pile temp=NULL;
 pile tmp_no=NULL;

 do{
  i=0;
  /* incrémenter i tant que le caractère saisi est un chiffre et l'empiler juste après*/
  while (!vide((pil=depiler(pil,ch))) && ch>=48 && ch<=57)
  {
   i++;
   tmp_no=empiler(tmp_no,ch);
  }

  if (i)
  {
   temp=empiler(temp,'N');
   if (!(ch>=48 && ch<=57))
    temp=empiler(temp,ch);
   else
   {
    i++;
    tmp_no=empiler(tmp_no,ch);
   }
   /* convertir le chiffre saisi en long int (note: '0'=48) */
   tmp_no=depiler(tmp_no,ch);
   x=ch-48;
   for (j=1;j<i;j++)
   {
    tmp_no=depiler(tmp_no,ch);
    x=x+(ch-48)*pow(10,j);
   }


*no=empiler1(*no,x);
  }
  else
  {
   if(ch>=48 && ch<=57)
   { *no=empiler1(*no,ch-48);
    temp=empiler(temp,'N');
   }
   else
    temp=empiler(temp,ch);
  }
 } while (!vide(pil));
 temp=renverser_pil(temp);


*no =renverser_pil1(*no);
 return(temp);
}

/* copier la pile de type long */
pile1 copier_pil1(pile1 *src)
{
 pile1 dest=NULL;
 pile1 temp=NULL;

 long int ch;

 while (!vide1(*src))
 {


*src=depiler1(*src,ch);
  temp=empiler1(temp,ch);
  dest=empiler1(dest,ch);
 }
 temp=renverser_pil1(temp);
 dest=renverser_pil1(dest);


*src=temp;
 return(dest);
}

/* copier la pile de caractères*/
pile copier_pil(pile *src)
{
 pile dest=NULL;
 pile temp=NULL;

 char ch;

 while (!vide(*src))
 {


*src=depiler(*src,ch);
  temp=empiler(temp,ch);
  dest=empiler(dest,ch);
 }
 temp=renverser_pil(temp);
 dest=renverser_pil(dest);


*src=temp;
 return(dest);
}

/* afficher le message d'erreur*/
void erreur(char code)
{
 sound(400);
 delay(400);
 nosound();

 gotoxy(35,12);
 textcolor(4+128);
 cprintf("Erreur syntaxique dans votre expression.");
 gotoxy(35,14);
 switch (code){
 case 0:
    cprintf(") manquant");
    break;
 case 1:
    cprintf("] manquant");
    break;
 case 2:
    cprintf("} manquant");
    break;

 case 3:
    gotoxy(28,14);
    cprintf("Operateur sans operande.");
    break;
 case 4:
    gotoxy(28,14);
    cprintf("Operande sans operateur.");
    break;
 }

}
/* vérifier si la saisie est correcte sinon afficher le message d'erreur avec la fonction erreur précédente


*  il y a un compteur tel que i-- si opérande,i++  si opérateur et i==1 si il n'y a pas d'erreurs de saisie

*  pour les parenthèses, il y a une pile telle que lorsque l'on renctonre celle qui ferment on doit dépiler et on doit

* doit retrouver les parenthèses ouvrantes sinon erreur, et pour les parenthèses de fin la pile doit etre vide sinon erreur*/

int verifiersicorrect(pile *pil)
{
 int compteur=0;
 char ch,br;
 pile parenthese=NULL;
 pile temp=NULL;
 temp=copier_pil(pil);
 while (!vide(temp))
 {
  br=0;
  temp=depiler(temp,ch);
  if (ch=='N')
   compteur++;
  else if (ch==42 || ch==43 || ch==45 || ch==47 || ch==37 || ch==94)
   compteur--;
  else if (ch==41)
  { if (parenthese)
   {
    parenthese=depiler(parenthese,br);
   }
   if (br!=40)
   {     erreur(0); return(0);}
  }
  else if (ch==93)
  { if (parenthese)
   {
    parenthese=depiler(parenthese,br);
   }
   if (br!=91)
   {     erreur(1); return(0) ;}
  }
  else if (ch==125)
  { if (parenthese)
   {
    parenthese=depiler(parenthese,br);
   }
   if (br!=123)
   {     erreur(2);  return(0);}
  }
  else
   parenthese=empiler(parenthese,ch);

 }
 if (!vide(parenthese))
 { erreur(0);
  gotoxy(35,14);
  parenthese=depiler(parenthese,ch);
  if (ch!=40)
   cprintf("%c manquant",ch+2);
  else
   cprintf("%c manquant",ch+1);
  return(0);
 }

 if (compteur>1)
 {
  erreur(3);
  return(0);
 }
 else if (compteur<1)
 { erreur(4); return(0);}
 else
  return(1);
}
/* retourner la précédence 1 si ch1 est premier sinon la précédence 0 */
int prioritaire(char ch1,char ch2)
{
 if (ch1==40 && ch2!=40)
  return(0);
 else if (ch1=='^')
  return(1);
 else if ((ch1=='*' || ch1=='/' || ch1=='%') && ch2!='^')
  return(1);
 else if ((ch1=='+' || ch1=='-') && (ch2=='-' || ch2=='+'))
  return(1);
 else if ((ch1=='*' || ch1=='/' || ch2=='%') && (ch2=='/' || ch2=='*' || ch2=='%'))
  return(1);
 else
  return(0);
}

/*fonction pour convertir l'expression saisie en expression postfixée*/

pile postfixe(pile pil)
{
  pile temp=NULL;
  pile oprnd=NULL;
  char ch,ch2;
  while (!vide(pil))
  {
   pil=depiler(pil,ch);
   ch2=0;
   if (ch=='N')
  temp=empiler(temp,ch);
   else if (ch==42 || ch==43 || ch==45 || ch==47 || ch==37 || ch==94)
   {
  if (!vide(oprnd))
  { top(oprnd,ch2);
   while (prioritaire(ch2,ch) && !vide(oprnd))
   {
    oprnd=depiler(oprnd,ch2);
    temp=empiler(temp,ch2);
    if (!vide(oprnd))
     top(oprnd,ch2);
   }
  }
  oprnd=empiler(oprnd,ch);
   }
   else if (ch==41 || ch==93 || ch ==125)
   {
  do{
   if (!vide(oprnd))
    oprnd=depiler(oprnd,ch2);
   if (ch2!=40)
    temp=empiler(temp,ch2);
  }
  while (ch2!=40);
   }
   else
  oprnd=empiler(oprnd,40);

  }

  while (!vide(oprnd))
  {
  oprnd=depiler(oprnd,ch);
  temp=empiler(temp,ch);
  }
  temp=renverser_pil(temp);
  return(temp);
}

/* fonctions mathématiques pour : + - * / % et ^ */
long int ajouter(long int x,long int y)
{
 return(x+y);
}

long int dif(long int x,long int y)
{
 return(x-y);
}

long int mul(long int x,long int y)
{
 return(x*y);
}

long int div(long int x,long int y)
{

 if (y!=0)
  return(x/y);
}

long int mod(long int x,long int y)
{
 return(x%y);
}

/* évaluation  de notr eexpression postfixée après convertion */
void evaluation(pile *pil,pile1 *no)
{
 pile1 nos=NULL;
 long int x,y,z;
 char ch;
 while(!vide(*pil))
 {


*pil=depiler(*pil,ch);
  if (ch=='N')
  {


*no=depiler1(*no,x);
   nos=empiler1(nos,x);
  }
  else
  {
   nos=depiler1(nos,y);
   nos=depiler1(nos,x);

   switch (ch){
   case '+':
    z=ajouter(x,y);
    break;
   case '-':
    z=dif(x,y);
    break;
   case '*':
    z=mul(x,y);
    break;

   case '/':
    if (y==0)
    {
      textcolor(4+128);
      gotoxy(12,35);
      cprintf("Division par zero !");
      sound(500);
      delay(400);
      nosound();
      return;
    }
    z=div(x,y);
    break;
   case '^':
    z=pow(x,y);
    break;

   case '%':
    z=mod(x,y);
    break;
   }
   nos=empiler1(nos,z);
  }
 }
 gotoxy(10,23);
 textcolor(2);
 nos=depiler1(nos,z);
 cprintf("Resultat = %li",z);

}
/**********************************************************************************************/
/**********************************************************************************************/
/*                                début de notre programme principal                                                        */
/**********************************************************************************************/
/**********************************************************************************************/
int main(void)
{
 textmode(3);
 _setcursortype(_NOCURSOR);

 clrscr();
 textcolor(15);
 gotoxy(5,2);
 cprintf("Evaluation des expressions arithmetiques.");
 gotoxy(10,4);
 cprintf("www.begueradj.com");

 textcolor(2);
 gotoxy(1,10);
 cprintf("Prise en compte de : (^ puissance) (% modulo) et (* / - +) avec precedence ^ puis * / % puis + -");
 gotoxy(1,25);
 textcolor(129);
 cprintf("Appuyez sur n'importe quelle touche pour continuer ...");
 getch();

 pile input=NULL;
 pile1 num=NULL;

 pile tmp_in=NULL;
 pile1 tmp_no=NULL;

 do{
  clrscr();

  input=saisie(input);
  if (input)
  { input=renverser_pil(input);

   input=remplirno(&num,input);
   if (verifiersicorrect(&input))
   {

    input=postfixe(input);

    /* copier la pile pour que l'on puisse l'afficher*/
    tmp_in=copier_pil(&input);
    tmp_no=copier_pil1(&num);

    gotoxy(2,18);
    cprintf("Postfixe:");
    char c;
    gotoxy(5,19);
    while (!vide(tmp_in))
    {
     tmp_in=depiler(tmp_in,c);
     cprintf("%c",c);

    }
    gotoxy(2,20);
    cprintf("Valeurs:");
    long int cc;
    gotoxy(5,21);
    while (!vide1(tmp_no))
    {
     tmp_no=depiler1(tmp_no,cc);
     cprintf("%li ",cc);

    }

    evaluation(&input,&num);
   }
  }

  gotoxy(1,25);
  textcolor(129);
  cprintf("Appuyez sur n'importe quelle touche pour continuer, Esc pour terminer.");

  input=mettreazero(input);
  num=mettreazero1(num);
 }while ((getch())!=27);

 return(0);
}
/**********************************************************************************************/
/**********************************************************************************************/
/*                                           fin du programme principal                                                             */
/**********************************************************************************************/
/**********************************************************************************************/

/**********************************************************************************************/
/*implémentation des différentes fonctions et procédures déclarées là haut*/
/**********************************************************************************************/
pile empiler (pile pil, char v)
{
 pile temp;

 temp=(pile)malloc(sizeof(noeud));
 if (temp !=NULL)
 { temp->val=v;

  temp->suivant=pil;
 }
 else
 {
  printf("nDebordement.");
  exit(1);
 }
 return(temp);

}

pile depiler (pile pil, char &v)
{
 pile temp;

 if (pil==NULL)
 {
  printf("nPile vide.");
  exit(1);
 }
 else
 {
  v=pil->val;

  temp=pil;

  pil=pil->suivant;

  free(temp);

 }
 return(pil);
}

void top (pile pil, char &v)
{
 if (pil==NULL)
 {
  printf("nPile vide.");
  exit(1);
 }
 else
  v=pil->val;

}

pile mettreazero (pile pil)
{

 pile temp;

 while (pil != NULL)
 {
  temp=pil;

  pil=pil->suivant;

  free(temp);
 }
 return(NULL);

}

int vide (pile pil)
{
 if (pil==NULL)
  return(1);
 else
  return(0);
}

pile1 empiler1 (pile1 pil, long int v)
{
 pile1 temp;

 temp=(pile1)malloc(sizeof(noeud1));
 if (temp !=NULL)
 { temp->val=v;

  temp->suivant=pil;
 }
 else
 {
  printf("nDebordement.");
  exit(1);
 }
 return(temp);

}

pile1 depiler1 (pile1 pil, long int &v)
{
 pile1 temp;

 if (pil==NULL)
 {
  printf("nPile vide.");
  exit(1);
 }
 else
 {
  v=pil->val;

  temp=pil;

  pil=pil->suivant;

  free(temp);

 }
 return(pil);
}

void top1 (pile1 pil, long int &v)
{
 if (pil==NULL)
 {
  printf("nPile vide.");
  exit(1);
 }
 else
  v=pil->val;

}

pile1 mettreazero1 (pile1 pil)
{

 pile1 temp;

 while (pil != NULL)
 {
  temp=pil;

  pil=pil->suivant;

  free(temp);
 }
 return(NULL);

}

int vide1 (pile1 pil)
{
 if (pil==NULL)
  return(1);
 else
  return(0);
}

A voir également

Ajouter un commentaire Commentaires
Messages postés
1
Date d'inscription
dimanche 26 novembre 2006
Statut
Membre
Dernière intervention
26 juin 2010

hello ! Ce programme m'intéresse énormément, c'est tout a fait ce que je souhaite étudier. Pourrais je savoir sur quelle méthode / théorie repose l'algorithme ... Et encore mieux, qqun a-t-il quelques références bibliographique (en anglais mm) afin de comprendre comment tout cela fonctionne :) merci
Messages postés
273
Date d'inscription
dimanche 4 octobre 2009
Statut
Membre
Dernière intervention
24 juin 2014
4
oui, c'était un programme demandé à réaliser 4 jours après la fin du chapitre des conversions et des notations différentes
Messages postés
147
Date d'inscription
lundi 16 août 2004
Statut
Membre
Dernière intervention
14 novembre 2009

Hi!
J'ai l'impression que la conversion en notation polonaise inverse complique et alourdit le code sans rien apporter de vraiment positif; si l'expression était entrée directement dans cette notation, je dis pas, mais là?, peut-être ce programme n'est-il après tout qu'un exercice pour démontrer la validité d'un algorithme de conversion?
Messages postés
273
Date d'inscription
dimanche 4 octobre 2009
Statut
Membre
Dernière intervention
24 juin 2014
4
Ah, j'ai déposé cette petite source ici car je reçois des emails des gens d'ici me demandant un soutien dans ce sens, donc au lieu de leur envoyer des fichiers attaché à chaque fois, je leur donne e lien directement .... (j'ai d'autres pseudo sur ce site)
Messages postés
273
Date d'inscription
dimanche 4 octobre 2009
Statut
Membre
Dernière intervention
24 juin 2014
4
Bonjour;

Oui, effectivement, une classe aurait été mieux utile.

Oui, j'aurais pu traiter les espaces blancs, les virgules, les racines, et des variables du genre: (a+b+25) ... oui, mais là, on sera à la limite d'un mini compilateur, or, lorsque j'ai fait ça, en étant dans ma première, j'ai juste répondu à ce que l'on m'a demandé de faire.

Pour le (-1+2) qui ne marche pas: j'ai eu la chance le jour du test: l'enseignant n'a pas remarqué ça et j'ai eu la deuxième note ;)

Pour l'interfaçage: oui, on peut me proposer mieux, mais ça restera subjectf.

L'idée de classe, par contre, est intelligente.

Begueradj ~~
Afficher les 12 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.