翁恺大作业二 画函数图像
之前写的计算器没用到,自己有重写了一个,这次用了好多栈,感觉最失败的地方是没有事先构思好框架,一有bug就补一个判断,又产生新的bug,唉。
代码:(中间注释的一大片是debug时写的,后来bug越弄越多,受不了了,就停工了。
//2019.4.17 16:00--2019.4.18 0:30
//2019.4.20 7:10--14:20
//2019.4.21 17:00--21:00 发现乘法的bug,debug无果,哭
//3180105524 黄隆钤
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include"acllib.h"
#include<ctype.h>
void read();
int isop(char ch);
void paint(char *fname);
char fname[1000];
int Setup()
{
initConsole();
initWindow("paintfx",-1,-1,800,600);
read(fname);
paint(fname);
return 0;
}
int isop(char ch)
{
return ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^';
}
void read(char *fname)
{
char ch;
int k=0,i,pl=0,pr=0;
ch=getchar();
while(ch!='\n')
{
if(ch==' ')
{
ch=getchar();
continue;
}
fname[k++]=ch;
ch=getchar();
}
for(i=0;i<strlen(fname);i++)
{
if(fname[i]=='(')pl++;
if(fname[i]==')')pr++;
}
if(pr!=pl)
{
printf("input error!");
memset(fname,'\0',sizeof(fname));
return;
}
return;
}
double func(char*d,double x)
{
if(strcmp(d,"nis")==0)return sin(x);
else if(strcmp(d,"soc")==0)return cos(x);
else if(strcmp(d,"nat")==0)return tan(x);
else if(strcmp(d,"toc")==0)return 1/tan(x);
else if(strcmp(d,"csc")==0)return 1/sin(x);
else if(strcmp(d,"ces")==0)return 1/cos(x);
else if(strcmp(d,"natcra")==0)return atan(x);
else if(strcmp(d,"soccra")==0)return acos(x);
else if(strcmp(d,"niscra")==0)return asin(x);
else if(strcmp(d,"e")==0)return exp(x);
else if(strcmp(d,"hnis")==0)return sinh(x);
else if(strcmp(d,"hsoc")==0)return cosh(x);
else if(strcmp(d,"hnat")==0)return tanh(x);
else if(strcmp(d,"nl")==0)return log(x);
else if(strcmp(d,"gl")==0)return log10(x);
else if(strcmp(d,"trqs")==0)return sqrt(x);
else if(strcmp(d,"roolf")==0)return floor(x);
else if(strcmp(d,"sba")==0)return abs(x);
}
int prior(char a){
if(a=='+'||a=='-')return 1;
if(a=='*'||a=='/')return 2;
if(a=='^')return 3;
}
double cal(double x,double y,char ch)
{
if(ch=='+')return x+y;
if(ch=='-')return x-y;
if(ch=='*')return x*y;
if(ch=='/')return x/y;
if(ch=='^')return pow(x,y);
}
/*double f(double x)
{
char numstack[1000]={'\0'};//系数栈 放x前面的系数 利用这个省去“* ”
numstack[0]='1';
int numtop=0;
double dstack[1000]={0};//结果栈 存放一个运算块的运算结果
int dtop=0;
int i=0,l=strlen(fname);
//dstack[++dtop]=1;//结果栈初始化为1
char opstack[1000]={'\0'};//符号栈 存放操作符
int optop=0;
int flag=0,aflag=0;
char fstack[1000]={'\0'};//函数栈 存放函数名
fstack[0]=' ';
int ftop=0;
char fun[1000]={'\0'};//用来调用函数栈里的函数
int fk=0;
int plusflag=0;//很重要的一个标记 区分sin(x)+cos(x)和sin(2x+1)中“+ ”号的不同
// int lpara=0,rpara=0;
//以上是初始化
while(i<l)
{
if(isalpha(fname[i]))//如果是字母
{
if(fname[i]=='x')//字母为x
{
dstack[++dtop]=1;
dstack[dtop]*=x;
i++;
}
else
{
while(isalpha(fname[i])&&fname[i]!='x')
{
if(fname[i]=='(')break;
else if(isalpha(fname[i]))fstack[++ftop]=fname[i++];
}
fstack[++ftop]=' ';
}
}
else if(fname[i]=='(')
{
//lpara++;
/*if(i>=2&&!isalpha(fname[i-2])&&!isalpha(fname[i-1]))
{
dstack[dtop]*=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
dstack[++dtop]=1;
}*/
/*i++;
}
else if(isdigit(fname[i]))//如果是数字
{
while(isdigit(fname[i])||fname[i]=='.')numstack[numtop++]=fname[i++];
dstack[++dtop]=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
if(fname[i]=='x')
{
if(i+1<l&&fname[i+1]!='^')
{
dstack[dtop]*=x;
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
}
i++;
}
}
else if(isop(fname[i]))//如果是操作符
{
if(fname[i]=='+'||fname[i]=='-')//如果是加号或者减号
{
if(fname[i-1]==')')plusflag=1;//如果加减号前面是右括号 则不能直接对结果栈进行运算
}
if(fname[i]=='^')
{
/*if(numtop&&fname[i-1]!='x')//如果系数栈里有东西 则是指数函数类型 更新栈顶
{
dstack[dtop]*=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
}
if((!isdigit(fname[i+1])&&fname[i+1]!='x')||i+1==l)
{
printf("输入错误!");
system("pause");
exit(0);
}
if(fname[i+1]=='x')//指数函数
{
dstack[dtop]=pow(dstack[dtop],x);
i++;
}
// else
if(isdigit(fname[i+1]))//幂函数
{
dstack[dtop]=pow(dstack[dtop],fname[i+1]-'0');
i++;
}
else opstack[++optop]=fname[i];
}
else if(optop==0||prior(fname[i])>prior(opstack[optop]))
{
opstack[++optop]=fname[i];
dstack[++dtop]=1;
}
else if(optop&&prior(fname[i])<=prior(opstack[optop]))//运算
{
int j=1;
//if(lpara==rpara)
//{
while(optop>0)
{
dstack[dtop]=cal(dstack[dtop-j],dstack[dtop],opstack[optop--]);
j++;
}
// }
opstack[++optop]=fname[i];
dstack[++dtop]=1;
}
i++;
}
else if(fname[i]==')')
{
//rpara++;
/* if(numtop)
{
dstack[dtop]*=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
}
if(optop>0&&(opstack[optop]=='+'||opstack[optop]=='-')&&plusflag==0)
{
//dstack[dtop]=cal(dstack[dtop-1],dstack[dtop],opstack[optop--]);
int j=1;
while(optop>0)
{
dstack[dtop]=cal(dstack[dtop-j],dstack[dtop],opstack[optop--]);
j++;
}
}
else if(optop>0&&plusflag)plusflag=0;
if(ftop>0)ftop--;
i++;
if(ftop==0)fstack[ftop]=' ';
else
{
while(fstack[ftop]!=' ')
{
fun[fk++]=fstack[ftop];
fstack[ftop]='\0';
ftop--;
}
dstack[dtop]=func(fun,dstack[dtop]);
memset(fun,'\0',sizeof(fun));
fk=0;
}//依次对栈顶作用函数栈中的各函数
}
}
if(optop>0)
{
// if(numtop)dstack[dtop]*=atof(numstack);
dstack[dtop]=cal(dstack[dtop-1],dstack[dtop],opstack[optop--]);
}
return dstack[dtop];
}*/
double f(double x)
{
char numstack[1000]={'\0'};//系数栈 放x前面的系数 利用这个省去“* ”
numstack[0]='1';
int numtop=0;
double dstack[1000]={0};//结果栈 存放一个运算块的运算结果
int dtop=0;
int i=0,l=strlen(fname);
dstack[++dtop]=1;//结果栈初始化为1
char opstack[1000]={'\0'};//符号栈 存放操作符
int optop=0;
int flag=0,aflag=0;
char fstack[1000]={'\0'};//函数栈 存放函数名
fstack[0]=' ';
int ftop=0;
char fun[1000]={'\0'};//用来调用函数栈里的函数
int fk=0;
int plusflag=0;//很重要的一个标记 区分sin(x)+cos(x)和sin(2x+1)中的加号
//以上是初始化
while(i<l)
{
if(isalpha(fname[i]))//如果是字母
{
if(fname[i]=='x')//字母为x
{
dstack[dtop]*=x;
i++;
}
else {
while((isalpha(fname[i])&&fname[i]!='x')||fname[i]=='(')
{
if(fname[i]=='(')
{
fstack[++ftop]=' ';
i++;
}
else if(isalpha(fname[i]))fstack[++ftop]=fname[i++];
}
}
}
else if(isdigit(fname[i]))//如果是数字
while(isdigit(fname[i])||fname[i]=='.')numstack[numtop++]=fname[i++];
else if(isop(fname[i]))//如果是操作符
{
if(fname[i]=='+'||fname[i]=='-')//如果是加号或者减号
{
dstack[dtop]*=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
if(fname[i-1]==')')plusflag=1;//如果加减号前面有右括号 标记
}
if(fname[i]=='^')
{
if(numtop&&fname[i-1]!='x')//前面如果是x则不操作,此时为幂函数
{
dstack[dtop]*=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
}
if((!isdigit(fname[i+1])&&fname[i+1]!='x')||i+1==l)
{
printf("输入错误!");
system("pause");
exit(0);
}
if(fname[i+1]=='x')//指数函数
{
dstack[dtop]=pow(dstack[dtop],x);
i++;
}
else if(isdigit(fname[i+1]))//幂函数
{
dstack[dtop]=pow(dstack[dtop],fname[i+1]-'0');
i++;
}
}
else if(optop==0||prior(fname[i])>prior(opstack[optop]))
{
opstack[++optop]=fname[i];
dstack[++dtop]=1;
}
else if(optop&&prior(fname[i])<=prior(opstack[optop]))//运算
{
int j=1;
while(optop>0){
dstack[dtop]=cal(dstack[dtop-j],dstack[dtop],opstack[optop--]);
j++;
}
opstack[++optop]=fname[i];
dstack[++dtop]=1;
}
i++;
}
else if(fname[i]==')')
{
if(optop>0&&plusflag==0)
{
dstack[dtop]=cal(dstack[dtop-1],dstack[dtop],opstack[optop--]);
}
else if(optop>0&&plusflag)plusflag=0;
ftop--;
i++;
if(ftop==0)fstack[ftop]=' ';
else
{
while(fstack[ftop]!=' ')
{
fun[fk++]=fstack[ftop];
fstack[ftop]='\0';
ftop--;
}
dstack[dtop]=func(fun,dstack[dtop]);
memset(fun,'\0',sizeof(fun));
fk=0;
}//依次对栈顶作用函数栈中的各函数
if(numtop)
{
dstack[dtop]*=atof(numstack);
memset(numstack,'\0',sizeof(numstack));
numstack[0]='1';
numtop=0;
}
}
}
if(optop>0)
{
if(numtop)dstack[dtop]*=atof(numstack);
dstack[dtop]=cal(dstack[dtop-1],dstack[dtop],opstack[optop--]);
}
return dstack[dtop];
}
void paintpoint(int w,int h)
{
double maxx=-100000.0,min=100000;
double x;
for(x=-10;x<10;x+=0.5)
{
if(f(x)>maxx)maxx=fabs(f(x));
}
double k=3*h/(8*maxx);//换算系数
beginPaint();
for(x=-9.999;x<=10;x+=0.0001)
{
double nx=x*w/20+w/2,ny=-f(x)*k+h/2;
putPixel(nx,ny,BLUE);//注意纵坐标 加个负号
}
char mmax[100],mmin[100];
sprintf(mmax,"%.1f",maxx);
int l=strlen(mmax)-1;
double ls=(l-2)*7;
paintText(w/2-22-ls,h/2-maxx*k-3,mmax);
endPaint();
}
void paintcoordinate(w,h)
{
beginPaint();
paintText(w/2-15,h/2+15,"0");//注意最后一个参数是string
line(0,h/2,w,h/2);
line(w/2,0,w/2,h);
line(w/2,0,w/2-15,17);
line(w/2,0,w/2+15,17);
line(w,h/2,w-17,h/2-15);
line(w,h/2,w-17,h/2+15);
endPaint();
}
void paintfname(int w,int h,char *fname)
{
setTextFont("宋体");
setTextBkColor(EMPTY);//透明
setTextColor(BLACK);
setTextSize(20);
beginPaint();
char p[1000]={'\0'};
char p1[100]={'\0'},p2[100]={'\0'},
p3[100]={'\0'},p4[100]={'\0'};
p[0]='y';
p[1]='=';
strcat(p,fname);
int ll=strlen(p);
//为了把函数名控制在y轴左边的一定范围
//进行了一个小计算,调整函数名的位置
for(int j=0;j<ll;j++)
{
if(j<28)p1[j]=p[j];
else if(j<56)p2[j-28]=p[j];
else if(j<84)p3[j-56]=p[j];
else if(j<112)p4[j-84]=p[j];
paintText(35,h*1/6-30,p1);
paintText(35,h*1/6,p2);
paintText(35,h*1/6+30,p3);
paintText(35,h*1/6+60,p4);
}
endPaint();
}
void paint(char* fname)
{
int w=getWidth(),h=getHeight();
setTextBkColor(EMPTY);
paintpoint(w,h);
paintcoordinate(w,h);
paintfname(w,h,fname);
}