/* Librerias Plucas(c)1992-98 Freeware (Libre Distribucion) Mega version Hiper Ultra Re Super Hipra Copra Dupra Depra ARREGLADA Esta version trata de ser 99% Free bugs pero aun asi puede tener broncas =NO INTENTE HACER ESTA FUNCION EN CASA= Puede llevarse unos 5 dias, y pelearse en la maquina como yo, asi que mejor chequen bien esta funcion y a¤adan lo que quieran, se explica paso a paso lo que se realiza. Como usar: Copielo en "\BC\INCLUDE" y agrege en sus programas la siguiente linea "#include " ahora tiene que crear una estructura e inicializar con lo siguiente: struct eva a; // <- inicializa la esctructura . . . strcpy(a.cad, "(x^2)/3"); //<-Aqui va la cadena a evaluar (Maximo 80) scanf("%f",a.x); //<-Obtiene el valor de x a.step=0; //<-Debe de ser inicializada en 0 (siempre) a.error=0; //<-Debe de ser inicializada en 0 (SIEMPRE) resultado=evalua(&a); //<-Llamada de la funcion. if (a.error!=0) //Esta variable sera diferente de 0 si ahi error printf("%s",error(&a); //Si ahi error muestra el tipo de error. Gracias a todos nuestros Beta Testers. Bugs: angel-c@altavista.net */ #ifndef _EVALUAR_H #define _EVALUAR_H #include #include #include #include #include #include #include #include "iograph.h" #define MAXSTACK 15 #define MAXSTRING 80 #define MAXOP 15 #define MAXCADENA 85 #define TRUE -1 #define FALSE 0 // Funciones de Pila de Cadenas (100% Free Bugs!) void mete(struct stack *, char *); char *saca(struct stack *); char *ve(struct stack *); int vacio(struct stack *); void vacia(struct stack *); // Funciones 'extras' de luxe ;) void errorfatal(char *); void center(char *, int); // Funciones de evaluacion de una cadena. float evalua(struct eva *); int precedencia(char *cadena); char *ftoc(float valor); char *error(struct eva *); int esdigito(char c); void addop(struct stack *ps, char *infija, char *posfija, struct eva *a); struct stack { char items[MAXSTACK][MAXOP]; int top; }; struct eva { char cad[MAXSTRING]; float x; int step; int error; }; // --------------------------------- // Funcion para Evaluar una Cadena // --------------------------------- // v0.913 float evalua(struct eva *a) { struct stack pila; char *ps, pos[MAXSTRING]={""}, postmp[MAXSTRING]={""}; char *psn, posn[MAXOP]={""}; float res, op1, op2; char waitnum=TRUE, waitop=FALSE, waitclose=FALSE; int xok, xn, o; vacia(&pila); //Convierte de Infija (a->cad) a Postfija (pos) //^^^^^^^^^ ^^ ^^^^^^ ^^^^^^^^ ^ ^^^^^^^^ ^^^^^ do { ps=&a->cad[a->step]; //Actualiza el apuntador //Si Termina cadena/parentesis, vacia la pila alrevez ;) if (*ps==')' || *ps=='\0') { if (waitclose==FALSE) { a->error=3; // 3 - Falta cerrar Parentesis. return 1; } while (vacio(&pila)==FALSE) { strcat(pos,saca(&pila)); strcat(pos,","); } ps++; break; } // Si el caracter/cadena no es niguno conocido, manda error... else if (precedencia(ps)==-1) { a->error=1; // 1 - Caracter irreconocible. return 1; } //en caso de ser digito, x, "." o negativo (-) lo mete a la cadena else if (esdigito(*ps) || *ps=='-') { if ((waitop==TRUE) && (*ps=='x')) addop(&pila, "*", pos, a); if ((waitop==TRUE) && (*ps=='-')) addop(&pila, "+", pos, a); else if (waitnum==FALSE) { a->error=4; // 4 - No se esperaba operando return 1; } o=0; do { strncat(pos,ps,1); ps=&a->cad[++(a->step)]; if (o>MAXOP) { a->error=7; // 7 - Operando demasiado largo! return 1; } o++; } while (esdigito(*ps)); strcat(pos,","); a->step--; waitnum=TRUE; waitop=TRUE; waitclose=TRUE; } //Si abre parentesis entonces //se llama a la misma funcion: "recursividad" else if (*ps=='(') { if (waitop==TRUE) addop(&pila, "*", pos, a); a->step++; strcat(pos,ftoc(evalua(a))); strcat(pos,","); waitnum=TRUE; waitop=TRUE; waitclose=TRUE; } //Si no es nada de lo anterior entonces de "ley" que es algun //operador valido... y lo clava... else { addop(&pila, ps, pos,a); waitnum=TRUE; waitop=FALSE; waitclose=FALSE; } a->step++; } while(1); strncpy(postmp,pos,strlen(pos)-1); strcpy(pos,postmp); //Posfija ==> Valor ps=pos; vacia(&pila); while (*ps!='\0') { if (*ps==',') ps++; //Saca los digitos y los mete a la pila... if (esdigito(*ps) || *ps=='-') { psn=posn; xok=0; xn=0; while (!(*ps==',' || *ps=='\0')) { if (*ps=='x') xok=1; if (*ps=='-') xn=1; *psn=*ps; psn++; ps++; } *psn='\0'; if (xok==1) { res=atof(posn); if (res==0) if (xn==1) res=-1; else res=1; res=res*a->x; mete(&pila,ftoc(res)); } else mete(&pila,posn); } else { //Si no es operando entonces es operador y saca los valores... if (vacio(&pila)==TRUE) { a->error=6; // 6- Faltan operandos return 6; } op2=atof(saca(&pila)); if (precedencia(ps)!=7) { if (vacio(&pila)==TRUE) { a->error=6; // 6- Faltan operandos return 6; } op1=atof(saca(&pila)); } switch(*ps) { case '+': res=op1+op2; break; case '-': res=op2-op1; break; case '/': if (op2==0) { a->error=2; return 2; } else res=op1/op2; break; case '*': res=op1*op2; break; case '^': if (op1<0 && op2<1) { a->error=8; //Error matematico return 1; } res=pow(op1,op2); break; default: o=0; if (strncmp(ps,"log",3)==0) { if (op2<=0) { a->error=8; return 1; } res=log10(op2); o=2; } else if (strncmp(ps,"e",1)==0) { if (op2>20 || op2<-20) { a->error=8; return 1; } res=exp(op2); } else if (strncmp(ps,"sen",3)==0) { res=sin(op2); o=2; } else if (strncmp(ps,"cos",3)==0) { res=cos(op2); o=2; } else if (strncmp(ps,"tan",3)==0) { if (fmod(op2,360)==90 || fmod(op2,360)==270) { a->error=8; return 1; } res=tan(op2); o=2; } else if (strncmp(ps,"ln",2)==0) { if (op2<=0) { a->error=8; return 1; } res=log(op2); o=2; } for(;o>0;o--) ps++; } psn=posn; psn = ftoc(res); mete(&pila, psn); } ps++; } res=atof(saca(&pila)); return res; } void addop(struct stack *ps, char *infija, char *posfija, struct eva *a) { char temp[4]={""}; int inc=0,i; if (strncmp(infija,"log",3)==0 || strncmp(infija,"sen",3)==0 || strncmp(infija,"cos",3)==0 || strncmp(infija,"tan",3)==0) { strncpy(temp,infija,3); inc=2; } else if (strncmp(infija,"ln",2)==0) { strncpy(temp,infija,2); inc=1; } else strncpy(temp, infija, 1); if (vacio(ps)) mete(ps,temp); else { if (precedencia(ve(ps)) > precedencia(infija)) { strcat(posfija,saca(ps)); mete(ps,temp); strcat(posfija,","); } else mete(ps,temp); } for(i=0;istep++; } // v1.2 mejorada char *ftoc(float valor) { char cad[MAXOP]={""}, *pc; int dec, sign, ndig = 5; char tem[MAXOP]={""}, *tp; int i; pc=cad; tp=tem; pc=fcvt(valor, ndig, &dec, &sign); if (sign==1) *tp++='-'; if (dec<0) { *tp++='.'; for (i=dec;i<0;i++) *tp++='0'; } else { for (i=0;istep++; if (a->step>strlen(a->cad)) a->step=strlen(a->cad); switch(a->error) { case 1: sprintf(buffer, "Caracter Irreconocible o no valido:'%c' en el paso %d", a->cad[a->step-1], a->step); break; case 2: sprintf (buffer,"Division por cero en el paso %d", a->step); break; case 3: sprintf (buffer, "Falta(n) cerrar parentesis"); break; case 4: sprintf (buffer, "No se esperaba un operando en el paso %d.", a->step); break; case 6: sprintf (buffer, "Faltan operandos, o esta mal escrita la ecuacion"); break; case 7: sprintf (buffer, "Operando demasiado largo en el paso %d.",a->step); break; case 8: sprintf (buffer, "Error Matematico"); break; default: sprintf (buffer, "Error #%d desconocido en el paso %d", a->error, a->step); } return buffer; } //------ Checa si la cadena es una funcion y no tiene errores... int prueba(char *cadena) { struct eva e; char par[MAXCADENA]; strcpy(e.cad,cadena); e.step=0; e.error=0; e.x=1; evalua(&e); if (e.error!=0) { strcpy(par, error(&e)); mensaje(par,ERROR); return FALSE; } else return TRUE; } // Regresa los parametros (cadenas separadas x espacios) // v1.2 - Optimizado/Arreglado - 26Jun98 char *parametro (char *cad, int num) { int i,j=0; char param[40]={""}, *s; s=cad; for (i=0;itop==MAXSTACK-1) errorfatal("Desborde de la pila en la funcion 'mete'."); else strcpy(ps->items[++(ps->top)],x); } char *saca(struct stack *ps) { if (vacio(ps)) errorfatal("Subdesborde de la pila en la funcion 'saca'."); return (ps->items[ps->top--]); } int vacio(struct stack *ps) { if (ps->top==-1) return TRUE; else return FALSE; } char *ve(struct stack *ps) { if (vacio(ps)) errorfatal("Subdesborde de la pila en la funcion 've'."); return (ps->items[ps->top]); } void vacia(struct stack *ps) { ps->top=MAXSTACK-1; do { strcpy(ps->items[ps->top--],""); } while (ps->top!=-1); } void errorfatal(char *msg) { closegraph(); textbackground(BLUE); textcolor(WHITE); clrscr(); textbackground(LIGHTGRAY); textcolor(BLACK); center(" Error Critico ",6); textbackground(BLUE); textcolor(WHITE); center("El programa a intentado transgredir el sistema intentando",8); center("ejecutar una operacion invalida en algun modulo en especifico",9); center(msg,10); center("+ Presione cualquier tecla para intentar continuar. ",12); center("+ Presione Ctrl+Alt+Del para reiniciar la computadora,",13); center(" perder  toda la informacion que tenia. ",14); center("Presione cualquier tecla para continuar",18); getch(); textbackground(BLACK); textcolor(LIGHTGRAY); clrscr(); } // ------------------------------- // Funciones Adicionales "De Luxe" // ------------------------------- void center(char *msg, int ren) { gotoxy(40-(strlen(msg)/2),ren); cprintf ("%s", msg); } #endif