Распознавание формулы со сложными математическими функциями в строке - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Задание курсовика - распознать формулу функции введенную с клавиатуры и построить ее график (прикручу графику позже, сам код уже написан мной для лабы, да и мелочи буду вылизывать в конце), нашел превосходный способ распознавания, допилил и модифицировал его под себя, так что остался только один не решенный вопрос о том, как можно реализовать распознавание матем. функций, на подобии sin, cos, log и других, на мой взгляд основная сложность заключается в том что бы распознать то что находиться у этих функций в скобках, не представляю как это можно реализовать, да и к тому же надо будет учитывать одз, хотя возможно есть и другие подводные камни о которых я и не ведаю (пока), хотелось бы услышать практических советов или примерчика какого нибудь, заранее благодарю) До этого начинал с работать с польской записью, но этот метод, в плане вычисления показался мне несколько проще - проще реализация вычисления "сложных" выражений содержащих в перемешку разные по приоритету операции. Пишу на чистом Си, в BorlandC 3.1 Сам код, избавленный от моих попыток научить программу понимать мат. функции:
Листинг программы
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <ctype.h>
  6. #include <conio.h>
  7. int next();
  8. void skip(int t);
  9. double expr();
  10. double numpar();
  11. double factor();
  12. double term();
  13. double x=5;
  14. int i=0; char s[50]; int Op; double tokval;
  15. int main()
  16. {
  17. clrscr();
  18. gets(s);
  19. //for(;x<10;x+=1)
  20. //{
  21. next();
  22. printf("\n%.9g\n", expr());
  23. // i=0;
  24. // Op=0;
  25. // tokval=0;
  26. //}
  27. if(!getch()) getch();
  28. clrscr();
  29. return 0;
  30. }
  31. int next()
  32. {
  33. int c,count=0;
  34. char cbuf[50];
  35. for (;;)
  36. {
  37. c=s[i++];
  38. if(strchr("+-*/^()\n",c)!=NULL&&i!=1)
  39. if(c=='*'&&s[i]=='*')
  40. {
  41. i=i+1;
  42. return Op='^';
  43. }
  44. else
  45. return Op=c;
  46. if(c=='s'&&s[i]=='i'&&s[i+1]=='n')
  47. {
  48. i=i+2;
  49. return Op='s';
  50. }
  51. if(isspace(c)) continue;
  52. if(isdigit(c)||c=='.'||c=='x'||c=='-')
  53. {
  54. if(c=='x')
  55. {
  56. tokval=x;
  57. return Op='n';
  58. }
  59. for(;((c>='0'&&c<='9')||c=='.'||c=='-');)
  60. {
  61. cbuf[count++]=c;
  62. cbuf[count]='\0';
  63. c=s[i++];
  64. }
  65. i-=1;
  66. tokval=atof(cbuf);
  67. return Op='n';
  68. }
  69. printf("Bad character: %c\n",c);
  70. if(!getch()) getch();
  71. }
  72. }
  73. void skip(int t)
  74. {
  75. if(Op!=t)
  76. {
  77. printf("You take a error, try agan");
  78. if(!getch()) getch();
  79. exit(1);
  80. }
  81. next();
  82. }
  83. // numpar ::= number | '(' expr ')'
  84. double numpar()
  85. {
  86. if (Op=='n')
  87. {
  88. double res=tokval;
  89. skip('n');
  90. return res;
  91. }
  92. skip('(');
  93. double res=expr();
  94. skip(')');
  95. return res;
  96. }
  97. // factor ::= numpar | numpar '^' factor
  98. double factor()
  99. {
  100. double res=numpar();
  101. if (Op=='^')
  102. {
  103. skip('^');
  104. res=pow(res,factor());
  105. }
  106. return res;
  107. }
  108. // term ::= factor | term '*' factor | term '/' factor
  109. double term()
  110. {
  111. double res=factor();
  112. for (;;)
  113. {
  114. if (Op=='*')
  115. {
  116. skip('*');
  117. res*=factor();
  118. }
  119. else
  120. if (Op=='/')
  121. {
  122. skip('/');
  123. res/=factor();
  124. }
  125. else
  126. return res;
  127. }
  128. }
  129. // expr ::= term | expr '+' term | expr '-' term
  130. double expr()
  131. {
  132. double res=term();
  133. for (;;)
  134. {
  135. if (Op=='+')
  136. {
  137. skip('+');
  138. res+=term();
  139. }
  140. else
  141. if (Op=='-')
  142. {
  143. skip('-');
  144. res-=term();
  145. }
  146. else
  147. return res;
  148. }
  149. }

