begin process at 2012 05 28 10:58:51
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C

 > 

Divers

 > 

Débutant(e)

 > 

aide pour calcul de formule


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

aide pour calcul de formule

vendredi 15 mai 2009 à 09:57:52 | aide pour calcul de formule

snakers07

bonjour, j'ai crée un programme permettant de calculer une formule utilisant les opérateurs +,-,*,/
avec un controle sur les parenthése:
par exemple :
((5-4)-(3*4))=-11

le probleme est que je suis obligé à chaque fois de parenthéser complétement mon expression.

je voudrais avoir ceci:

avant: ((5-4)-(3*4))=-11
après: (5-4)-(3*4)=-11  j'aimerai que en écrivant cette formule sous cette forme, qu'il me donne le même résulat

voici mon code:

#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable : 4996)
/*-----
 Pile Num
   -----*/
struct StructNumLifo{
 double pile[50];
 int sommet;
};

typedef struct StructNumLifo NumLifo;

void initialiserNum(NumLifo* lifo){
 //initialisation des valeurs de la pile
 int i=0;
 for(i=0;i<50;i++){
  lifo->pile[i]=0; //lifo->pile[i] est equivalent à *lifo.pile[i]
 }
 //initialisation du sommet
 lifo->sommet=-1;
}
int empilerNum(NumLifo* lifo, double value){
 //test de position du sommet
 if(lifo->sommet < 49){
  lifo->sommet++; //incrémentation du sommet
  lifo->pile[lifo->sommet] = value; //enregistrement de la valeur
  return 1;
 }else{
  return 0;
 }
}
double depilerNum(NumLifo* lifo){
 double value=0; //test de position du sommet
 if(lifo->sommet > -1){
  value = lifo->pile[lifo->sommet]; //récupération temporaire de la valeur
  lifo->pile[lifo->sommet] = 0; //mise à zéro de la valeur courante
  lifo->sommet--; //décrémentation du sommet
  return value;
 }else{
  return 0;
 }
}
void afficherNum(NumLifo* lifo){
 int i=0;
 printf("\n");
 for(i=0;i<=lifo->sommet;i++){
  printf("%d\t%f\n",i,lifo->pile[i]);
 }
 printf("Sommet %d\n",lifo->sommet);
}


/*-----
 Pile Char
   -----*/
struct StructChar{
 char pile[50];
 int sommet;
};

typedef struct StructChar CharLifo;

void initialiserChar(CharLifo* lifo){
 //initialisation des valeurs de la pile
 int i=0;
 for(i=0;i<50;i++){
  lifo->pile[i]='\0';
 }
 //initialisation du sommet
 lifo->sommet=-1;
}
int empilerChar(CharLifo* lifo, char value){
 //test de position du sommet
 if(lifo->sommet < 49){
  lifo->sommet++; //incrémentation du sommet
  lifo->pile[lifo->sommet] = value; //enregistrement de la valeur
  return 1;
 }else{
  return 0;
 }
}
char depilerChar(CharLifo* lifo){
 char value = '\0';
 //Test de position du sommet
 if(lifo->sommet > -1){
  value = lifo->pile[lifo->sommet]; //récupération temporaire de la valeur
  lifo->pile[lifo->sommet] = 0; //mise à zéro de la valeur courante
  lifo->sommet--; //décrémentation du sommet
  return value;
 }else{
  return 0;
 }
}
void afficherChar(CharLifo* lifo){
 int i=0;
 printf("\n");
 for(i=0;i<=lifo->sommet;i++){
  printf("%d\t%c\n",i,lifo->pile[i]);
 }
 printf("Flag %d\n",lifo->sommet);
}
/*-----
 Calcul
   -----*/
