代码解释都用注释写在旁边了

解题思路:
一步步来就没问题

注意事项:
上题过了这题就一遍过;

可能要有的:

①忽略前导0 如009+001-002这样的

②直接回车也输出0

参考代码:

#include<stdio.h>
const int N=1e4+5;//上题用的常数
inline void swap(int &a,int &b){int c=a;a=b;b=c;}//交换
inline void deal(int *a)//把009变成900的左右颠倒函数
{ int len=a[0]>>1;//移位运算符,相当于/2
  for(int i=1;i<=len;++i)swap(a[i],a[a[0]+1-i]);
}
void out(int *a){for(int i=a[0]?a[0]:1;i>0;--i)printf("%d",a[i]);/*putchar(10);*/}//输出结果的函数
inline void add(int *a,int *b)//高精度加法
{ a[0]=(a[0]>b[0]?a[0]:b[0])+1;//取两个长度中较长的并且+1,因为最高的位数在相加时可能会进1  如9+1=10
  b[0]=0;//清理数组
  for(int i=1;i<=a[0];++i)
  { a[i]+=b[i];
    b[i]=0;//顺便清理数组
    if(a[i]>9)a[i]-=10,++a[i+1];//进位
  }
  while(a[0]>1&&!a[a[0]])--a[0];//至少保留1位,同时去除前导0
}
inline void subtraction(int *a,int *b)
{ a[0]=a[0]>b[0]?a[0]:b[0];//从上面抄下来的。因为是减法没有+1也行
  b[0]=0;//清理数组
  for(int i=1;i<=a[0];++i)
  { a[i]-=b[i];
    b[i]=0;//顺便清理数组
    if(a[i]<0)a[i]+=10,--a[i+1];//借位
  }
  while(a[0]>1&&!a[a[0]])--a[0];//至少保留1位,同时去除前导0
}
inline void yunsuan(const char &op,int *a,int *b)
{ deal(b);//运算前先处理b数组
  switch(op)//根据上次的运算符决定进行什么运算
  { case('+'):add(a,b);return;
    case('-'):subtraction(a,b);return;
    default:return; 
  }
}
inline bool check(const char &k,char &op,int *a,int *b)//看看这个是运算符还是数字还是别的
{ switch(k)
  { case('+'):yunsuan(op,a,b),op=k;return 1;//运算在前面是因为op是上次没算的运算符。  实际上1+1-1 是读到减号的时候才开始算加号的
    case('-'):yunsuan(op,a,b),op=k;return 1;
    case('*'):yunsuan(op,a,b),op=k;return 1;
    case('/'):yunsuan(op,a,b),op=k;return 1;
    case('^'):yunsuan(op,a,b),op=k;return 1;
    default:return 0;
  }//1是运算符,0不是
}
int a[N],b[N];//a是结果数组,b是临时数组,a[0],b[0]为数组长度
char op,k;//op是上次的运算符,k是用来读字符的变量
bool key,mark;//key用于去除前导0,mark判断a有没有被处理过,处理过才能用out()输出
main()
{ while(k!=-1&&k!=10&&~(k=getchar()))//如果读取到回车或EOF就退出
  { if(check(k,op,a,b))//看看这个是运算符还是数字还是别的
    { deal(a);
      key=0;//每次读取数字都要关闭,说明还没处理前导0
      mark=1;//处理过a数组的标志
      while(~(k=getchar())&&k!=10)//不读取EOF和回车
      if(check(k,op,a,b))key=0;//读取的是个运算符,说明要接受新数字,将key关闭
      else if(k>=48&&k<=57)//如果是数字
             if(key)b[++b[0]]=k-48;//如果不是第一次碰到非0就记录
             else if(k!=48)b[++b[0]]=k-48,key=1;//第一次碰到非0的数字记录,并且把key打开
    }
    else if(k>=48&&k<=57)//如果是数字
           if(key)a[++a[0]]=k-48;//如果不是第一次碰到非0就记录
           else if(k!=48)a[++a[0]]=k-48,key=1;//第一次碰到非0的数字记录,并且把key打开
  } 
  if(!mark)deal(a);//没处理就处理一下
  yunsuan(op,a,b);//最后没有运算符,不会自动进行计算,手动补上一步
  out(a);//输出
}


点赞(0)
 

0.0分

1 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论