Распознавание формулы со сложными математическими функциями в строке - C (СИ)
Формулировка задачи:
Задание курсовика - распознать формулу функции введенную с клавиатуры и построить ее график (прикручу графику позже, сам код уже написан мной для лабы, да и мелочи буду вылизывать в конце), нашел превосходный способ распознавания, допилил и модифицировал его под себя, так что остался только один не решенный вопрос о том, как можно реализовать распознавание матем. функций, на подобии sin, cos, log и других, на мой взгляд основная сложность заключается в том что бы распознать то что находиться у этих функций в скобках, не представляю как это можно реализовать, да и к тому же надо будет учитывать одз, хотя возможно есть и другие подводные камни о которых я и не ведаю (пока), хотелось бы услышать практических советов или примерчика какого нибудь, заранее благодарю)
До этого начинал с работать с польской записью, но этот метод, в плане вычисления показался мне несколько проще - проще реализация вычисления "сложных" выражений содержащих в перемешку разные по приоритету операции.
Пишу на чистом Си, в BorlandC 3.1 Сам код, избавленный от моих попыток научить программу понимать мат. функции:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <ctype.h> #include <conio.h> int next(); void skip(int t); double expr(); double numpar(); double factor(); double term(); double x=5; int i=0; char s[50]; int Op; double tokval; int main() { clrscr(); gets(s); //for(;x<10;x+=1) //{ next(); printf("\n%.9g\n", expr()); // i=0; // Op=0; // tokval=0; //} if(!getch()) getch(); clrscr(); return 0; } int next() { int c,count=0; char cbuf[50]; for (;;) { c=s[i++]; if(strchr("+-*/^()\n",c)!=NULL&&i!=1) if(c=='*'&&s[i]=='*') { i=i+1; return Op='^'; } else return Op=c; if(c=='s'&&s[i]=='i'&&s[i+1]=='n') { i=i+2; return Op='s'; } if(isspace(c)) continue; if(isdigit(c)||c=='.'||c=='x'||c=='-') { if(c=='x') { tokval=x; return Op='n'; } for(;((c>='0'&&c<='9')||c=='.'||c=='-');) { cbuf[count++]=c; cbuf[count]='\0'; c=s[i++]; } i-=1; tokval=atof(cbuf); return Op='n'; } printf("Bad character: %c\n",c); if(!getch()) getch(); } } void skip(int t) { if(Op!=t) { printf("You take a error, try agan"); if(!getch()) getch(); exit(1); } next(); } // numpar ::= number | '(' expr ')' double numpar() { if (Op=='n') { double res=tokval; skip('n'); return res; } skip('('); double res=expr(); skip(')'); return res; } // factor ::= numpar | numpar '^' factor double factor() { double res=numpar(); if (Op=='^') { skip('^'); res=pow(res,factor()); } return res; } // term ::= factor | term '*' factor | term '/' factor double term() { double res=factor(); for (;;) { if (Op=='*') { skip('*'); res*=factor(); } else if (Op=='/') { skip('/'); res/=factor(); } else return res; } } // expr ::= term | expr '+' term | expr '-' term double expr() { double res=term(); for (;;) { if (Op=='+') { skip('+'); res+=term(); } else if (Op=='-') { skip('-'); res-=term(); } else return res; } }
Решение задачи: «Распознавание формулы со сложными математическими функциями в строке»
textual
Листинг программы
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <ctype.h> #include <conio.h> #include <alloc.h> #include <graphics.h> #include <DOS.h> #define pi 3.14159265 int next(char *s,char *sid); int skip(int t, char *s,char *sid); double expr(char *s,char *sid); double numpar(char *s,char *sid); double factor(char *s,char *sid); double term(char *s,char *sid); void test(); int mod(char *s); int graph(char *s,char *sid); struct Operation { char* sid[7]; int Op; double tokval; double x; }Oper={"sin","cos","tg","ctg","sqrt","log","exp"}; int main() { char c; int i=0; char *s,sid[6]; int blocknum=0; int gd=DETECT,gm,err; heapinfo hi; hi.ptr=NULL; clrscr(); printf("\nEnter the formula\n"); fflush(stdin); s=(char*)realloc(s,++i*sizeof(char)); s[i-1]='('; while((c=getch())!=13) { if(c==8) continue; fflush(stdin); putch(c); s=(char*)realloc(s,++i*sizeof(char)); if(s==NULL) { printf("\n memory error"); if(!getch()) getch(); return -1; } s[i-1]=c; } s=(char*)realloc(s,++i*sizeof(char)); s[i-1]=')'; s[i]='\0'; mod(s); while(heapwalk(&hi)==_HEAPOK) if(hi.in_use) ++blocknum; test(); clrscr(); detectgraph(&gd,&gm); err=graphresult(); if(err) { printf("\n%s",grapherrormsg(err)); return 1; } registerbgidriver(EGAVGA_driver); initgraph(&gd,&gm,""); err=graphresult(); if(err) { printf("n%s",grapherrormsg(err)); return 2; } cleardevice(); clrscr(); graph(s,sid); if(!getch()) getch(); free(s); hi.ptr=NULL; while (heapwalk(&hi)==_HEAPOK) if(hi.in_use) --blocknum; if(blocknum) printf("\n Error: Useing block in heap \n"); clrscr(); closegraph(); return 0; } int mod(char *s) { int a,j,n=0,i=0; a=strlen(s); for(i=0;s[i]!='\0';i++) { if(s[i]=='-') { if(s[i-1]=='(') { for (j=0;j!=a+1-i;j++) s[(a+1)-j]=s[a-j]; s[i]='0'; } } } a=strlen(s); for(i=0;i<a;i++) { if(s[i]=='(') n=n+1; if(s[i]==')') n=n-1; } if(n!=0) { closegraph(); printf("\nYou take a error, try agan"); if(!getch()) getch(); exit(1); } return 0; } int next(char *s,char *sid) { int c,count=0; static int i=0; char cbuf[50]; if(Oper.Op=='Ж') i=0; for (;;) { c=s[i++]; if(strchr("+-*/^()\n",c)!=NULL&&i!=1) { if(c=='*'&&s[i]=='*') { i=i+1; return Oper.Op='^'; } return Oper.Op=c; } if(isspace(c)) continue; if(isdigit(c)||c=='.'||c=='x') { for(;(c=='x'||(c>='0'&&c<='9')||c=='.');) { if(c=='x') { if(s[i-i]=='-') Oper.tokval=-1*Oper.x; else Oper.tokval=Oper.x; return Oper.Op='n'; } cbuf[count++]=c; cbuf[count]='\0'; c=s[i++]; } i-=1; Oper.tokval=atof(cbuf); return Oper.Op='n'; } if(isalpha(c)) { if(c=='p'&&s[i++]=='i') { Oper.tokval=pi; return Oper.Op='n'; } do { cbuf[count++]=c; cbuf[count]='\0'; c=s[i++]; } while(isalpha(c)); strcpy(sid,cbuf); i--; return Oper.Op='a';//alpha function } } } int skip(int t,char *s,char *sid) { if(Oper.Op!=t) { closegraph(); printf("\nYou take a error, try agan"); if(!getch()) getch(); exit(1); } next(s,sid); return 0; } // numpar ::= number | '(' expr ')' | (func1||...||func2) '(' expr ')' double numpar(char *s,char *sid) { int i=0,j=0; if (Oper.Op=='n') { double res=Oper.tokval; skip('n',s,sid); return res; } if (Oper.Op=='a') { skip('a',s,sid); skip('(',s,sid); double res=expr(s,sid); skip(')',s,sid); for(i=0;(strcmp(sid,Oper.sid[i])!=0);i++); switch(i) { case 0: res=sin(res); break; case 1: res=cos(res); break; case 2: res=sin(res)/cos(res); break; case 3: res=cos(res)/sin(res); break; case 4: if(res>=0) res=sqrt(res); else { res=res+getmaxx()/2; res=sqrt(res); } break; case 5: if(res>=0) res=log(res); else { res=res+getmaxx()/2; res=log(res); } break; case 6: res=exp(res); break; default: closegraph(); printf("\nBad function: %s\n",sid);res=0; } return res; } skip('(',s,sid); double res=expr(s,sid); skip(')',s,sid); return res; } // factor ::= numpar | numpar '^' factor double factor(char *s,char *sid) { double res=numpar(s,sid); if (Oper.Op=='^') { skip('^',s,sid); res=pow(res,factor(s,sid)); } return res; } // term ::= factor | term '*' factor | term '/' factor double term(char *s,char *sid) { double temp; double res=factor(s,sid); for (;;) { if (Oper.Op=='*') { skip('*',s,sid); res*=factor(s,sid); } else if (Oper.Op=='/') { skip('/',s,sid); temp=factor(s,sid); if(temp!=0) res/=temp; else { temp=temp+0.001; res/=temp; } } else return res; } } // expr ::= term | expr '+' term | expr '-' term double expr(char *s,char *sid) { double res=term(s,sid); for (;;) { if (Oper.Op=='+') { skip('+',s,sid); res+=term(s,sid); } else if (Oper.Op=='-') { skip('-',s,sid); res-=term(s,sid); } else return res; } } void test() { char s[]="(sin(pi)^2+cos(pi)^2)"; char sid[6]; next(s,sid); if(sin(pi)*sin(pi)+cos(pi)*cos(pi)!=expr(s,sid)) { clrscr(); printf("\nTest failed"); if(!getch()) getch(); exit(1); } Oper.Op='Ж'; Oper.tokval=0; } int graph(char *s,char *sid) { float a,b,i; int xmax,ymax,px,py,x0,y0; a=-4; b=4; xmax=getmaxx()+1; ymax=getmaxy()+1; px=100; py=100; x0=xmax/2; y0=ymax/2; for(;;) { if(((xmax/2+b*px)>xmax)||((xmax/2+a*px)<0)) { next(s,sid); putpixel(xmax/2+Oper.x*px,ymax/2-expr(s,sid)*py,WHITE); px=px-1; py=py-1; Oper.Op='Ж'; Oper.tokval=0; continue; } bar(0,0,xmax,ymax); setfillstyle(SOLID_FILL,WHITE); setcolor(GREEN); setlinestyle(SOLID_LINE,0,3); line(0,y0,xmax,y0); line(x0,0,x0,ymax); line(xmax,y0,xmax-20,y0+10); line(xmax,y0,xmax-20,y0-10); line(x0,0,x0-10,0+20); line(x0,0,x0+10,0+20); setlinestyle(DASHED_LINE,0,2); for(i=x0;i<xmax;i+=px) line(i,0,i,ymax); for(i=x0;i>0;i-=px) line(i,0,i,ymax); for(i=y0;i>0;i-=py) line(0,i,xmax,i); for(i=y0;i<ymax;i+=py) line(0,i,xmax,i); setlinestyle(DOTTED_LINE,0,2); for(i=x0;i<xmax;i+=(px/10)) line(i,0,i,ymax); for(i=x0;i>0;i-=(px/10)) line(i,0,i,ymax); for(i=y0;i>0;i-=(py/10)) line(0,i,xmax,i); for(i=y0;i<ymax;i+=(py/10)) line(0,i,xmax,i); setcolor(BROWN); setlinestyle(SOLID_LINE,0,3); circle(x0,y0,2); circle(x0+px,y0,2); circle(x0,y0-py,2); settextstyle(0,0,2); outtextxy(x0-18,y0+7,"0"); outtextxy(x0+px,y0+14,"1"); outtextxy(x0-14,y0-py,"1"); outtextxy(xmax-25,y0+14,"X"); outtextxy(x0-18,0+25,"Y"); for(Oper.x=a;Oper.x<b;Oper.x+=(b-a)/xmax) { next(s,sid); putpixel(xmax/2+Oper.x*px,ymax/2-expr(s,sid)*py,BLUE); delay(5); Oper.Op='Ж'; Oper.tokval=0; } break; } return 0; }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д