/*!\file postfix.c * * \author SOUPLET Antoine * \version 1.0 * \date 09-01-2012 * * \brief Fichier contenant les fonctions de traitement de la transformation d'une chaine infixe en postfixe et du calcul de celle-ci * */ #include "functionAdd.h" #include "postfix.h" #include #include #include #include //Calcule une expression postfixe double calculPostfix(char* pc_postfix, double d_X, double d_Y) { stack** st_stack;//Une pile utilisée pour stocker des valeurs ou des opérateurs lors du calcul de l'expression postfixe double d_res;//Double correspondant à la valeur du résultat int i;//variable de boucle int i_operandNumber;//entier correspondant au numéro de l'opérande du char en cours de lecture, 0 si le char en cours de lecture n'est pas un opérande st_stack=stack_new();//initialise et alloue la mémoire nécéssaire à la pile for (i=0 ; i=1) {//si le caractère lu n'est pas un opérande, alors si c'est un opérateur réalise l'opération avec un ou deux opérandes présent dans la pile suivant l'opérateur if(isDualOperator(pc_postfix[i])==0) { d_res=calcSimpleOperator(pc_postfix[i], st_stack); } else { d_res=calcDualOperator(pc_postfix[i], st_stack); } } else { i= calcNumeralOperand(i,pc_postfix,st_stack);//si le caractère n'est ni un opérande classique, ni un opérateur, alors c'est un opérande numérique (chiffre), on le calcul et on l'ajoute à la pile } } freeStack(st_stack);//libère l'espace mémoire allouée pour la pile return (d_res);//retourne le resultat } //Réalise le traitement d'un opérand numérique int calcNumeralOperand(int i_cpt, char* pc_postfix, stack** st_stack) { uCharDouble ucd_value;//valeur à insérer dans la pile double d_coma;//réél permettant de gérer les nombres décimaux double d_dec;//réél permettant de gérer les nombres décimaux int i_deblock;//entier à 0 lorsque tant que le nombre n'est pas décimal d_coma=1.0; d_dec=10.0; i_deblock=0; ucd_value.d_value=0.0; for(;i_cpt=1) { i=processOperand(i,pc_infix,pc_postfix); } else if (pc_infix[i]=='(') { processParenthesisOpen(st_stack); } else if(pc_infix[i]==')') { processParenthesisClose(st_stack, pc_postfix); } else { i=processOperator(i,st_stack, pc_infix, pc_postfix); } } processEndOfStack(st_stack,pc_postfix); freeStack(st_stack);//libération de l'espace mémoire alloué à la pile return (pc_postfix);//retourne la chaine de caractère postfixe } //Ajoute à l'expression postfixe les derniers éléments contenus dans la pile void processEndOfStack(stack** st_stack, char* pc_postfix) { while(*st_stack!=NULL) {//tant que la pile est non vide, on copie le caractère présent en haut de la pile, et on le copie à la fin de l'expression postfixe sprintf(pc_postfix, "%s%c", pc_postfix, stack_peek(*st_stack).c_value); stack_pop(st_stack);//on dépile } } //Réalise le traitement des parenthèses ouvrantes lors de la transformation d'une chaine infixe en postfixe void processParenthesisOpen(stack** st_stack) { uCharDouble ucd_value;//valeur correspondant à la parenthèse ouvrante ucd_value.c_value='('; stack_push(st_stack,ucd_value);//on empile la parenthèse ouvrante dans la pile } //Réalise le traitement des parenthèses fermantes lors de la transformation d'une chaine infixe en postfixe void processParenthesisClose(stack** st_stack, char* pc_postfix) { while(stack_peek(*st_stack).c_value!='(') {//tant que le sommet de la pile n'est pas une parenthèse fermante, on concatène le sommet de la pile à l'expression postfixe sprintf(pc_postfix, "%s%c", pc_postfix, stack_peek(*st_stack).c_value); stack_pop(st_stack);//on dépile le caractère concaténé } stack_pop(st_stack);//on dépile la parenthèse ouvrante } //Réalise le traitement des opérateur lors de la transformation d'une expression infixe en postfixe int processOperator(int i_cpt,stack** st_stack, char* pc_infix, char* pc_postfix) { uCharDouble ucd_value;//valeur à empiler while(((*st_stack)!=NULL && st_stack!=NULL) && (priority(stack_peek(*st_stack).c_value) >= priority(pc_infix[i_cpt]))) {//tant que la pile est non vide et que l'opérateur en sommet de la pile est prioritaire sur celui en cours de lecture, on concatène le sommet de la pile à l'expression postfixe sprintf(pc_postfix, "%s%c", pc_postfix, stack_peek(*st_stack).c_value); stack_pop(st_stack);//on dépile } if(pc_infix[i_cpt]=='a') { ucd_value.c_value=pc_infix[i_cpt+4]; } else if(pc_infix[i_cpt]=='h') { ucd_value.c_value=pc_infix[i_cpt+2]-32; } else { ucd_value.c_value=pc_infix[i_cpt]; } stack_push(st_stack,ucd_value); i_cpt=i_cpt+isOperator(pc_infix[i_cpt])-1;//calcule la position du prochain caractère en lecture en fonction du nombre de caractères associés à l'opérateur actuellement lu return (i_cpt);//retourne la position du prochain caractère en lecture en fonction du nombre de caractères associés à l'opérateur actuellement lu } //Réalise le traitement d'un opérande lors de la transformation d'une expression infixe en postfixe int processOperand(int i_cpt, char* pc_infix, char* pc_postfix) { sprintf(pc_postfix, "%s%c", pc_postfix, pc_infix[i_cpt]);//on concatène à l'expression postfixe le caractère en cours de lecture while((i_cpt+1)=1 ) {//tant que nous ne somme pas à la fin de l'expression infixe et que le prochain caractère lu représent un opérande, on concatène celui ci à l'expression postfixe sprintf(pc_postfix,"%s%c", pc_postfix, pc_infix[i_cpt+1]); if(isOperand(pc_infix[i_cpt+1])) { i_cpt++; } } if(pc_infix[i_cpt]=='P') { i_cpt++; } if(isOperand(pc_infix[i_cpt])==1) { sprintf(pc_postfix,"%s%c",pc_postfix,'|'); } return (i_cpt);//retourne la position du prochain caractère en lecture en fonction du nombre de tours de boucle effectué } //Retourne la priorité de l'opérateur passé en paramètre int priority(char c_operator) { if(c_operator=='*' || c_operator=='%' || c_operator=='/') { return (2); } else if(c_operator=='+' || c_operator=='-') { return (1); } else if(c_operator=='^') { return (3); } else if(c_operator=='a' || c_operator =='e' || c_operator=='t' || c_operator=='c' || c_operator=='s' || c_operator=='S' || c_operator=='h' ) { return (4); } else return (-1); } //Teste si le caractère passé en paramètre correspond à un opérateur. Retourne le nombre de caractère de cet opérateur si celui-ci en est un, 0 sinon. int isOperator(char c_op) { switch (c_op) { case '+': return (1); break; case '-': return (1); break; case '*': return (1); break; case '/': return (1); break; case '%': return (1); break; case '^': return (1); break; case 'c': return (3); break; case 's': return (3); break; case 't': return (3); break; case 'e': return (3); break; case 'a': return (6); break; case 'h': return (4); break; default: return(isOperator2(c_op)); } } int isOperator2(char c_op) { switch (c_op) { case 'I': return (4); break; case 'T': return (4); break; case 'O': return (4); break; case 'S': return (4); break; default: return (0);//si le caractère lu ne correspond à aucun cas du switch, alors celui-ci ne représente pas un caractère, on retourne donc 0 } } //Teste si le caractère passé en paramètre représente un opérande, retourne 2 ou 1 suivant le type d'opérande, ou 0 si ce n'est pas un opérande int isOperand(char c_op) { if(c_op=='P'||c_op=='Y'||c_op=='R'||c_op=='X') { return (2); } if(isOperator(c_op)==0 && c_op != '|' && c_op != '(' && c_op != ')') { return (1); } else return (0); } //Teste si l'opérateur est un opérateur binaire, retourne 1 si oui, 0 sinon int isDualOperator(char c_operator) { if(isOperator(c_operator)>1) {//si le nombre de caractère de l'opérateur est supérieur à 1, ce n'est pas un opérateur binaire, en effet, tous les opérateurs binaires sont représentés par un unique caractère (+,-,*,/,%,^) return (0); } else return (1); } //Teste si l'operande est un operand particulier (pas un chiffre), si c'est le cas, renvoie un entier différent suivant l'operand particulier, ou renvoi 0 si ce n'est pas le cas. int isParticularOperand(char c_op) { switch (c_op) { case 'X': return (1); break; case 'Y': return (2); break; case 'R': return (3); break; case 'P': return (4); break; default: return (0); }; } //Réalise le traitement d'un opérande lors du calcul de l'expression postfixe void calcOperand(int i_operandNumber, stack** st_stack, double d_X, double d_Y) { uCharDouble ucd_value;//valeur représentant l'opérande à empiler switch (i_operandNumber) { case 1: ucd_value.d_value=d_X; stack_push(st_stack,ucd_value);//empile l'opérande break; case 2: ucd_value.d_value=d_Y; stack_push(st_stack,ucd_value);//empile l'opérande break; case 3: ucd_value.d_value=sqrt(d_Y*d_Y + d_X*d_X); stack_push(st_stack, ucd_value);//empile l'opérande break; case 4: ucd_value.d_value=M_PI; stack_push(st_stack, ucd_value);//empile l'opérande break; default: { }//de part les fonctions de verification précèdent le calcul d'une expression postfixe, la variable c_operator ne peut être différente de celles définies dans les cas du switch } } //Ajoute un 0 devant les signes + et - afin que l'analyseur syntaxique puisse les interpréter comme des opérateurs + et - void filterNegative(char* pc_infix) { int i;//variable de boucle char* pc_newInfix;//nouvelle expression infixe pc_newInfix=myMalloc(300*sizeof(char));//allocation mémoire nécéssaire à la nouvelle expression infixe *pc_newInfix='\0';//efface tous les caractères de la nouvelle expression infixe for (i = 0; i < strlen(pc_infix); i++) { if(pc_infix[i]=='-' || pc_infix[i] =='+') { if(i==0 || previousIsOperator(pc_infix, i)) {//si l'opérateur peut être confondu avec le signe, alors on concatène le caractère '0' à la nouvelle chaine infixe sprintf(pc_newInfix, "%s%c", pc_newInfix, '0'); } } sprintf(pc_newInfix, "%s%c", pc_newInfix, pc_infix[i]);//on concatène le caractère en cours de lecture à la nouvelle expression infixe } strcpy(pc_infix,pc_newInfix);//on copie la nouvelle expression infixe dans l'ancienne free(pc_newInfix);//on libère l'espace mémoire allouée à la nouvelle expression } //teste si le caractère précédent est un opérateur, retourne 1 si c'est le cas, 0 sinon int previousIsOperator(char* pc_infix, int i_cpt) { if(i_cpt>0 && isOperator(pc_infix[i_cpt-1])) { return (1); } else if (i_cpt>1&&pc_infix[i_cpt-1]=='('&&(isOperator(pc_infix[i_cpt-2])|| pc_infix[i_cpt-2]=='n'||pc_infix[i_cpt-2]=='s')) { return (1); } else if(i_cpt>2&&pc_infix[i_cpt-1]=='('&&pc_infix[i_cpt-2]=='('&&(isOperator(pc_infix[i_cpt-3])||pc_infix[i_cpt-3]=='n'||pc_infix[i_cpt-3]=='s')) { return (1); } else if(i_cpt>3&&pc_infix[i_cpt-1]=='('&&pc_infix[i_cpt-2]=='('&&pc_infix[i_cpt-3]=='('&&(isOperator(pc_infix[i_cpt-4])||pc_infix[i_cpt-4]=='n'||pc_infix[i_cpt-4]=='s')) { return (1); } else return (0); }