自己编的简易计算器,可以运算+ - * / ()的表达式,可以计算小数
#include "unistd.h" /*头文件瞎搞的,对这个一直不了解*/#include "stdlib.h"
#include "stdio.h"
struct a /*存放字符和字符运算优先级*/
{
char ax[10];
char *top1;
char *base1;
int p1;
};
struct b /*存放运算数*/
{
float bx[10];
float *top;
float *base;
};
struct a *p;
struct b *s;
int pan(char c) /*判断运算优先级别*/
{
int i;
switch(c)
{
case '+':
i=1;
break;
case '-':
i=1;
break;
case '*':
i=2;
break;
case '/':
i=2;
break;
case '(':
i=3;
break;
case ')':
i=4;
break;
default :
printf("表达式错误,你妹\n");
exit(0);
}
return(i);
}
void init1(struct a *p) /*初始化站*/
{
p->base1=p->ax;
p->top1=p->ax;
}
void init(struct b *s)
{
s->base=s->bx;
s->top=s->bx;
}
void pusha(struct a *p,char c)
{
*(p->top1)=c;
p->top1++;
p->p1=pan(c);
}
void pushb(struct b *s,float c)
{
*(s->top)=c;
s->top++;
}
char popa(struct a *p)
{
char c;
p->top1-=1;
c=*(p->top1);
return(c);
}
float popb(struct b *s)
{
float c;
s->top-=1;
c=*(s->top);
return(c);
}
int qunfen(char *st,float num[],char *st1) /*从字符串中分离出数和运算符分别放在NUM【】和STR数组中*/
{
int j=0,o=0,m=0,t,z=0,u,x=0,n=0,l=0;
float f,f1=0;
float num1[10];
if((*(st+j)<'0'&&*(st+j)!='(')||(*(st+j)>'9'&&*(st+j)!='('))
{
printf("表达式错误11111\n"); /*读入字符串,起手不是数字和符号‘(’,表达式就是错误的*/
exit(1);
}
if(*(st+j)=='(') /*对表达式的处理分两种情况,‘(’是字符起头的,和不是字符起头的*/
{ /*是字符起头的要对其进行初始话,有考虑不写这段*/
z=1;
*st1=*st;
m++;
j++;
}
while(*(st+j)!='\0') /*对字符的循环读入操作*/
{
if((*(st+j)>='0'&&*(st+j)<='9')||*(st+j)=='.') /*判断是否为数字 数字组成是有0-9和.构成*/
{
num1[o]=*(st+j)-'0'; /*ASCII码是从0是从48开始的,所以要得到数字必须减掉48,才是ASCII码 0 1 23*/
t=o; /*t=o 主要是对读入数字的个数进行计数*/
o++; /*o记录的是当前读入数字的下标,NUM数组将这些数字进行存放*/
z=0; /*“z”主要是记录读入字符的个数的,字符个数除去遇到‘)’时 其值会曾到1以上*/
}
else
{
if(z!=0&&*(st+j)!='('&&*(st+j)!=')')
{
printf("表达式错误xxxx:\n"); /*不是因为因为字符’(‘’)‘引起的Z!=0的情况都是错误的表达式*/
exit(1); /*例如"*("或者")+" 是正常的*/
}
else
{
if(z==0) /*在这个地方计算数的原因是 这个选择分支代表上面数的读入结束*/
{
f=num1[0]; /*先读入的数字是数的最高位的,数字*10可以提高数的位 21=10*2+1来的*/
for(u=1;u<=t;u++) /*t是代表读入数的数组的最大下标 对于num1[0]他是最高的位 */
{ /*f记录每次10*f的值 比如 num[t]={12345} f=1 f=10*f+num[u] 就可以表达成*/
if(num1[u]>=0) /* f=10*1+2 f=12 通过循环把数用f记录下来*/
f=10*f+num1[u]; /* 为什么要判断 num1[u]的值是否》0 主要是小数点.的ASCII码为46当num[u]<0*/
else /*就要跳出循环去计算小数点后面的值*/
break;
}
if(u<t) /*计算小数点的值,F1存放*/
{
f1=num1[t]/10;
t=t-1;
for(;t>u;t--)
f1=(f1+num1[t])/10;
}
f=f1+f;
f1=0; /*你说的问题在这个地方要对f1清零,用在下次存放小数*/
num[x]=f;
x++;
o=0;
}
if(*(st+j)=='(') n++;
else if(*(st+j)==')') l++;
*(st1+m)=*(st+j); /*这个地方是对字符做的处理*/
m++;z++; /*z,读入1个字符实现自加,如果不是'(',')'造成的z=2的情况的话 表达式就是错误的*/
}
}
j++;
}
if(n!=l)
{printf("表达式错误!!!!");
exit(0);
} /*while(循环体结束后因为只读入了数 而没有处理数 所以这里要重新处理数)*/
f=num1[0];
for(u=1;u<=t;u++){
if(num1[u]>=0)
{
f=10*f+num1[u];
}
else
break;
}
if(u<t)
{
f1=num1[t]/10;
t=t-1;
for(;t>u;t--)
f1=(f1+num1[t])/10;
}
f=f1+f;
num[x]=f;
*(st1+m)='\0'; /*一点不要忘记存入的字符结束标志存入*/
}
float jisuan(char c,float a1,float a2 ) /*计算*/
{
switch(c)
{
case '+':
a1=a1+a2;
break;
case '-':
a1=a2-a1;
break;
case '*':
a1=a1*a2;
break;
case '/':
a1=a2/a1;
break;
}
return(a1);
}
float jieguo(char *st,float num[]) /*通过两个栈分别放运算符和数据来进行运算*/
{
float a1,a2,jg1; /*a1 a2取出的运算数, jg1存放运算结果 jg 是多余的*/
char c;
int i=0,j=2,n;
init1(p);
init(s);
if(*st=='(') /*同样表达式要分起手是’(‘和不是的情况,是的话就不用放入操作数到栈里面 记住1个 字符对应两个数*/
{
pusha(p,*st);
i++;
}
pusha(p,*(st+i)); /*进入循环体前 数据的初始化*/
pushb(s,num[0]);
pushb(s,num[1]);
i++;
while(*(st+i)!='\0')
{
n=pan(*(st+i)); /*数的优先级别的判定,分成3中情况 ’(‘和’)‘和其他*/
if(n!=3&&n!=4)
{
if(n>p->p1) /*优先级别大于栈中的优先级别 那么从数据中放入一个数到栈中 后再取出两个数进行操作*/
{
pushb(s,num[j]); /*有想过从栈取一个数然后在从数组中取一个数进行运算,这样省一步入栈,觉得麻烦就没这么做*/
a1=popb(s);
a2=popb(s);
jg1=jisuan(*(st+i),a1,a2);
pushb(s,jg1);
}
else
{
a1=popb(s); /*优先级小于等于的话 就得从栈中取两个数运算后把结果放进去 这样栈中只有1个操作数,所以要放入一个数*/
a2=popb(s); /*运算符也少了1个,所以要进仓*/
c=popa(p);
jg1=jisuan(c,a1,a2);
pushb(s,jg1);
pushb(s,num[j]);
pusha(p,*(st+i));
}
i++; /*因为所以的操作都花掉了数据NUM和运算符一个, 所以都得指向下一个要操作的数和运算符*/
j++;
}
if(n==3)
{ /*为'('的时候 不需要进行运算但是得放入两个数和一个运算符 为下一次运算初始话*/
pusha(p,*(st+i));
pusha(p,*(st+i+1));
i=i+2;
pushb(s,num[j]); /*老师这个地方做了更改的,因为上面的操作已经放了一个数 所以这个地方只用放一个数字*/
j++;
}
else if(n==4) /*为')'的时候 '(' ‘)’里面肯定是有两个数和1个运算符 */
{
a1=popb(s);
a2=popb(s);
c=popa(p);
jg1=jisuan(c,a1,a2);
pushb(s,jg1);
popa(p);
i++;
if(p->top1==p->base1) /*运算完了就得判断表达式的情况了,如果没有运算符了,这个时候就只有1个数了*/
{
if(*(st+i)!='\0') /*判断还有木有运算符,有的话就放1个数 1个运算符*/
{
pusha(p,*(st+i));
pushb(s,num[j]);
j++;
i++;
}
}
}
}
if((s->top-s->base)!=1) /*元算完后 要么只有1个数在栈中,要么就是2个数在数据栈中 1个操作符在运算符栈里*/
{ /*因为+-/*都是双目运算符*/
a1=popb(s);
a2=popb(s);
c=popa(p);
jg1=jisuan(c,a1,a2);
}
return(jg1);
}
int main()
{
char *st,*st1,num4[20],num5[10];
float num[10],zjg;
st=num4;
st1=num5;
s=(struct b*)malloc(sizeof(struct b));
p=(struct a*)malloc(sizeof(struct a));
printf("请输入表达式:\n");
scanf("%s",st);
qunfen(st,num,st1);
zjg=jieguo(st1,num);
printf("%f\n",zjg);
}
老师您给再看看 这次 全改好了,自己的算法图 对着代码全部都检查过了,您给再挑挑毛病把。
[ 本帖最后由 zhu224039 于 2012-8-21 21:26 编辑 ]