double calcul(char* expression){
 //Déclarations
 char* c=NULL; //pointeur qui parcourt le tableau (plus facile que naviguer dans celui-ci)
 int OpenParenthese = 0; //définit si la derniére occurance été une parenthése ouvrante : seul cas possbile pour un nombre négatif
 NumLifo numbers; //pile des nombres
 CharLifo operations; //pile des opérations
 initialiserNum(&numbers);
 initialiserChar(&operations);

 //Parcours de l'expression
 for(c=expression; c<expression+strlen(expression); c++){

  
  
  //Détection d'un nombre
  if( (*c>='0' && *c<='9') || (*c=='-' && OpenParenthese==1) ){
   char* end; //poiteur de fin de chaine du nombre
   double number;
   
   //récupération du nombre
   number=strtod(c,&end);  /*fonction qui convertie une portion de chaine en double (ex: 2 chiffres a la suite en nombre)
         chercher sur internet pour faciliter les calculs parce que sinon trop incomprehensible*/
   empilerNum(&numbers,number);

   //mise à jours des variables
   c=end-1;
   OpenParenthese=0;
   continue;
  }

  //Détection d'une opération
  if(*c == '+' || *c == '-' || *c == '*' || *c == '/'){
   empilerChar(&operations,*c);
   OpenParenthese=0;
   continue;
  }

  //Déclenchement d'un calcul
  if(*c == ')'){
   double nb1 = depilerNum(&numbers);
   double nb2 = depilerNum(&numbers);
   char operation = depilerChar(&operations);

   switch (operation){
    case '*' :
     empilerNum(&numbers,nb2*nb1);
     printf("%f * %f = %f\n",nb2,nb1,nb2*nb1);
     break;
    case '+' :
     empilerNum(&numbers,nb2+nb1);
     printf("%f + %f = %f\n",nb2,nb1,nb2+nb1);
     break;
    case '-' :
     empilerNum(&numbers,nb2-nb1);
     printf("%f - %f = %f\n",nb2,nb1,nb2-nb1);
     break;
    case '/' :
     empilerNum(&numbers,nb2/nb1);
     printf("%f / %f = %f\n",nb2,nb1,nb2/nb1);
     break;
   } 
   OpenParenthese=0;
  }
 }
 return depilerNum(&numbers);
}
/*-----
 Interface
   -----*/


void startCalcul(char* expression){
 printf("%s = %f\n\n",expression,calcul(expression));
}

 
 

/*-----
  Main
   -----*/
void main(){
 
    char expression[50];

 system("cls");
 printf("Saisir une expression completement parenthesee :\n");
 scanf("%s", &expression);
 startCalcul(expression);
}

merci d'avance de votre aide...

vendredi 15 mai 2009 à 11:23:30 | Re : aide pour calcul de formule

CptPingu

Administrateur CodeS-SourceS
Il y a plein d'autre petites erreurs:

Saisir une expression completement parenthesee :
(((1+1)))
1.000000 + 1.000000 = 2.000000
(((1+1))) = 0.000000

Saisir une expression completement parenthesee :
(1--1)   
1.000000 - 1.000000 = 0.000000
(1--1) = 0.000000

Saisir une expression completement parenthesee :
(1 + 1)
(1 = 1.000000

Saisir une expression completement parenthesee :
toto          
toto = 0.000000

Saisir une expression completement parenthesee :
x1+1)
1.000000 + 1.000000 = 2.000000
x1+1) = 2.000000

Quelques remarques sur le code:
 for(c=expression; c<expression+strlen(expression); c++)
Et pourquoi pas tout simplement ceci, qui est plus rapide d'ailleurs:
 for (char* c = expression; c && *c; c++)
Ou si tu préfères, en plus explicite:
 for (char* c = expression; c != NULL && *c != '\0'; c++)

Voici toutefois une version qui fonctionne, que j'ai un peu "proprisé" en passant (et corriger 2-3 petits trucs). Ton problème venait du fait que tu ne te servait jamais de "OpenParenthese". A noter que c'est plus de la bidouille sale fait à la va-vite, qu'autre chose. Renseigne toi sur une vraie méthode pour répondre à ce besoin: les AST.

Les modifs:

//#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* #pragma warning(disable : 4996) */

struct StructNumLifo
{
  double pile[50];
  int sommet;
};

typedef struct StructNumLifo NumLifo;

void initialiserNum(NumLifo* lifo)
{
  for (int i = 0; i < 50; i++)
    lifo->pile[i] = 0;

  lifo->sommet=-1;
}

int empilerNum(NumLifo* lifo, double value)
{
  if (lifo->sommet < 49)
  {
    lifo->sommet++;
    lifo->pile[lifo->sommet] = value;
    return 1;
  }
  return 0;
}

