C++程序设计语言(特别版) -- 一个桌面计算器

前言

  • 这里要介绍各种语句和表达式,将通过一个桌面计算器的程序做些事情,该计算器提供四种座位浮点数的中缀运算符的标准算术运算。
  • 这个计算器由四个部分组成:一个分析器,一个输入函数,一个符号表和一个驱动程序。

分析器

program:ENDexpr_list END //END表示输入结束 expr_list: expression PRINT // PRINT表示分号 expression PRINT expr_list expression: expression + term expression - term term term: term / primary term * primary primary primary: NUMBER NAME NAME = expression - primary (expression)
  • 语法分析器采用通常的递归下降的风格。终结符由词法分析程序get_token()识别,而非终结符由语法分析函数expr(),term()和prim()识别。一旦一个表达式的两个运算对象都知道,就立即对这个表达式求值。
  • 个人觉得分析器就像是定义程序能接受什么输入,而这里采用递归的形式,例如program代表程序,program可以接受END符号或者expr_list END,而expr_list又继续递归下去可以由其他的组成,直到可以得到一个结束情况。

总代码

#include<iostream>
#include<string> #include<map> #include<cctype> using namespace std; // 将token用他们的字符所对应的整数表示,这样做既方便有效, // 又能帮助使用排错系统的人。 enum Token_value { NAME, NUMBER, END, PLUS='+', MINUS='-', MUL='*', DIV='/', PRINT=';', ASSIGN='=', LP='(', RP=')', }; Token_value curr_tok = PRINT; double expr(bool); double term(bool); double prim(bool); Token_value get_token(); double error(const string&); map<string, double> table; int no_of_errors; int main() { table["pi"] = 3.1415924535; table["e"] = 2.178; while(cin) { get_token(); if(curr_tok == END) break; if(curr_tok == PRINT) continue; cout<<expr(false)<<'\n'; } return no_of_errors; } // 每个分析器都有一个bool参数, // 指明该函数是否需要调用get_token()去取得下一个参数 // expr处理加减,一直到不是加减返回left double expr(bool get) { double left = term(get); for(;;) { switch (curr_tok){ case PLUS: left += term(true); break; case MINUS: left += term(true); break; default: return left; } } } // 函数term处理乘除,采用的方式与expr()处理方法一样 double term(bool get) { double left = prim(get); for(;;) { switch (curr_tok){ case MUL: left *= prim(true); break; case DIV: if (double d = prim(true)) { left /= d; break; } return error("divide by 0"); default: return left; } } } double number_value; string string_value; // prim处理初等项的方式很像expr和term double prim(bool get) { if (get) get_token(); switch(curr_tok) { case NUMBER: { double v = number_value; get_token(); return v; } case NAME: { double& v = table[string_value]; if (get_token() == ASSIGN) v = expr(true); return v; } case MINUS: return -prim(true); case LP: { double e = expr(true); if (curr_tok != RP) return error(" ) expected"); get_token(); return e; } default: return error("primary expected"); } } Token_value get_token() { char ch; do { // 低级输入,改进输入 if(!cin.get(ch)) return curr_tok = END; } while(ch != '\n' && isspace(ch)); switch(ch) { case 0: return curr_tok=END; case '\n': return curr_tok=PRINT; case '+': case '-': case '*': case '/': case ';': case '(': case ')': case '=': return curr_tok = Token_value(ch); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': cin.putback(ch); cin>>number_value; return curr_tok = NUMBER; default: if (isalpha(ch)) { string_value = ch; while(cin.get(ch) && isalnum(ch)) string_value.push_back(ch); cin.putback(ch); return curr_tok = NAME; } error("bad token"); return curr_tok = PRINT; } } double error(const string& s) { no_of_errors ++; cerr<<"error: "<<s<<'\n'; return 1; }

扩展

  • 自己的代码只是简单的拼接,这里发现一个更好的博客。

转载于:https://www.cnblogs.com/zhengxingpeng/p/6685763.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/416952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(2364):图片的上传

message.vue <template><view><button type"primary" click"chooseImg">上传图片</button><image v-for"item in imgArr" :src"item" mode""></image></view> </template>…

superset docker方式安装

superset是优秀的数据可视化开源项目&#xff0c;为用户提供了丰富的图表视觉效果&#xff0c;基于python开发。但仅可以以图表、表格形式展示结果&#xff0c;不支持页面组装等高级BI功能。 准备环境docker 然后执行命令 docker pull amancevice/superset docker run --det…

※交换排序(1)——快速排序(quick sort)

