Распознавание формулы со сложными математическими функциями в строке - 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;
}

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


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

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

11   голосов , оценка 3.636 из 5
Похожие ответы