Решение задачи: «Распознавание формулы со сложными математическими функциями в строке»

textual
Листинг программы
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <ctype.h>
  6. #include <conio.h>
  7. #include <alloc.h>
  8. #include <graphics.h>
  9. #include <DOS.h>
  10. #define pi 3.14159265
  11. int next(char *s,char *sid);
  12. int skip(int t, char *s,char *sid);
  13. double expr(char *s,char *sid);
  14. double numpar(char *s,char *sid);
  15. double factor(char *s,char *sid);
  16. double term(char *s,char *sid);
  17. void test();
  18. int mod(char *s);
  19. int graph(char *s,char *sid);
  20.  
  21. struct Operation
  22. {
  23.        char* sid[7];
  24.        int Op;
  25.        double tokval;
  26.        double x;
  27. }Oper={"sin","cos","tg","ctg","sqrt","log","exp"};
  28.  
  29. int main()
  30. {
  31. char c;
  32. int i=0;
  33. char *s,sid[6];
  34. int blocknum=0;
  35. int gd=DETECT,gm,err;
  36.     heapinfo hi;
  37.     hi.ptr=NULL;
  38.     clrscr();
  39.     printf("\nEnter the formula\n");
  40.     fflush(stdin);
  41.     s=(char*)realloc(s,++i*sizeof(char));
  42.     s[i-1]='(';
  43.     while((c=getch())!=13)
  44.     {
  45.         if(c==8) continue;
  46.         fflush(stdin);
  47.         putch(c);
  48.         s=(char*)realloc(s,++i*sizeof(char));
  49.         if(s==NULL)
  50.         {
  51.                 printf("\n memory error");
  52.                 if(!getch()) getch();
  53.                 return -1;
  54.         }
  55.         s[i-1]=c;
  56.     }
  57.     s=(char*)realloc(s,++i*sizeof(char));
  58.     s[i-1]=')';
  59.     s[i]='\0';
  60.     mod(s);
  61.     while(heapwalk(&hi)==_HEAPOK)
  62.     if(hi.in_use) ++blocknum;
  63.     test();
  64.     clrscr();
  65.     detectgraph(&gd,&gm);
  66.     err=graphresult();
  67.     if(err)
  68.     {
  69.         printf("\n%s",grapherrormsg(err));
  70.         return 1;
  71.     }
  72.     registerbgidriver(EGAVGA_driver);
  73.     initgraph(&gd,&gm,"");
  74.     err=graphresult();
  75.     if(err)
  76.     {
  77.         printf("n%s",grapherrormsg(err));
  78.         return 2;
  79.     }
  80.     cleardevice();
  81.     clrscr();
  82.     graph(s,sid);
  83.     if(!getch()) getch();
  84.     free(s);
  85.     hi.ptr=NULL;
  86.     while (heapwalk(&hi)==_HEAPOK)
  87.           if(hi.in_use)
  88.              --blocknum;
  89.           if(blocknum)
  90.             printf("\n Error: Useing block in heap \n");
  91.     clrscr();
  92.     closegraph();
  93.     return 0;
  94. }
  95. int mod(char *s)
  96. {
  97. int a,j,n=0,i=0;
  98.     a=strlen(s);
  99.     for(i=0;s[i]!='\0';i++)
  100.     {
  101.         if(s[i]=='-')
  102.         {
  103.                 if(s[i-1]=='(')
  104.                 {
  105.                         for (j=0;j!=a+1-i;j++) s[(a+1)-j]=s[a-j];
  106.                         s[i]='0';
  107.                 }
  108.         }
  109.     }
  110.     a=strlen(s);
  111.     for(i=0;i<a;i++)
  112.     {
  113.         if(s[i]=='(') n=n+1;
  114.         if(s[i]==')') n=n-1;
  115.     }
  116.     if(n!=0)
  117.     {
  118.         closegraph();
  119.         printf("\nYou take a error, try agan");
  120.         if(!getch()) getch();
  121.         exit(1);
  122.     }
  123.     return 0;
  124. }
  125.  
  126. int next(char *s,char *sid)
  127. {
  128. int c,count=0;
  129. static int i=0;
  130. char cbuf[50];
  131.     if(Oper.Op=='Ж') i=0;
  132.     for (;;)
  133.     {
  134.         c=s[i++];
  135.         if(strchr("+-*/^()\n",c)!=NULL&&i!=1)
  136.         {
  137.             if(c=='*'&&s[i]=='*')
  138.             {
  139.                     i=i+1;
  140.                     return Oper.Op='^';
  141.             }
  142.             return Oper.Op=c;
  143.         }
  144.         if(isspace(c)) continue;
  145.         if(isdigit(c)||c=='.'||c=='x')
  146.         {
  147.  
  148.                         for(;(c=='x'||(c>='0'&&c<='9')||c=='.');)
  149.                         {
  150.                                 if(c=='x')
  151.                                      {
  152.                                         if(s[i-i]=='-') Oper.tokval=-1*Oper.x;
  153.                                         else
  154.                                         Oper.tokval=Oper.x;
  155.                                         return Oper.Op='n';
  156.                                      }
  157.                                 cbuf[count++]=c;
  158.                                 cbuf[count]='\0';
  159.                                 c=s[i++];
  160.                         }
  161.                         i-=1;
  162.                         Oper.tokval=atof(cbuf);
  163.                         return Oper.Op='n';
  164.         }
  165.         if(isalpha(c))
  166.         {
  167.                 if(c=='p'&&s[i++]=='i')
  168.                 {
  169.                         Oper.tokval=pi;
  170.                         return Oper.Op='n';
  171.  
  172.                 }
  173.                 do
  174.                 {
  175.                         cbuf[count++]=c;
  176.                         cbuf[count]='\0';
  177.                         c=s[i++];
  178.                 }
  179.                 while(isalpha(c));
  180.                 strcpy(sid,cbuf);
  181.                 i--;
  182.                 return Oper.Op='a';//alpha function
  183.         }
  184.     }
  185. }
  186. int skip(int t,char *s,char *sid)
  187. {
  188.     if(Oper.Op!=t)
  189.     {
  190.         closegraph();
  191.         printf("\nYou take a error, try agan");
  192.         if(!getch()) getch();
  193.         exit(1);
  194.     }
  195.     next(s,sid);
  196.     return 0;
  197. }
  198.  
  199. // numpar ::= number | '(' expr ')' | (func1||...||func2) '(' expr ')'
  200. double numpar(char *s,char *sid)
  201. {
  202. int i=0,j=0;
  203.     if (Oper.Op=='n')
  204.     {
  205.         double res=Oper.tokval;
  206.         skip('n',s,sid);
  207.         return res;
  208.     }
  209.     if (Oper.Op=='a')
  210.     {
  211.         skip('a',s,sid);
  212.         skip('(',s,sid);
  213.         double res=expr(s,sid);
  214.         skip(')',s,sid);
  215.         for(i=0;(strcmp(sid,Oper.sid[i])!=0);i++);
  216.         switch(i)
  217.         {
  218.                 case 0: res=sin(res); break;
  219.                 case 1: res=cos(res); break;
  220.                 case 2: res=sin(res)/cos(res); break;
  221.                 case 3: res=cos(res)/sin(res); break;
  222.                 case 4: if(res>=0) res=sqrt(res);
  223.                         else
  224.                         {
  225.                                 res=res+getmaxx()/2;
  226.                                 res=sqrt(res);
  227.                         }
  228.                         break;
  229.                 case 5: if(res>=0) res=log(res);
  230.                         else
  231.                         {
  232.                                 res=res+getmaxx()/2;
  233.                                 res=log(res);
  234.  
  235.                         }
  236.                 break;
  237.                 case 6: res=exp(res); break;
  238.                 default: closegraph(); printf("\nBad function: %s\n",sid);res=0;
  239.         }
  240.         return res;
  241.     }
  242.     skip('(',s,sid);
  243.     double res=expr(s,sid);
  244.     skip(')',s,sid);
  245.     return res;
  246. }
  247. // factor ::= numpar | numpar '^' factor
  248. double factor(char *s,char *sid)
  249. {
  250.     double res=numpar(s,sid);
  251.     if (Oper.Op=='^')
  252.  
  253.     {
  254.         skip('^',s,sid);
  255.         res=pow(res,factor(s,sid));
  256.     }
  257.     return res;
  258. }
  259. // term ::= factor | term '*' factor | term '/' factor
  260. double term(char *s,char *sid)
  261. {
  262. double temp;
  263.     double res=factor(s,sid);
  264.     for (;;)
  265.     {
  266.         if (Oper.Op=='*')
  267.         {
  268.                 skip('*',s,sid);
  269.                 res*=factor(s,sid);
  270.         }
  271.         else
  272.         if (Oper.Op=='/')
  273.         {
  274.                 skip('/',s,sid);
  275.                 temp=factor(s,sid);
  276.                 if(temp!=0) res/=temp;
  277.                 else
  278.                 {
  279.                      temp=temp+0.001;
  280.                      res/=temp;
  281.                 }
  282.         }
  283.         else
  284.         return res;
  285.     }
  286. }
  287. // expr ::= term | expr '+' term | expr '-' term
  288. double expr(char *s,char *sid)
  289. {
  290.     double res=term(s,sid);
  291.     for (;;)
  292.         {
  293.                 if (Oper.Op=='+')
  294.                 {
  295.                         skip('+',s,sid);
  296.                         res+=term(s,sid);
  297.                 }
  298.                 else
  299.                 if (Oper.Op=='-')
  300.                 {
  301.                         skip('-',s,sid);
  302.                         res-=term(s,sid);
  303.                 }
  304.                 else
  305.                 return res;
  306.  
  307.  
  308.         }
  309. }
  310.  
  311. void test()
  312. {
  313. char s[]="(sin(pi)^2+cos(pi)^2)";
  314. char sid[6];
  315.      next(s,sid);
  316.      if(sin(pi)*sin(pi)+cos(pi)*cos(pi)!=expr(s,sid))
  317.      {
  318.         clrscr();
  319.         printf("\nTest failed");
  320.         if(!getch()) getch();
  321.         exit(1);
  322.      }
  323.      Oper.Op='Ж';
  324.      Oper.tokval=0;
  325. }
  326. int graph(char *s,char *sid)
  327. {
  328. float a,b,i;
  329. int xmax,ymax,px,py,x0,y0;
  330.         a=-4;
  331.         b=4;
  332.         xmax=getmaxx()+1;
  333.         ymax=getmaxy()+1;
  334.         px=100;
  335.         py=100;
  336.         x0=xmax/2;
  337.         y0=ymax/2;
  338.  
  339.         for(;;)
  340.         {
  341.                 if(((xmax/2+b*px)>xmax)||((xmax/2+a*px)<0))
  342.                 {
  343.                         next(s,sid);
  344.                         putpixel(xmax/2+Oper.x*px,ymax/2-expr(s,sid)*py,WHITE);
  345.                         px=px-1;
  346.                         py=py-1;
  347.                         Oper.Op='Ж';
  348.                         Oper.tokval=0;
  349.                         continue;
  350.                 }
  351.                 bar(0,0,xmax,ymax);
  352.                 setfillstyle(SOLID_FILL,WHITE);
  353.                 setcolor(GREEN);
  354.                 setlinestyle(SOLID_LINE,0,3);
  355.                 line(0,y0,xmax,y0);
  356.                 line(x0,0,x0,ymax);
  357.                 line(xmax,y0,xmax-20,y0+10);
  358.                 line(xmax,y0,xmax-20,y0-10);
  359.                 line(x0,0,x0-10,0+20);
  360.                 line(x0,0,x0+10,0+20);
  361.                 setlinestyle(DASHED_LINE,0,2);
  362.                 for(i=x0;i<xmax;i+=px) line(i,0,i,ymax);
  363.                 for(i=x0;i>0;i-=px) line(i,0,i,ymax);
  364.                 for(i=y0;i>0;i-=py) line(0,i,xmax,i);
  365.                 for(i=y0;i<ymax;i+=py) line(0,i,xmax,i);
  366.                 setlinestyle(DOTTED_LINE,0,2);
  367.                 for(i=x0;i<xmax;i+=(px/10)) line(i,0,i,ymax);
  368.                 for(i=x0;i>0;i-=(px/10)) line(i,0,i,ymax);
  369.                 for(i=y0;i>0;i-=(py/10)) line(0,i,xmax,i);
  370.                 for(i=y0;i<ymax;i+=(py/10)) line(0,i,xmax,i);
  371.                 setcolor(BROWN);
  372.                 setlinestyle(SOLID_LINE,0,3);
  373.                 circle(x0,y0,2);
  374.                 circle(x0+px,y0,2);
  375.                 circle(x0,y0-py,2);
  376.                 settextstyle(0,0,2);
  377.                 outtextxy(x0-18,y0+7,"0");
  378.                 outtextxy(x0+px,y0+14,"1");
  379.                 outtextxy(x0-14,y0-py,"1");
  380.                 outtextxy(xmax-25,y0+14,"X");
  381.                 outtextxy(x0-18,0+25,"Y");
  382.                 for(Oper.x=a;Oper.x<b;Oper.x+=(b-a)/xmax)
  383.                    {
  384.                         next(s,sid);
  385.                         putpixel(xmax/2+Oper.x*px,ymax/2-expr(s,sid)*py,BLUE);
  386.                         delay(5);
  387.                         Oper.Op='Ж';
  388.                         Oper.tokval=0;
  389.                    }
  390.                 break;
  391.         }
  392.         return 0;
  393. }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 3.636 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы