请选择 进入手机版 | 继续访问电脑版

计算化学公社

 找回密码
 现在注册!
查看: 486|回复: 6

[C/C++] 请问大拿这道题该怎么写?

[复制链接]

467

帖子

2

威望

2792

eV
积分
3299

Level 5 (御坂)

发表于 2019-9-18 19:03:54 | 显示全部楼层 |阅读模式
怎么用C++实现下面这道题?
写一个计算器,支持三个运算数。
比如用户输入 2 * 3 + 2,应输出:8
注意要保证乘除先运算。没有括号。



565

帖子

0

威望

1018

eV
积分
1583

Level 5 (御坂)

发表于 2019-9-18 20:50:46 来自手机 | 显示全部楼层
首先parse输入字符串为5个fields,第1,3,5个转为数字a,b,c,第2,4个是运算符x,y。因为一共只有两个运算,所以很容易比较出先算axb还是先算byc

56

帖子

0

威望

158

eV
积分
214

Level 3 能力者

发表于 2019-9-19 10:42:30 | 显示全部楼层
(1) 先将a保存在一个数组中,然后读入符号
(2) 判断符号是加减还是乘除
      如果是乘除:直接运算数组最后一位与新加入数字的乘积然后替换数组最后一位
      如果是加减:将新加入的数字添加到数组最后
(3) 全部读取完毕后累加整个数组

以你的题目为例,数组如下一步步变化:
[2]
[6]
[6,2]

以1+2*3+4*5为例:
[1]
[1,2]
[1,6]
[1,6,4]
[1,6,20]
上海交通大学计算化学与分子生物信息学实验室
Shanghai JiaoTong University
Computational Chemistry and Molecular Bioinformatics Laboratory

CCMBI of SJTU

132

帖子

0

威望

751

eV
积分
883

Level 4 (黑子)

发表于 2019-9-19 11:13:14 | 显示全部楼层
就加减和乘除两个优先级的话你压个栈就好了啊。加减就压栈,乘除就弹出上一个,算数,再压进去。然后最后再把栈内元素累加。
哦你就算仨数,那算了。

1651

帖子

3

威望

6087

eV
积分
7798

Level 6 (一方通行)

Ab Initio Amateur

