#include "stdlib.h"
#include "stdio.h"
#include <setjmp.h>
jmp_buf jmp;
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 p_i=0,s_i=0;
char *st,*st1;
float num[10],jg1;
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);
}
char SEEK(struct a *p)
{
char c;
c=*(p->top1-1);
return c;
}
float jisuanshu(int num1[],int i)
//对分离出来的单个数,进行计算,将你复原为数字,包括小数和整数分段计算再相加
{
int
j;
float f,f1=0;
f=num1[0];
for(j=1;j<=i;j++)
{
if(num1[j]>=0)
f=10*f+num1[j];
else
break;
}
if(j<i)
{
f1=num1[i]/10;
for(;i>j;i--)
f1=(f1+num1[i])/10;
}
f=f+f1;
return(f);
}
void biaodashi(char *st,int i,int z)
{
if(*(st+i)!='('&&*(st+i-1)!=')')
{
printf("表达式错误1,请重新输入:\n");
longjmp(jmp,1);
}
}
void biaodashi1(char *st,int i,int z)
{
if(*(st+i-1)!=')')
{
printf("表达式错误1,请重新输入:\n");
longjmp(jmp,1);
}
}
int qufen()
{
struct shu
{
int num1[10];
int j1;
//J1记录数在数组中的位置
}sj;
int i=0,j=0,z=1,k=0,m=0,k1=0,k2=0;
float f;
while(*(st+i)!='\0')
{
if((*(st+i)>='0'&&*(st+i)<='9')||*(st+i)=='.')
// 对是数字部分的字符进行分离
分离集合为{0-9和。}
{
sj.num1[j]=*(st+i)-'0';
//字符数字的ASCII码是从48开始的,char和int是通用的,当然只能从char转换成int 而不能将int转化成char
所有要得到数字 就需要减去
0的ASCII 48码
sj.j1=j;
j++; i++;
z=0;
}
else
{
if(z>0)
biaodashi(st,i,z);
if(z==0)
//这个分块Z=0 代表刚刚对数的读取完
所以在这将数计算出来
{
f=jisuanshu(sj.num1,sj.j1);
num[k]=f;
k++;j=0;f=0;
if(i!=0&&*(st+i)=='(')
{
printf("表达式错误1,请重新输入:\n");
longjmp(jmp,1);
}
}
if(*(st+i)=='(')
k1++;
//
k1
k2用来测试 (与)是否对称
else
if(*(st+i)==')')
k2++;
*(st1+m)=*(st+i);
m++;
i++;
z++;
// z
是用来计算连续读取不是数字的字符个数
}
}
if(z!=0)
biaodashi1(st,i,z);
if(k1!=k2)
{
printf("表达式错误2,请重新输入:\n");
longjmp(jmp,2);
}
if(j!=0)
//j!=0
表示 还有个数没有 被分离出来了 还没有被计算,因为如果最后1个是一个字符 那么 j 值是为0 的
{
f=jisuanshu(sj.num1,sj.j1);
num[k]=f;
}
*(st1+m)='\0';
//这个地方要给字符数组手动放上结束标志,编译器是不会帮组你给数组加上‘\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 a1,a2;int i,n,jx;
//这部分变量声名在这 主要是作用域 要求
几个函数都需要这么几个变量 ,在函数段里声名的话,不能起到传递数值的作用,这个地方还需细思量处理
char c,*pr;
int j_jisuan()
// 计算分为4个函数 j_jisuan() 计算 a+b+c+d 类型的
j_jisuan1()用来处理 ‘(’ 的情况,j_jisuan2() 用来处理‘)’的情况 和 jieguo 计算最后结果
{
// 和初始化 起始数据
int j_jisuan1();
//算法介绍:1.判断起始字符是否为‘(’
是 进入j_jisuan1() 开始运算。j_jisuan1()完成动作
‘(’入栈
while(*(st1+p_i)!='\0'){
//2.如果不是
‘(’
那么放入 1个数 和1个操作符号
判断字符是否为‘(’ 如果是 进入j_jisuan1()
如果不是那么放入操作数
进入j_jisuan()进行计算
n=pan(*(st1+p_i));
//遇到‘)’进入j_jisuan2()的 进行计算
大体流程如此
if(n!=3&&n!=4){
// 需要注意情况
(a+(。。。。。
)
(a+b*()) 和 a
(a)的情况
大致是说这么多
if(n>p->p1){
if(*(st1+p_i+1)!='('){
pushb(s,num[s_i]);
s_i++;
a1=popb(s);
a2=popb(s);
jg1=jisuan(*(st1+p_i),a1,a2);
pushb(s,jg1);
}
else
pusha(p,*(st1+p_i));
p_i++;
}
else{
a1=popb(s);
a2=popb(s);
c=popa(p);
jg1=jisuan(c,a1,a2);
pushb(s,jg1);
pusha(p,*(st1+p_i));
pushb(s,num[s_i]);
p_i++;
s_i++;
}
}
else if(n==3)
j_jisuan1();
else
j_jisuan2();
}
}
int j_jisuan2()
{
i=0;jx=0;
a1=popb(s);
a2=popb(s);
c=popa(p);
jg1=jisuan(c,a1,a2);
pushb(s,jg1);
popa(p);
p_i++;
pr=p->top1;
while((pr-p->base1)!=0){
pr--;
if(*pr=='('){
jx=1;
break;
}
i++;
}
if((p->top1-p->base1)==0){
if(*(st1+p_i)!='\0'){
pushb(s,num[s_i]);
pusha(p,*(st1+p_i));
s_i++;p_i++;
j_jisuan();
}
}
else if(i==1&&jx==1){
j_jisuan();
}
else if(i>1){
a1=popb(s);
a2=popb(s);
c=popa(p);
jg1=jisuan(c,a1,a2);
pushb(s,jg1);
j_jisuan();
}
else if(i==0&&jx==1)
{
if(*(st1+p_i)==')'){
popa(p);
p_i++;
}
if(*(st1+p_i)!='\0'){
pushb(s,num[s_i]);
pusha(p,*(st1+p_i));
s_i++;p_i++;
j_jisuan();
}
}
}
int j_jisuan1()
{
pusha(p,*(st1+p_i));
p_i++;
while(*(st1+p_i)!='\0'){
n=pan(*(st1+p_i));
if(n!=3&&n!=4){
pusha(p,*(st1+p_i));
p_i++;
pushb(s,num[s_i]);
s_i++;
if(*(st1+p_i)=='(')
j_jisuan1();
else{
pushb(s,num[s_i]);
s_i++;
j_jisuan();
}
}
else if(n==3)
j_jisuan1();
else{
j_jisuan2();
}
}
}
float jieguo()
{
init1(p);
init(s);
if(*(st1+p_i)=='(')
j_jisuan1();
else{
pusha(p,*(st1+p_i));
p_i++;
pushb(s,num[s_i]);
s_i++;
if(*(st1+p_i)=='(')
j_jisuan1();
else{
pushb(s,num[s_i]);
s_i++;
j_jisuan();
}
}
while(p->top1!=p->base1){
a1=popb(s);
a2=popb(s);
c=popa(p);
printf("%c\n",c);
jg1=jisuan(c,a1,a2);
pushb(s,jg1);
}
printf("%f\n",jg1);
}
int main()
{
char num4[20],num5[10],xy;
float zjg;
int cz;
st=num4;
st1=num5;
setjmp(jmp);
s=(struct b*)malloc(sizeof(struct b));
p=(struct a*)malloc(sizeof(struct a));
printf("请输入表达式:\n");
scanf("%s",st);
qufen();
jieguo();
printf("还要计算吗?y/n\n");
scanf("%c",&xy);
//---------->这个地方要等待我输入的,他不等我输入 就跑到
while(xy!='n')
//我前天用的个编译器不是这个样子的,哎 网上下载的绿色版VC++,很诡异
{
if(xy=='y'){
free(p);free(s);
while(st!='\0')
{
*st='\0';
st++;
}
while(st1!='\0')
{
st1='\0';
st1++;
}
for(i=0;i<10;i++){
num[i]=0;
}
longjmp(jmp,1);
}
else if(xy=='n')
exit(0);
else
{
printf("请输入:y 或者 n\n");
//----------->跑到了这 求 大牛帮忙 讲解下为什么,输入了 Y 一直都不按我想的走
scanf("%c",&xy);
//
------------->外 计算器 计算部分已经完工 还请 各位大神 找找BUG
呵呵
}
//--->网吧的机器怎么我写前面的后面的就给我删掉了,这机器弄不来,没法写注释就像前天下的个编译器
}
//一样的诡异。。。。怀恋我的电脑,怀念 linux下的 GDB调试
}
[
本帖最后由 zhu224039 于 2012-9-6 21:33 编辑 ]