软件工程实践第一次作业:前后端分离计算器系统

发布时间:2026/10/2 17:33:46

软件工程实践第一次作业:前后端分离计算器系统 软件工程实践第一次作业前后端分离计算器系统Course for This Assignment软件工程实践Assignment Requirements前后端分离计算器系统Objectives of This Assignment掌握前后端分离架构、接口开发、数据库持久化、系统设计与博客文档撰写姓名 / 学号吴正杨 / 24127167Other ReferencesCSDN社区作业文档仓库与代码规范链接Frontend Repository:https://github.com/Wzy13850918263/24127167_calculator_frontendBackend Repository:https://github.com/Wzy13850918263/24127167_calculator_backendFrontend Code Standard:https://github.com/Wzy13850918263/24127167_calculator_frontend/blob/main/codestyle.mdBackend Code Standard:https://github.com/Wzy13850918263/24127167_calculator_backend/blob/main/codestyle.md目录PSP 表格需求分析系统设计与架构功能成品展示关键代码解释遇到的问题与学习总结1. PSP 表格PSP2.1Personal Software Process Stages预估耗时分钟实际耗时分钟Planning计划3025· Estimate· 估计任务工时1010Development开发320360· Analysis· 需求分析3025· Design· 系统设计、API、数据库设计4045· Design Review· 设计复审1515· Coding Standard· 代码规范 codestyle 编写1515· Coding· 后端编码逆波兰 数据库接口90110· Coding· 前端页面编码6070· Test· 测试所有功能与异常用例3035Reporting报告150160· Test Report· 测试截图收集4040· Postmortem· 总结、博客撰写90100Total总计5005452. 需求分析本作业要求实现一个前后端完全分离的计算器系统。核心硬性要求所有计算逻辑必须在后端完成。前端只负责收集用户输入的表达式字符串通过 HTTP POST 发给后端禁止前端算好再把结果发给后端存储。计算历史持久化在后端数据库刷新页面历史不能丢失不允许使用浏览器 localStorage。支持复合表达式运算符优先级、括号、小数、一元正负号如-5、3*-2。异常处理非法表达式、除零错误要返回友好提示。严禁使用 eval / exec直接执行用户输入。前端、后端分别建立独立 GitHub 仓库均含 README.md 与 codestyle.md。支持按 id 删除指定历史记录。技术选型后端Python FastAPI轻量、自动生成接口文档数据库SQLite零配置、文件型适合课程作业前端原生 HTML CSS JavaScript无框架专注前后端通信表达式计算手写逆波兰后缀表达式算法不使用 eval3. 系统设计与架构3.1 整体架构浏览器前端 (index.html) │ HTTP / JSON ▼ FastAPI 后端 (main.py) │ ├── 表达式解析模块词法分析 → 中缀转后缀 → 后缀求值 ├── 历史记录模块SQLAlchemy ORM 增删查 ▼ SQLite 数据库 (calculator.db)验证方式停掉后端服务后前端按钮还能点但无法得到任何计算结果说明计算确实发生在后端。3.2 API 接口设计接口方法作用请求 / 返回/api/calculatePOST提交表达式并计算、写入历史请求{expression:(12)*3}返回{success:true,result:9.0}/api/historyGET获取全部历史按时间倒序返回{history:[...]}/api/history/{id}DELETE删除指定 id 的历史记录返回{success:true,msg:删除成功}成功响应样例{success:true,expression:(12)*3,result:9.0}错误响应样例{success:false,message:除数不能为零}3.3 数据库表设计表名calc_history字段类型说明idInteger 主键自增expressionString用户输入的表达式resultFloat计算结果created_atDateTime计算时间默认当前时间3.4 表达式计算模块思路为遵守禁止 eval的要求我用经典的栈 逆波兰三步走词法分析 tokenize把字符串拆成 token 列表特别处理一元负号——当-出现在开头或运算符后时标记为u-一元负号与二元减法区分开。中缀转后缀 infix_to_postfix用运算符栈按优先级u-* / -把中缀表达式转成后缀表达式。后缀求值 calc_postfix遍历后缀表达式遇到数字入栈遇到运算符弹出两个数计算后把结果入栈。除零时抛出ZeroDivisionError。4. 功能成品展示说明以下截图按顺序上传对应我本地博客截图文件夹中的图片4.1 主界面简洁的计算器界面上方为表达式输入框与结果区下方为按钮区最下方为计算历史列表。4.2 基础四则运算输入128后端返回结果 20。4.3 小数运算输入2.5*4结果 10。4.4 括号与运算符优先输入(12)*3结果 9验证括号改变优先级正确。4.5 一元负号输入3*-2结果 -6验证运算符后接负号正确识别。4.6 除零错误处理输入5/0前端显示错误除数不能为零该错误不会写入历史。4.7 非法表达式处理输入括号不匹配的(12提示括号不匹配。4.8 计算历史列表所有成功计算的记录都持久化在后端数据库按时间倒序展示。4.9 刷新页面历史不丢失刷新页面后前端重新调用/api/history从数据库拉取历史依然存在。4.10 删除历史记录点击某条记录的删除按钮后端从数据库真实删除前端列表同步刷新。5. 关键代码解释5.1 前端提交表达式并展示结果前端不做任何计算只把表达式 POST 给后端再根据返回的success字段决定展示结果还是错误信息asyncfunctionsubmitCalc(){constexprinputDom.value.trim();constrespawaitfetch(BACKEND_URL/api/calculate,{method:POST,headers:{Content-Type:application/json},body:JSON.stringify({expression:expr})});constdataawaitresp.json();if(data.success){resultDom.innerText结果 data.result;}else{resultDom.innerText错误data.message;}loadHistory();// 计算后刷新历史}5.2 后端计算接口统一异常处理后端用 try/except 分别捕获除零和其他表达式错误返回统一的 JSON 结构无论成功失败都关闭数据库会话app.post(/api/calculate)defcalc(req:CalcRequest):dbSessionLocal()try:rescalculate_expression(req.expression)recordCalcHistory(expressionreq.expression,resultres)db.add(record);db.commit();db.refresh(record)return{success:True,expression:req.expression,result:res}exceptZeroDivisionError:return{success:False,message:除数不能为零}exceptExceptionase:return{success:False,message:表达式错误str(e)}finally:db.close()5.3 核心一元负号识别词法分析时判断-是一元还是二元这是支持3*-2、-59的关键ifc-:ifi0orexpr[i-1]in(-*/:tokens.append(u-)# 一元负号i1continuetokens.append(c)# 二元减法5.4 历史记录的删除删除接口按 id 查询查不到返回 404查到则从数据库删除并提交app.delete(/api/history/{hid})defdel_history(hid:int):dbSessionLocal()itemdb.query(CalcHistory).filter(CalcHistory.idhid).first()ifnotitem:raiseHTTPException(status_code404,detail记录不存在)db.delete(item);db.commit();db.close()return{success:True,msg:删除成功}6. 遇到的问题与学习总结前后端跨域问题一开始用浏览器直接打开index.htmlfile 协议fetch 后端接口被浏览器 CORS 策略拦截。解决方法是在 FastAPI 里加上CORSMiddleware允许跨域。一元负号的识别最容易出错的是3*-2和开头的-5。一开始没区分一元负号和二元减号导致解析栈里数字和运算符数量对不上。后来在词法分析阶段根据-前面的字符判断标记成独立的u-token 并给最高优先级解决。除零与非法表达式不能让服务崩溃用 try/except 在接口层兜底把异常转成友好的 JSON 错误返回而不是让后端 500。历史持久化的验证一开始容易把历史存在前端内存里刷新就没了。这次每次计算后都写 SQLite、每次进页面都重新拉/api/history确保刷新和重启后端后数据都在。收获真正理解了前后端分离——前端是哑巴只负责展示和发请求后端才是大脑负责计算和存数据。也第一次完整走了一遍写代码 → git 提交 → push 到 GitHub → 写文档的工程流程。后续可优化方向增加科学计算三角函数、开方历史记录分页用 ngrok 把后端暴露到公网方便他人在线访问
延伸阅读