快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为&#xff1a; 从序列中挑出一个元素&#xff0c;作为"基准"(pivot). 把所有比基准值小的元素放在基准前面&#xff0c;所有比基准值大的元素放在基准的后面&#xff08;相同的数可以到任…

前端学习(2365):图片的预览

message.vue <template><view><button type"primary" click"chooseImg">上传图片</button><image v-for"item in imgArr" :src"item" click"previewImg(item)"></image></view>…

superset 图标调整

superset docker方式安装 系统为debian 9 安装路径为 /usr/local/lib/python3.6/site-packages/superset/ web页面左上角图标路径为&#xff1a; static/assets/images/superset-logo2x.png 采用Flask框架 页面在views/中&#xff0c;core.py中 #欢迎页面 expose(/welco…

第五周思维导图

转载于:https://www.cnblogs.com/java1765415329/p/6686733.html

superset 时区问题Timestamp subtraction must have the same timezones or no timezones

superset绑定数据源后&#xff0c;切换到图表展示时报错&#xff1a; Timestamp subtraction must have the same timezones or no timezones File "/usr/local/lib/python3.6/site-packages/superset/utils/core.py", line 362, in datetime_to_epoch return (dtt…

使用Kotlin开发Android应用 - 环境搭建 (1)

一. 在Android Studio上安装Kotlin插件 按快捷键Command, -> 在Preferences界面找到Plugins -> 点击Browse repositories ... -> 输入Kotlin -> 安装Kotlin (老版本需要安装 Kotlin 和Kotlin Extensions For Android两个插件, 最新版本的Kotlin插件包含了Android E…

前端学习(2367):两种方式导航跳转和传参

<template><view><button type"primary" click"chooseImg">上传图片</button><image v-for"item in imgArr" :src"item" click"previewImg(item)"></image><navigator url"../…

sqlserver启用登陆审计

客户端管理工具进入后&#xff1a;安全性——审核——新建审核——审核目标&#xff08;就是存储位置&#xff09;选application log&#xff08;windows系统应用日志&#xff09;或者选File&#xff08;文件目录中会产生一堆日志文件&#xff0c;设置最大滚动更新文件数、最大…

java基础——equals及==的区别

①数值比较【必须为整数&#xff0c;小数因为精度问题不能通过这个比较&#xff0c;只能依靠d1-d2<0.0000000001这样的比较两者的不同】&#xff0c;值相等就行。 ②引用比较&#xff0c;引用的对象有父子关系或者是同一类的才能比较&#xff0c;只有当指向同一个引用才相等…

前端学习(2368):编程式导航

<template><view><button type"primary" click"chooseImg">上传图片</button><image v-for"item in imgArr" :src"item" click"previewImg(item)"></image><navigator url"../…

centos7 firewall防火墙实现映射其他机器的端口

vi /etc/sysctl.conf 增加一行 net.ipv4.ip_forward 1 使上述修改生效 sysctl -p firewall-cmd --add-port5432/tcp --permanent #开放端口 firewall-cmd --add-forward-portport5432:prototcp:toaddr10.0.197.189:toport5432 --permanent #添加端口映射 10.0.197.189的54…

Navicat Premium 未保存和已执行SQL存储位置

未保存备份存放目录地址&#xff1a; C:\Users\{登录用户名}\Documents\Navicat\MySQL\servers\{MySQL连接名称}\{数据库名称} SQL执行历史文件地址&#xff1a; C:\Users\{登录用户名}\Documents\Navicat\Premium\logs\LogHistory.txt

正则表达式之反向引用

1.概述 捕获组捕获到的内容&#xff0c;不仅可以在正则表达式外部通过程序进行引用&#xff0c;也可以在正则表达式内部进行引用&#xff0c;这种引用方式就是反向引用。要了解反向引用&#xff0c;首先要了解捕获组&#xff0c;关于捕获组&#xff0c;参考 正则基础之——捕获…

MySQL 表一列逗号分隔字段,按逗号切割

直接查询 ---切割前 select id,content from test_split; 1 12,13,14 2 21,25 3 33 --切割后 1 12 1 13 1 14 2 21 2 25 3 33 --执行sql SELECT a.id,SUBSTRING_INDEX(SUBSTRING_INDEX(a.content,,,b.help_topic_id1),,,-1) AS num FROM test_split a join mys…

jquery template.js前端模板引擎

作为现代应用&#xff0c;ajax的大量使用&#xff0c;使得前端工程师们日常的开发少不了拼装模板&#xff0c;渲染模板 在刚有web的时候&#xff0c;前端与后端的交互&#xff0c;非常直白&#xff0c;浏览器端发出URL&#xff0c;后端返回一张拼好了的HTML串。浏览器对其进行渲…