2 zhang 09 11 zhang_09_11 于 2017.06.19 19:56 提问

解决一个计算器跳出循环

代码:
#include
#include
#include
#define N 100 //定义接收字符串大小
typedef struct StackNode
{
int num_ch; //数字和符号都用int存储
struct StackNode next;
} StackNode;
//创建一个链栈 注意我的栈最后一个元素无意义但必须存在 因为方便在表达式末尾进行操作
StackNode *CreatStackNode()
{
StackNode *q=(StackNode *)malloc(sizeof(StackNode));
if(q==NULL)return NULL;
q->num_ch =0;
q->next=NULL;
return q;
}
//直接给最后一个元素赋值 并新建一个无意义的结点作为最后元素
int push(StackNode *p,int num)
{
while(p->next!=NULL)
{
p=p->next;
}
p->num_ch=num;
StackNode *q=(StackNode *)malloc(sizeof(StackNode));
q->num_ch =0;
q->next=NULL;
p->next=q;
return 0;
}
// 最后一个无意义的直接free // 倒数第二个next置空,返回倒数第二的值
int Pop(StackNode *p)
{
int tmp;
if(p->next==NULL) return -1;//只有头,无值时无法Pop
while(p->next->next!=NULL)
{
p=p->next;
}
tmp=p->num_ch;
free(p->next);
p->num_ch = 0;
p->next = NULL;
return tmp;
}//获取栈顶元素
int GetTop(StackNode *p)
{
while(p->next->next!=NULL)
{
p=p->next;
}
return p->num_ch;
}
//判栈空 如果只剩一个结点(这是个无意义的) 那么就为空
int Empty(StackNode *p)
{
if(p->next==NULL) return 1;
return 0;
}
//显示栈的所有元素
void DispStack(StackNode *p)
{
if(p->next==NULL) return;//只有头,无值时无法Pop
while(p->next!=NULL)
{
printf("%d,",p->num_ch);
p=p->next;
}
putchar(10);
}
//计算int变量的长度 例如1234长度为4
int sum_int(int in)
{
int len=0;
while(in!=0)
{
len++;
in/=10;
}
return len;
}
// 符号优先级判断 返回: 1(opt1>opt2) -1(opt1<opt2) 0(opt1=opt2) 注意符号的ASSIC码:43(+) 45(-) 42(
) 47(/)
int opt_max(int opt1,int opt2)
{
if(42==opt1||47==opt1)
{
if(43==opt2||45==opt2)
{
return 1;
}
return 0;
}
else
{
if(42==opt2||47==opt2)
{
return -1;
}
return 0;
}
}
//计算a和b在mode符号的运算结果
int cal(int a,int b,int mode)
{
int re=-1;
switch(mode)
{
case 43:
re=a+b;
break;
case 45:
re=a-b;
break;
case 42:
re=a*b;
break;
case 47:
re=a/b;
break;
default:
break;
}
return re;
}
//计算表达式的值
int cal(char str)
{
int num1,num2,opt1,opt2;
StackNode *num,*opt;
num=CreatStackNode(); //创建数字栈
opt=CreatStackNode(); //创建符号栈
while(1)
{
if('\0'==*str) // 读到字符串末尾
{
//如果最后一个符号是
或/则会剩下三个数字和两个符号
//如果最后一个符号时+或-则会剩下两个数字和一个符号
//结果只是算两次和算一次的问题
opt1=GetTop(opt);
if((42==opt1)||(47==opt1))
{
num2=Pop(num);
num1=Pop(num);
opt2=Pop(opt);
push(num,cal(num1, num2, opt2));
}
num2=Pop(num);
num1=Pop(num);
opt2=Pop(opt);
num1=cal(num1, num2, opt2);
break;
}
else if('('==*str) // 读到(,注意进栈的时(的ASSIC码40
{
push(opt,(int)'(');
str++;
}
else if(')'==*str) // 只是判断)不进入栈
{
while(1) // 本循环会计算与)匹配的最近的(地方为之
{
if(40==GetTop(opt)) // 如果当前栈顶是(则弾栈退出
{
Pop(opt);
break;
}
else // 否则弾两个数字,一个符号进行运算
{
// 结果入操作数栈
num2=Pop(num);
num1=Pop(num);
opt2=Pop(opt);
push(num,cal(num1, num2, opt2));
}
}
str++;
}
else if(('9'>=*str)&&('0'<=*str)) // 如果取到数字则将数字进入栈
{
sscanf(str,"%d",&num1);
push(num,num1);
//将指针移动到当前数字到后面
str=str+sum_int(num1);
}
else // 取到一个符号
{
opt1=(int)*str++;
while(1)
{
if( (1==Empty(opt))||(40 == GetTop(opt)) ) // 如果栈不空则遇到(则进入取到的符号
{
// 为空时也要进栈
push(opt,opt1);
break;
}
else
{
//取出符号栈顶元素
opt2=GetTop(opt);
if(0<opt_max(opt1,opt2)) // 当前获取的符号优先级大于栈顶符号
{
// 则进栈
push(opt,opt1);
break;
}
else // 栈顶优先级高或者平级则
{
// 取两个数和栈顶符号进行运算
num2=Pop(num);
num1=Pop(num);
opt2=Pop(opt);
push(num,cal(num1,num2,opt2));
}
}
}
}
}
free(num);
free(opt);
return num1;
}
int main()
{
int flag=1;
char buf[N]={0};
printf("\t\t********************************$\n");
printf("\t\t* 欢迎您使用本计算器 \n");
printf("\t\t
*******************************$\n");
printf(" 作者:张治政\n");
printf("请输入一个运算式(eg:8+6*(9-3)+8/4注意括号为英文式的!):\n");
printf("当你想结束的时候输入一个纯数字就结束了!\n");
while(flag==1)
{
scanf("%s",buf);
if(getchar()=="0000")
{
flag=0;
}
printf("%s=%d\n",buf,cal(buf));
}
return 0;
}

1个回答

devmiao
devmiao   Ds   Rxr 2017.06.20 01:10
Csdn user default icon
上传中...
上传图片
插入图片