更多相关文章

2026/10/2 17:33:46

卤牛头生产厂家靠谱商家测评排名:不踩坑的源头工厂实力分析

卤牛头行业入门科普:选源头工厂前必须理清的核心逻辑作为日常餐饮、熟食门店的高频选品,卤牛头凭借厚实的肉感、浓郁的卤香,成为很多线下商户的核心引品。不过很多新手商家在寻找供货源头时容易陷入认知盲区:卤牛头的品质核心取决…

2026/10/2 17:33:46

CUDA 与 N 卡驱动安装

CUDA 与 N 卡驱动安装系列第 1 篇。刚拿到 N 卡想本地跑 AI,却不知道驱动、CUDA Toolkit、cuDNN 到底要装哪几个?本篇把"CUDA 安装 / N 卡驱动"这件事一次讲透:先 nvidia-smi 看家底,再按决策树装驱动,判断 …

2026/10/2 17:33:46

我要输入 [特殊字符],Windows 却让我先学会英语

我要输入 💩,Windows 却让我先学会英语 一个被 Win . 恶心了很多年的人,最后自己写了个工具的故事。 事情是这样的 那天我想在QQ群里发个 💩,来表达我的难以形容的心情与态度。啊,一坨正在微笑的💩!这坨&…

2026/10/2 18:38:49