double depilerNum(NumLifo* lifo)
{
  if (lifo->sommet > -1)
  {
    double value = lifo->pile[lifo->sommet];
    lifo->pile[lifo->sommet] = 0;
    lifo->sommet--;
    return value;
  }
  return 0;
}

void afficherNum(NumLifo* lifo)
{
  printf("\n");
  for (int i = 0; i <= lifo->sommet; i++)
    printf("%d\t%f\n",i,lifo->pile[i]);
  printf("Sommet %d\n",lifo->sommet);
}


/*-----
  Pile Char
  -----*/
struct StructChar
{
  char pile[50];
  int sommet;
};

typedef struct StructChar CharLifo;

void initialiserChar(CharLifo* lifo)
{
  int i = 0;

  for (i = 0; i < 50; i++)
    lifo->pile[i] = '\0';
  lifo->sommet = -1;
}

int empilerChar(CharLifo* lifo, char value)
{
  if (lifo->sommet < 49)
  {
    lifo->sommet++;
    lifo->pile[lifo->sommet] = value;
    return 1;
  }
  return 0;
}

char depilerChar(CharLifo* lifo)
{
  if (lifo->sommet > -1)
  {
    char value = lifo->pile[lifo->sommet];
    lifo->pile[lifo->sommet] = 0;
    lifo->sommet--;
    return value;
  }
  return 0;
}

void afficherChar(CharLifo* lifo)
{
  printf("\n");
  for (int i = 0; i <= lifo->sommet; i++)
    printf("%d\t%c\n", i, lifo->pile[i]);
  printf("Flag %d\n", lifo->sommet);
}

/*-----
  Calcul
  -----*/
double calcul(char* expression)
{
  int OpenParenthese = 1;
  NumLifo numbers;
  CharLifo operations;

  initialiserNum(&numbers);
  initialiserChar(&operations);

  for (char* c = expression; c && *c != '\0'; c++)
  {
    if (*c == '(')
    {
      OpenParenthese = 1;
      continue;
    }

    //Detection d'un nombre
    if ((*c >= '0' && *c <= '9') || (*c == '-' && OpenParenthese))
    {
      char* end = NULL;
      double number = strtod(c, &end);
      empilerNum(&numbers, number);
      c = end - 1;
      continue;
    }

    if (*c == '+' || *c == '-' || *c == '*' || *c == '/')
    {
      empilerChar(&operations, *c);
      continue;
    }

    if (OpenParenthese && *c == ')')
    {
      double nb1 = depilerNum(&numbers);
      double nb2 = depilerNum(&numbers);
      char operation = depilerChar(&operations);

      switch (operation)
      {
    case '*':
      empilerNum(&numbers, nb2 * nb1);
      printf("%f * %f = %f\n", nb2, nb1, nb2 * nb1);
      break;
    case '+':
      empilerNum(&numbers, nb2 + nb1);
      printf("%f + %f = %f\n", nb2, nb1, nb2 + nb1);
      break;
    case '-':
      empilerNum(&numbers, nb2 - nb1);
      printf("%f - %f = %f\n", nb2, nb1, nb2 - nb1);
      break;
    case '/':
      empilerNum(&numbers, nb2 / nb1);
      // Testez la division par 0 !!!
      printf("%f / %f = %f\n", nb2, nb1, nb2 / nb1);
      break;
      }
      OpenParenthese = 0;
    }
  }

  // Solution sale...
  if (OpenParenthese)
  {
    double nb1 = depilerNum(&numbers);
    double nb2 = depilerNum(&numbers);
    char operation = depilerChar(&operations);

    switch (operation)
    {
      case '*':
    empilerNum(&numbers, nb2 * nb1);
    printf("%f * %f = %f\n", nb2, nb1, nb2 * nb1);
    break;
      case '+':
    empilerNum(&numbers, nb2 + nb1);
    printf("%f + %f = %f\n", nb2, nb1, nb2 + nb1);
    break;
      case '-':
    empilerNum(&numbers, nb2 - nb1);
    printf("%f - %f = %f\n", nb2, nb1, nb2 - nb1);
    break;
      case '/':
    empilerNum(&numbers, nb2 / nb1);
    // Testez la division par 0 !!!
    printf("%f / %f = %f\n", nb2, nb1, nb2 / nb1);
    break;
    }
  }
  return depilerNum(&numbers);
}