发表于 2019-9-20 10:07:55 | 显示全部楼层
存3个数字和2个足矣,能计算任意长度的计算。这里用python写了个草稿在上面加了注释。C++版本和Fortran90版本放在附件里面,尽管编程语言不同编程的思想没啥差别。当然python确实有更简单的做法,当然最简单的大概就是exec或ast.literal_eval了,那也就没啥好讨论的了。
  1. #作者:卡开发发
  2. #日期:2019-9-20
  3. #计算加减乘除


  4. #给定a、b两个数和当中的计算符号,返回计算结果。
  5. def calc(a,string,b):
  6.         if string=='+':
  7.                 return a+b
  8.         if string=='-':
  9.                 return a-b
  10.         if string=='*':
  11.                 return a*b
  12.         if string=='/':
  13.                 return a/b

  14. #键盘输入获取计算的表达式。
  15. string=input('input the expression:')
  16. #保存三个数和两个符号,
  17. #例如a+b*c会被保存为tmp=[a,b,c],sign=['+','*']。
  18. tmp=[0,0,0]
  19. sign=['+','+']

  20. #遍历所输入的字符串
  21. for i in range(len(string)):
  22.         s=string[i]
  23.         #遇到数字就x10+新的数字,这样就将连续的数字构成的字符数组转化为数字,
  24.         #即'abc..'=str(10*(10*a+b)+c...)
  25.         #通过ASCII来判断是否为数字。
  26.         if ord(s)>=48 and ord(s)<=57:
  27.                 tmp[2]=float(tmp[2]*10+ord(s)-48)
  28.         #遇到符号就对前面三个数和两个符号进行计算。
  29.         if s=='*' or s=='/'or s=='+' or s=='-':
  30.                 #如果第二个符号是乘除号,直接计算这乘法,
  31.                 #这样就相当于将tmp[1]和tmp[2]还有sign[1]合并为一个新的tmp[2]。
  32.                 #例如a+b*c+d...,表示为tmp=[a,b,c],sign=['+','*'],
  33.                 #现在遇到字符是第三个符号'+',则计算b*c,
  34.                 #计算后的结果就变成了tmp=[a,a,b*c],sign=['+','+']。
  35.                 if sign[1]=='*' or sign[1]=='/':
  36.                         tmp[2]=calc(tmp[1],sign[1],tmp[2])
  37.                         tmp[1]=tmp[0]
  38.                         sign[1]=sign[0]
  39.                 else:
  40.                         #如果两个符号都是加减号,直接计算第一个加减法,
  41.                         #这样就相当于将tmp[0]和tmp[1]还有sign[0]合并为一个新的tmp[1]。
  42.                         #例如a+b+c*d...,表示为tmpp=[a,b,c],sign=['+','+'],
  43.                         #现在遇到字符是第三个符号'*',则计算a+b,
  44.                         #计算后结果变成tmp=[a,a+b,c],sign=['+','+']。
  45.                         if (sign[1]=='+' or sign[1]=='-') and \
  46.                         (sign[0]=='+' or sign[0]=='-'):
  47.                                 tmp[1]=calc(tmp[0],sign[0],tmp[1])
  48.                 #扔掉tmp[0]和sign[0],
  49.                 #tmp[2]设置为0用来存放新的数字,
  50.                 #sign[1]用来存放当前读取到的符号。
  51.                 tmp[0]=tmp[1]
  52.                 tmp[1]=tmp[2]
  53.                 tmp[2]=0
  54.                 sign[0]=sign[1]
  55.                 sign[1]=s

  56. #读取到字符串末尾后,表达式就会变成三个数的运算。
  57. #如果加号在前面,如a+b*c,先计算b*c,其余情况按照顺序计算。
  58. if sign[0]=='+' or sign[0]=='-':
  59.         result=calc(tmp[0],sign[0],calc(tmp[1],sign[1],tmp[2]))
  60. else:
  61.         result=calc(calc(tmp[0],sign[0],tmp[1]),sign[1],tmp[2])
  62. #输出计算结果。
  63. print(string+'='+str(result))
复制代码
calculator.f90 (1.18 KB, 下载次数: 1)
满招损,谦受益。热衷于理论和方法研究水平不高但欢迎讨论。

565

帖子

0

威望

1018

eV
积分
1583

Level 5 (御坂)

发表于 2019-9-20 12:19:15 来自手机 | 显示全部楼层
卡开发发 发表于 2019-9-20 10:07
存3个数字和2个足矣,能计算任意长度的计算。这里用python写了个草稿在上面加了注释。C++版本和Fortran90版 ...

还得考虑输入数字可能是浮点数和负数吧?

1651

帖子

3

威望

6087

eV
积分
7798

Level 6 (一方通行)

Ab Initio Amateur

发表于 2019-9-20 12:51:20 | 显示全部楼层
本帖最后由 卡开发发 于 2019-9-20 13:19 编辑
granvia 发表于 2019-9-20 12:19
还得考虑输入数字可能是浮点数和负数吧?

负数不影响,浮点数的话就把读取数字部分做一下处理就行了,没有多复杂。22行下面:
  1. sign=['+','+']
  2. frac=False
  3. frac_len=0
复制代码
30行下面:
  1.     if ord(s)>=48 and ord(s)<=57 or s=='.':
  2.         if s=='.':
  3.             frac=True
  4.             s='0'
  5.         if not frac:
  6.             tmp[2]=float(tmp[2]*10+ord(s)-48)
  7.         else:
  8.             tmp[2]=float(tmp[2]+(ord(s)-48)/10**frac_len)
  9.             frac_len+=1
复制代码
57行下面:
  1.         tmp[2]=0
  2.         frac=False
  3.         frac_len=0
复制代码

其他语言的代码修改思路是一样的,就不再写一遍了。


满招损,谦受益。热衷于理论和方法研究水平不高但欢迎讨论。
您需要登录后才可以回帖 登录 | 现在注册!

本版积分规则

手机版|北京科音自然科学研究中心|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949-1号 )

GMT+8, 2019-10-14 22:21 , Processed in 0.194660 second(s), 26 queries .

快速回复 返回顶部 返回列表