Python旅游网站开发:Flask+MySQL管理后台源码实战

简介:一套基于Flask和MySQL的旅游旅行网站及管理后台项目源码,面向计算机专业毕业设计、课程设计或希望入门Python Web开发的读者。项目围绕旅游景点展示、线路推荐、用户登录注册、后台数据管理等典型业务展开,结构清晰,适合作为…

2026/10/2 18:38:49

Redis接入AI能力实战:向量检索与语义缓存深度解析

1. 从一条更新日志说起:Redis 接入 AI 到底意味着什么 前几天刷技术社区,看到一条消息说 Redis 正式接入了 AI 能力。第一反应是:这又是哪个营销号在搞标题党?Redis 一个内存数据库,跟 AI 能扯上什么关系?但…

2026/10/2 18:38:49

PostgreSQL 12.0源码编译安装实战:CentOS 7.9从依赖到systemd管理

1. 部署前想清楚的三件事:版本、方式、目录PostgreSQL 12.0是2019年10月发布的版本,放在今天看并不算新,最新社区版已经迭代到17甚至更高。但现实中需要部署它的项目一点不少:很多国产化数据库改造项目、存量业务系统的迁移验收、…

2026/10/2 18:38:49

Windows下用WSL2部署OpenClaw个人AI助理的完整指南

说实话,第一次在Windows上跑OpenClaw的时候,我踩的坑比想象中多得多。这个项目本身定位就是“个人AI助理”,能把聊天平台、本地模型、笔记工具串在一起,让它替你操作浏览器、查资料、写总结,听起来很爽,但你…

2026/10/2 18:38:49

XShell安装配置与SSH远程连接实战指南

1. 为什么选XShell?它真不是“又一个SSH工具”,而是终端操作的效率分水岭 XShell这个名字,在运维、开发、测试甚至高校实验室里,几乎等同于“稳定”“可靠”“不折腾”。它不是那种装完就闪退、连三次断两次、中文乱码到怀疑显示器…

2026/10/2 18:33:49

Hudi + Hive 增量数据处理全攻略:从同步机制到小文件优化

做网约车大数据项目那段时间,每天几十亿条订单、轨迹、支付流水往数据平台涌。团队最头疼的并不是数据量大,而是“变化”本身:订单状态不停更新、司机位置持续漂移、部分记录还要回滚删除。如果还是按离线思路每天全量重跑,计算资…

2026/10/2 8:16:46

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/10/2 18:20:53

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 10:48:55

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/2 0:02:57

PWN入门:从栈溢出原理到ROP链实战

1. 这不是“学PWN”,是重新理解你每天敲的每一行C代码我第一次在CTF赛场上写出能控制程序流的exp时,手抖得连gdb的c命令都输错三次。那道题只有23行C代码,一个gets()调用,一个printf(),一个return——它甚至没开NX&…

2026/10/2 0:02:57

Windows下cudaMallocHost显存占用之谜:WDDM与TCC模式差异及优化方案

1. 一个反直觉的显存占用现象第一次在 Windows 上看到cudaMallocHost把显存吃掉的时候,我的反应是打开任务管理器反复确认了三遍。明明调用的是主机端锁页内存分配,按 CUDA 文档的说法,这块内存应该落在系统 RAM 里,跟 GPU 的显存…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