/*-----
  Interface
  -----*/
void startCalcul(char* expression)
{
  printf("%s = %f\n\n", expression, calcul(expression));
}

/*-----
  Main
  -----*/
int main(void)
{
  char expression[50];

  /* system("cls"); */
  printf("Saisir une expression completement parenthesee :\n");
  scanf("%s", expression);
  startCalcul(expression);

  return 0;
}

mardi 26 mai 2009 à 17:46:06 | Re : aide pour calcul de formule

snakers07

merci beaucoup de ton aide, j'ai modifié ton code et il marche bien, j'ai du rajouter quelques conditions, mais rien de bien méchant.
maintenant j'aimerai te poser une dernière question, à savoir les priorité
c'est à dire si j'effectue le calcul suivant:

(4-1*9)+(9*5)= 44
en bref de gérer la priorité sur la multiplication vis a vis de la soustraction

merci d'avance de ton aide




mardi 26 mai 2009 à 19:40:46 | Re : aide pour calcul de formule

CptPingu

Administrateur CodeS-SourceS
Gérer ce type de priorité est bien plus hardu. Il faudrait revoir beaucoup de chose dans ton code pour gérer cela correctement (comme je te l'ai dit, la version que je te propose est sale).
Plutôt que de bidouiller ton code, je te conseil de jeter un coup d'oeil à ce qu'on appelle les AST, ainsi qu'à la grammaire en notation BNF.
Mieux vaut utiliser une méthode propre, maintenable et élégante, plutôt que de t'empêtrer sur une successions de bidouille.


Cette discussion est classée dans : pile, nb1, lifo, nb2, sommet


Répondre à ce message

Sujets en rapport avec ce message

Je n'arrive pas a créer une variable aléatoire !!! [ par daikyo ] Bonjour a tous, j'ai dévelopé un petit jeu ou l'on doit trouver un nombre entre 1 er 100 mais ce nombre (ici la variable Nb1) a trouver je souhaiterai template- au secours [ par toddy_101 ] bonjour tout le monde, j'ai un probleme au niveau des templates, ca bloke au niveau du linkage!! voici la declaration de la classe , et des methodes: Calculatrice en C [ par tototiti ] Bonjour, j' ai un projet à rendre qui consiste à faire un calculatrice en C en utilisant une pile.Il faut entrer toute l' expression d'un coup et comp VOID [ par langenoir7712 ] AIDER MOI SVP JE VEUX LE MEME PROGRAMME MAIS MTN AVEC UN VOID POUR NE PAS AVOIR TOUT CE BLABLA REPONDEZ MOI SVPMERCI D'AVANCE#include #include #includ Erreur de définition de pointeurs [ par HellYodan ] Bonjour,j'ai codé ce code mais à chaque fois que je compile il me met qu'il y a une erreur de définition de pointeurs. Mais je ne vois pas comment rég Nombres amis [ par Darksnakes ] Bonjour tout le monde,Voila je débute en C, et pour un tp j'ai besoin de faire un programme qui m'affiche la liste des nombres amis inférieur ou égale Construction d'une pile avec une structure [ par sheep70400 ] Bonjour à tous,Voilà j'ai un petit problème avec une pile, je dois utiliser une structure :#define TAILLE 10    //taille de notre piletypedef struct{  Variable de type string en paramètre d'une fonction [ par sheep70400 ] Bonsoir à tous et à toutes,Je voudrais parcourir une chaine de caractère dans une variable de type string dans une fonction qui utilise une pile.int m Infos sur la pile et le tas [ par clempar55 ] Voila je vois souvent sur le forum des phrases telles que "tel objet a été créé sur la pile/le tas", "tel paramètre a été dépilé". J'ai enfin décidé d pile [ par faresfrance ] salut j'ai utilise le langage Cpouver vous m'aider pour pouvoir manipuler une pile pile systeme empiler et depiler des fonction et des variable merci


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 2,948 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales