C语言笔记:算数表达式求值问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42124234/article/details/101542122

问题场景以及实现代码

问题描述:
完成不含括号的整数的加减乘除四则运算的长算式(含两个运算符)的求值,其中所有的中间结果均为整数。输入一行不含括号
的加减乘除四则运算的长算式,"="表示输入结束。输出有三种情况:
1、如果能够进行运算则输出运算结果
2、如果出现除以零的情况,输出Divided by 0
3、如果运算符不是加减乘除符号,则输出error

问题分析:
a,b,c均为整型数,op1和op2为加减乘除中的运算符,有多个运算符需要考虑运算符的优先级情况,所以设计了函数int Priority(char op),返回运算符op的优先级,用整数代表op的优先级,数的大小代表优先级的大小,其次判断运算符优先级之前,还需判断用户输入的运算符是否合法,故设计了函数int Isop(char ch),判断运算符优先级之后还要考虑除数是否为零的情况。(1)如果op1优先级大于op2优先级,则先计算a op1 b,这里多了一步,就是把a op1 b的结果赋值a,op2赋值op1,c赋值b,再计算剩余式子;(2)否则先计算b op2 c,将结果赋值给b,再计算剩余式子。剩余式子再统一计算a op1 b得到最终结果。

/*
问题描述:
完成不含括号的整数的加减乘除四则运算的长算式(含两个运算符)的求值,其中所有的中间结果均为整数。输入一行不含括号
的加减乘除四则运算的长算式,"="表示输入结束。输出有三种情况:
1、如果能够进行运算则输出运算结果
2、如果出现除以零的情况,输出Divided by 0
3、如果运算符不是加减乘除符号,则输出error 
*/
#include <stdio.h>
int Isop(char ch);//判断ch是否为运算符,是返回1,否则返回0 
int Priority(char op);//返回运算符op的优先级,整数大小代表优先级大小 
int Compute(int a,char op,int b);//返回a op b的计算结果 
int main(void)
{
 int a,b,c;//3个操作数 
 char op1,op2;//2个运算符
 printf("请输入格式为:\"a op1 b op2 c =\"(输入'='则是结束)\n"); 
 scanf("%d %c %d %c %d",&a,&op1,&b,&op2,&c);
 getchar();//接收等于号 
 if(!Isop(op1)||!Isop(op2))
 {
  printf("运算符输入错误!");
 }
 else
 {
  if(Priority(op1)>=Priority(op2))//先计算a op1 b,大于等于是因为四则运算在优先级相同的情况下,结合性是从左至右  
  {
   if(op1=='/'&&b==0)
   {
    printf("式子%d %c %d中除数为零!\n",a,op1,b);
    return 0;
   }
   a=Compute(a,op1,b);//a为计算完的a op1 b 
   op1=op2;//op1为op2 
   b=c;//b为c 
  }
  else//先计算b op2 c 
  {
   if(op2=='/'&&c==0)
   {
    printf("式子%d %c %d中除数为零!\n",b,op2,c);
    return 0;
   }
   b=Compute(b,op2,c);
  }
  if(op1=='/'&&b==0)//计算上面两种情况后剩余式子
  {
   printf("除数为零!");
   return 0;
  } 
  a=Compute(a,op1,b);//不管是先计算a op1 b还是b op2 c,剩下最后一步计算在前面两种情况中统一处理a op1 b 
  printf("长算式的结果为:\n");
  printf("%d",a);
  
 } 
 return 0;
}
int Isop(char ch)
{
 int flag;
 switch(ch)
 {
  case '+':
   flag=1;
   break;
  case '-':
   flag=1;
   break;
  case '*':
   flag=1;
   break;
  case '/':
   flag=1;
   break;
  default:
   flag=0;
   break;
 }
 return flag;
}
int Priority(char op)
{
 switch(op)
 {
  case '+'://多个case可共用一个执行语句 
  case '-'://多个case可共用一个执行语句 
   return 1;
  case '*':
  case '/':
   return 2; 
 }
}
int Compute(int a,char op,int b)
{
 switch(op)
 {
  case '+':
   return a+b;
  case '-':
   return a-b;
  case '*':
   return a*b;
  case '/':
   return a/b;
 }
}

运行结果:
在这里插入图片描述

进一步思考以及优化代码

思考:
前面的代码只能实现3个数两个运算符的计算,能不能不限制用户输入运算数和运算符的数量,任由用户输入一个长算式,然后程序计算结果?比如用户输入2+3*4/2-1=,然后程序计算输出结果。

问题分析:考虑到不定长的算数表达式,应该用循环实现(不断计算a op1 b,前提是做好操作数和运算符的转换),在 a op1 b op2 c表达式的基础上实现,式子从0+b开始(先初始化a=0,op1=’+’,输入b),b为用户输入的第一个运算数,然后循环执行:输入op2,如果op2为’=’,式子输入结束,否则再输入c,使算术式变长,接着就变为上面代码的a op1 b op2 c的计算,每次接收的字符均为op2,接收的操作数均为c,根据运算符优先级,无论先计算op1还是op2,结果均保证没计算的式子为a op1 b,直到op2为’=’,式子结束。

/*
问题描述:
完成不含括号的整数的加减乘除四则运算的长算式(含两个运算符)的求值,其中所有的中间结果均为整数。输入一行不含括号
的加减乘除四则运算的长算式,"="表示输入结束。输出有三种情况:
1、如果能够进行运算则输出运算结果
2、如果出现除以零的情况,输出Divided by 0
3、如果运算符不是加减乘除符号,则输出error 
*/
#include <stdio.h>
int Isop(char ch);//判断ch是否为运算符,是返回1,否则返回0 
int Priority(char op);//返回运算符op的优先级,整数大小代表优先级大小 
int Compute(int a,char op,int b);//返回a op b的计算结果 
int main(void)
{
 int a,b,c;//3个操作数 
 char op1,op2;//2个运算符
 printf("输入表达式=结束\n");
 a=0;
 op1='+';
 scanf("%d",&b);
 while(1)
 {
  op2=getchar();
  if(op2=='=')
  {
   break;
  }
  else
  {
   scanf("%d",&c);
  }
  if(!Isop(op2))
  {
   printf("运算符输入错误!");
   return 0;
  }
  if(Priority(op1)>=Priority(op2))//先计算a op1 b ,大于等于是因为四则运算在优先级相同的情况下,结合性是从左至右 
  {
   if(op1=='/'&&b==0)
   {
    printf("式子%d %c %d中除数为零!\n",a,op1,b);
    return 0;
   }
   a=Compute(a,op1,b);//a为计算完的a op1 b 
   op1=op2;//op1为op2 
   b=c;//b为c 
  }
  else//先计算b op2 c 
  {
   if(op2=='/'&&c==0)
   {
    printf("式子%d %c %d中除数为零!\n",b,op2,c);
    return 0;
   }
   b=Compute(b,op2,c);
  }
 }
 if(op1=='/'&&b==0)//计算上面两种情况后剩余式子
 {
  printf("除数为零!");
  return 0;
 } 
 a=Compute(a,op1,b);//不管是先计算a op1 b还是b op2 c,剩下最后一步计算在前面两种情况中统一处理a op1 b 
 printf("长算式的结果为:\n");
 printf("%d",a);
 return 0;
}
int Isop(char ch)
{
 int flag;
 switch(ch)
 {
  case '+':
   flag=1;
   break;
  case '-':
   flag=1;
   break;
  case '*':
   flag=1;
   break;
  case '/':
   flag=1;
   break;
  default:
   flag=0;
   break;
 }
 return flag;
}
int Priority(char op)
{
 switch(op)
 {
  case '+'://多个case可共用一个执行语句 
  case '-'://多个case可共用一个执行语句 
   return 1;
  case '*':
  case '/':
   return 2; 
 }
}
int Compute(int a,char op,int b)
{
 switch(op)
 {
  case '+':
   return a+b;
  case '-':
   return a-b;
  case '*':
   return a*b;
  case '/':
   return a/b;
 }
}

运行结果:
在这里插入图片描述
解释:
算术表达式:2+3*4/2-1,每次计算的过程为:

  • 0+2+3
  • 2+3*4
  • 2+12/2
  • 2+6-1

总之都回归到a op1 b op2 c的形式计算。

参考书籍《C语言从入门到项目实战》 王一萍等编著

猜你喜欢

转载自blog.csdn.net/weixin_42124234/article/details/101542122
今日推荐