当前位置: 首页 > article >正文

【java】小练习--零钱通

文章目录

  • 前言
  • 一、项目开发流程说明
  • 二、功能实现
    • 2.1 菜单
    • 2.2 零钱通明细
    • 2.3 零钱通收益
    • 2.4 零钱通消费
    • 2.5 零钱通退出确认
    • 2.6 零钱通金额校验
    • 2.7 完整代码
  • 三、零钱通OOP版

前言

本文是我跟着B站韩顺平老师的 Java 教程学习时动手实现“零钱通”项目的学习笔记,主要用于记录自己的学习过程,方便复习和巩固

一、项目开发流程说明

  1. 项目需求说明

使用java开发零钱通项目,可以完成收益入账,消费,查看明细,退出系统等功能

  1. 项目界面

在这里插入图片描述

  1. 项目代码实现

编写文件 SmallChangeSys.java 完成基本功能(过程编程)

我们先使用过程编程,后面改成OOP版本

  1. 项目代码实现改进

在实现零钱通的基本功能后,我们还需要对项目代码进行改进,例如:

(1)用户输入4退出时,给出提示信息“你确定要退出吗?y/n”,必须输入正确的 y/n,否则循环输入指令,直到输入 y 或者 n

(2)在 收益入账 和 消费 时,判断金额是否合理,并给出相应的提示

(3)将面向过程的代码修改成面向对象的方法,编写 SmallChangeSysOOP.java类,并使用 SmallChangeSysApp.java 完成测试

二、功能实现

2.1 菜单

我们首先先完成 【显示菜单,并可以选择】

img

思路:

1)打印菜单,因为我们希望用户选择菜单的某个选项之后还可以继续选择其他选项,所以我们使用do-while将菜单包起来,并定义一个布尔类型的变量 loop,默认为true,作为循环的条件

2)打印菜单后,用户应该是可以选择选项的,所以我们需要定义Scanner,用Scanner对象来接收用户输入的数据,并用 String 类型的变量 key 用来接收用户输入的字符串

3)用户输入选择之后,我们需要判断用户的选择,并完成相应的功能。我们这里使用 switch-case

当用户输入“退出”的对应的选项后,需要退出循环,所以我们需要将 loop 变量的值改为 false

package smallchange;import java.util.Scanner;public class SmallChangeSys {//1.先完成显示菜单,并可以选择菜单,给出对应的提示public static void main(String[] args) {//定义相关变量boolean loop = true;Scanner scanner = new Scanner(System.in);String key = "";do{System.out.println("-------------零钱通菜单--------------");System.out.println("\t\t\t1 零钱通明细");System.out.println("\t\t\t2 收益入账");System.out.println("\t\t\t3 消费");System.out.println("\t\t\t4 退    出");System.out.print("请选择(1-4):");key = scanner.next();//使用 switch 分支控制switch (key) {case "1":System.out.println("显示零钱通明细");break;case "2":System.out.println("收益入账");break;case "3":System.out.println("消费");break;case "4":System.out.println("退出");loop = false;break;default:System.out.println("选择有误,请重新输入");}}while(loop);System.out.println("--------已退出零钱通项目---------");}
}

2.2 零钱通明细

接下来我们来完成零钱通明细,下面的三种方式都可以:

(1)可以把收益入账和消费,保存到数组

(2)可以使用对象

(3)可以使用String拼接

我们这里使用第三种方式

//在main方法中定义details变量
String details = "-------------零钱通明细--------------";//...
case "1":System.out.println(details);break;

2.3 零钱通收益

img

首先需要定义三个变量

  1. 接收入账的金额
  2. 入账的时间
  3. 余额

入账的时间我们这里用Date类型,但是由于默认的日期格式是国外的风格

img

所以我们还需要定义一个SimpleDateFormat对象,到时候用来把我们得到的日期格式化

double money = 0; // 入账金额
double balance = 0; // 余额
Date date = null; // date 是 java.util.Date类型,表示日期
double money = 0;SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 可以用于日期格式化

然后完成零钱通收益的功能

  1. 接收用户输入的入账金额并做检验(校验部分我们后面再实现)
  2. 获取当前日期
  3. 拼接到 details 字符串中
case "2":System.out.print("收益入账金额:");money = scanner.nextDouble();//money 的值范围应该校验//...balance += money;//拼接收益入账信息到 detailsdate = new Date(); // 获取当前日期details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t余额:" + balance;break;

2.4 零钱通消费

消费部分需要定义一个新变量,用来保存消费的原因

String note = "";

然后完成零钱通消费的功能

  1. 接收用户输入的消费金额和消费原因(校验部分我们后面再实现)
  2. 对用户输入的金额进行校验
  3. 获取当前日期
  4. 拼接到 details 字符串中
case "3":System.out.print("消费金额:");money = scanner.nextDouble();System.out.print("消费说明:");note = scanner.next();//money 的值范围应该校验//...balance -= money;date = new Date();details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t余额:" + balance;break;

2.5 零钱通退出确认

用户输入 4 退出时,给出提示信息“你确定要退出吗?y/n”,必须输入正确的 y/n,否则循环输入指令,直到输入 y 或者 n

思路分析

(1)定义一个变量 choice

(2)使用 while(true) 无限循环,直到输入正确的 y 或 n 才break退出循环

(3)退出循环后,再判断 choice 是 y 还是 n ,就可以决定是否退出

case "4":
String choice = "";
while(true) { // 要求用户必须输入 y/n ,否则就一直循环System.out.println("你确定要退出吗?y/n");choice = scanner.next();if("y".equals(choice) || "n".equals(choice)) {break;}
}
//当用户退出while后,进行判断
if("y".equals(choice)) {loop = false;
}
break;

2.6 零钱通金额校验

在收益入账消费时,判断金额是否合理,并给出相应的提示

思路: 找出不正确的金额,然后给出提示

校验收益金额是否合理:

//输入收益金额后,校验金额
if(money <= 0) {System.out.println("收益入账失败,收益金额需要大于 0");break;
}

校验消费金额是否合理:

//输入消费金额后,校验金额
if(money <= 0 || money > balance) {System.out.println("你的消费金额应该在 0~" + balance);break;
}

2.7 完整代码

package smallchange;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;public class SmallChangeSys {//1.先完成显示菜单,并可以选择菜单,给出对应的提示public static void main(String[] args) {//定义相关变量boolean loop = true;Scanner scanner = new Scanner(System.in);String key = "";//        2.完成零钱通明细
//        三种方式都可以:
//        (1)可以把收益入账和消费,保存到数组
//        (2)可以使用对象
//        (3)简单地话,可以使用String拼接String details = "----------------零钱通明细-----------------";//3.完成收益入账 完成功能驱动程序员增加新的变化和代码//思路:定义新变量double money = 0;double balance = 0;Date date = null; // date 是 java.util.Date类型,表示日期SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 可以用于日期格式化//4.消费//定义新变量,保存消费的原因String note = "";do{System.out.println("\n----------------零钱通菜单-----------------");System.out.println("\t\t\t1 零钱通明细");System.out.println("\t\t\t2 收益入账");System.out.println("\t\t\t3 消费");System.out.println("\t\t\t4 退    出");System.out.print("请选择(1-4):");key = scanner.next();//使用 switch 分支控制switch (key) {case "1":System.out.println(details);break;case "2":System.out.print("收益入账金额:");money = scanner.nextDouble();//money 的值范围应该校验//思路:找出不正确的金额,然后给出提示if(money <= 0) {System.out.println("收益入账失败,收益金额需要大于 0");break;}balance += money;//拼接收益入账信息到 detailsdate = new Date(); // 获取当前日期details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t余额:" + balance;break;case "3":System.out.print("消费金额:");money = scanner.nextDouble();System.out.print("消费说明:");note = scanner.next();//money 的值范围应该校验//思路:找出不正确的金额,然后给出提示if(money <= 0 || money > balance) {System.out.println("你的消费金额应该在 0~" + balance);break;}balance -= money;date = new Date();details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t余额:" + balance;break;case "4"://用户输入 4 退出时,给出提示信息“你确定要退出吗?y/n”,//必须输入正确的 y/n,否则循环输入指令,直到输入 y 或者 n
//                    思路
//                    (1)定义一个变量 choice
//                    (2)使用 while(true) 无限循环,直到输入正确的 y 或 n 才break退出循环
//                    (3)退出循环后,再判断 choice 是 y 还是 n ,就可以决定是否退出String choice = "";while(true) { // 要求用户必须输入 y/n ,否则就一直循环System.out.println("你确定要退出吗?y/n");choice = scanner.next();if("y".equals(choice) || "n".equals(choice)) {break;}}//当用户退出while后,进行判断if("y".equals(choice)) {loop = false;}break;default:System.out.println("选择有误,请重新输入");}}while(loop);System.out.println("--------已退出零钱通项目---------");}
}

三、零钱通OOP版

将面向过程的代码修改成面向对象的方法,编写 SmallChangeSysOOP.java类,并使用 SmallChangeSysApp.java 完成测试

SmallChangeSysOOP.java类主要用于完成零钱通的各个功能,而SmallChangeSysApp.java 通过调用SmallChangeSysOOP.java中的相关方法,使用零钱通的功能,二者关系如下:

img

SmallChangeSysOOP.java 类中代码如下:

package smallchange.oop;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;/*** 该类是完成零钱通的各个功能的类* 使用OOP(面向对象编程)* 将各个功能对应一个方法*/
public class smallChangeSysOOP {//属性boolean loop = true; // 循环条件Scanner scanner = new Scanner(System.in); // 接收用户输入String key = ""; // 用户的选择String details = "----------------零钱通明细-----------------";double money = 0; // 收益/消费的金额double balance = 0; // 余额Date date = null; // date 是 java.util.Date类型,表示日期SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 可以用于日期格式化String note = ""; // 消费的原因//完成显示菜单,并可以选择public void mainMenu() {do{System.out.println("\n----------------零钱通菜单-----------------");System.out.println("\t\t\t1 零钱通明细");System.out.println("\t\t\t2 收益入账");System.out.println("\t\t\t3 消费");System.out.println("\t\t\t4 退    出");System.out.print("请选择(1-4):");key = scanner.next();//使用 switch 分支控制switch (key) {case "1":this.detail();break;case "2":this.income();break;case "3":this.pay();break;case "4":this.exit();break;default:System.out.println("选择有误,请重新输入");}}while(loop);}//完成零钱通明细public void detail() {System.out.println(details);}//完成收益入账public void income() {System.out.print("收益入账金额:");money = scanner.nextDouble();//money 的值范围应该校验//思路:找出不正确的金额,然后给出提示if(money <= 0) {System.out.println("收益入账失败,收益金额需要大于 0");return;}balance += money;//拼接收益入账信息到 detailsdate = new Date(); // 获取当前日期details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t余额:" + balance;}//消费public void pay() {System.out.print("消费金额:");money = scanner.nextDouble();System.out.print("消费说明:");note = scanner.next();//money 的值范围应该校验//思路:找出不正确的金额,然后给出提示if(money <= 0 || money > balance) {System.out.println("你的消费金额应该在 0~" + balance);return;}balance -= money;date = new Date();details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t余额:" + balance;}//退出public void exit() {String choice = "";while(true) { // 要求用户必须输入 y/n ,否则就一直循环System.out.println("你确定要退出吗?y/n");choice = scanner.next();if("y".equals(choice) || "n".equals(choice)) {break;}}//当用户退出while后,进行判断if("y".equals(choice)) {loop = false;}}
}

SmallChangeSysApp.java 中的代码如下

package smallchange.oop;/*** 这里我们直接调用 SmallChangeSysOOP 对象,显示主菜单即可*/
public class smallChangeSysApp {public static void main(String[] args) {smallChangeSysOOP smallChangeSysOOP = new smallChangeSysOOP();smallChangeSysOOP.mainMenu();}
}

相关文章:

【java】小练习--零钱通

文章目录 前言一、项目开发流程说明二、功能实现2.1 菜单2.2 零钱通明细2.3 零钱通收益2.4 零钱通消费2.5 零钱通退出确认2.6 零钱通金额校验2.7 完整代码 三、零钱通OOP版 前言 本文是我跟着B站韩顺平老师的 Java 教程学习时动手实现“零钱通”项目的学习笔记&#xff0c;主要…...

旅游信息检索

旅游信息检索 旅游信息检索是系统中实现数据获取和处理的关键环节&#xff0c;负责根据用户输入的目的地城市和出游天数&#xff0c;动态获取并生成高质量的旅游数据。 模块的工作流程分为以下几个阶段&#xff1a;首先&#xff0c;对用户输入的信息进行标准化处理&#xff0…...

贝叶斯理论

一、贝叶斯理论的核心思想 贝叶斯理论&#xff08;Bayesian Theory&#xff09;是一种基于条件概率的统计推断方法&#xff0c;其核心是通过先验知识和新观测数据的结合&#xff0c;动态更新对事件发生概率的估计。它体现了“用数据修正信念”的思想&#xff0c;广泛应用于机器…...

Docker-mongodb

拉取 MongoDB 镜像: docker pull mongo 创建容器并设置用户&#xff1a; 要挂载本地数据目录&#xff0c;请替换此路径: /Users/Allen/Env/AllenDocker/mongodb/data/db docker run -d --name local-mongodb \-e MONGO_INITDB_ROOT_USERNAMEadmin \-e MONGO_INITDB_ROOT_PA…...

Gartner《Optimize GenAI Strategy for 4 Key ConsumerMindsets》学习心得

一、引言 在当今数字化营销浪潮中,生成式人工智能(GenAI)正以前所未有的速度重塑着市场格局。GenAI 既是一场充满机遇的变革,也是一场潜在风险的挑战。一方面,绝大多数 B2C 营销领导者对 GenAI 赋能营销抱有极高期待,他们看到了 GenAI 在提升时间与成本效率方面的巨大潜…...

[ARM][汇编] 02.ARM 汇编常用简单指令

目录 1.数据传输指令 MRS - Move from Status Register 指令用途 指令语法 代码示例 读取 CPSR 到通用寄存器 在异常处理程序中读取 SPSR 使用场景 MSR - Move to Status Register 指令语法 使用场景 示例代码 改变处理器模式为管理模式 设置条件标志位 异常处理…...

达梦数据库-学习-22-库级物理备份恢复(超详细版)

目录 一、环境信息 二、说点什么 三、概念 1、备份恢复 2、重做日志 3、归档日志 4、LSN 5、检查点 四、语法 1、BACKUP DATABASE 2、DMRMAN RESTORE DATABASE 3、DMRMAN RECOVER DATABASE 4、DMRMAN UPDATE DB_MAGIC 五、实验 1、开归档 &#xff08;1&#xf…...

python网络爬虫的基本使用

各位帅哥美女点点关注&#xff0c;有关注才有动力啊 网络爬虫 引言 我们平时都说Python爬虫&#xff0c;其实这里可能有个误解&#xff0c;爬虫并不是Python独有的&#xff0c;可以做爬虫的语言有很多例如&#xff1a;PHP、JAVA、C#、C、Python。 为什么Python的爬虫技术会…...

AI Agent开发第74课-解构AI伪需求的魔幻现实主义

开篇 🚀在之前的系列中我们狂炫了AI Agent的各种高端操作(向量数据库联动、多模态感知、动态工作流等…),仿佛每个程序员都能用LLM魔法点石成金✨。 但今天咱们要泼一盆透心凉的冷水——当企业把AI当成万能胶水强行粘合所有需求时,连电风扇都能被玩出量子纠缠的魔幻现实…...

【卫星通信】通信卫星链路预算计算及其在3GPP NTN中的应用

引言 卫星通信是现代信息传播的重要手段&#xff0c;广泛应用于电信、广播、气象监测、导航等领域。卫星链路预算计算是设计和优化卫星通信系统的重要步骤&#xff0c;它帮助工程师评估信号在传输过程中的衰减和增益&#xff0c;从而确保系统在预定条件下可靠地工作。 1. 链路…...

HTTP请求方法:GET与POST的使用场景解析

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 HTTP协议定义了多种请求方法&#xff0c;其中GET和POST是最常用的两种。它们在Web开发中承担着不同的角色&#xff0c;理解其核心差异和使用场景是构建高效、…...

第十五章:数据治理之数据目录:摸清家底,建立三大数据目录

在上一篇随想篇中&#xff0c;介绍了数据资源资产化的过程&#xff0c;理解了数据资源、数据资产的区别。这些对于本章的介绍会有帮助&#xff0c;如果仍有疑问可以看上一篇【数据资源到数据资产的华丽转身 ——从“沉睡的石油”到“流动的黄金”】。 说到本章要介绍的数据目录…...

c++命名空间的作用及命名改编

c命名空间的作用及命名改编 命名空间 namespace的作用&#xff1a; std::命名空间&#xff0c;命名空间&#xff08;namespace&#xff09;是 C 中用于解决标识符命名冲突问题的机制。在大型程序开发中&#xff0c;不同模块可能会使用相同名称的变量、函数或类等标识符&…...

Go核心特性与并发编程

Go核心特性与并发编程 1. 结构体与方法&#xff08;扩展&#xff09; 高级结构体特性 // 嵌套结构体与匿名字段 type Employee struct {Person // 匿名嵌入Department stringsalary float64 // 私有字段 }// 构造函数模式 func NewPerson(name string, age int) *Pe…...

echarts实现项目进度甘特图

描述 echarts并无甘特图配置项&#xff0c;我们可以使用柱状图模拟&#xff0c;具体配置项如下&#xff0c;可以在echarts直接运行 var option {backgroundColor: "#fff",legend: {data: ["计划时间","实际时间"],align: "right",…...

Flutter 中 build 方法为何写在 StatefulWidget 的 State 类中

Flutter 中 build 方法为何写在 StatefulWidget 的 State 类中 在 Flutter 中&#xff0c;build 方法被设计在 StatefulWidget 的 State 类中而非 StatefulWidget 类本身&#xff0c;这种设计基于几个重要的架构原则和实际考量&#xff1a; 1. 核心设计原因 1.1 生命周期管理…...

C#串口打印机:控制类开发与实战

C#串口打印机&#xff1a;控制类开发与实战 一、引言 在嵌入式设备、POS 终端、工业控制等场景中&#xff0c;串口打印机因其稳定的通信性能和广泛的兼容性&#xff0c;仍是重要的数据输出设备。本文基于 C# 语言&#xff0c;深度解析一个完整的串口打印机控制类Printer&…...

2025深圳国际无人机展深度解析:看点、厂商与创新亮点

2025深圳国际无人机展深度解析&#xff1a;看点、厂商与创新亮点 1.背景2.核心看点&#xff1a;技术突破与场景创新2.1 eVTOL&#xff08;飞行汽车&#xff09;的规模化展示2.2 智能无人机与无人值守平台2.3 新材料与核心零部件革新2.4 动态演示与赛事活动 3.头部无人机厂商4.核…...

Electron 后台常驻服务实现(托盘 + 开机自启)

基于 electron-vite-vue 项目结构 本篇将详细介绍如何为 Electron 应用实现后台常驻运行&#xff0c;包括&#xff1a; ✅ 创建系统托盘图标&#xff08;Tray&#xff09;✅ 支持点击托盘菜单控制窗口显示/退出✅ 实现开机自启功能&#xff08;Auto Launch&#xff09; &#…...

Spring Boot与Kafka集成实践:从入门到实战

Spring Boot与Kafka集成实践 引言 在现代分布式系统中&#xff0c;消息队列技术扮演着至关重要的角色。Kafka作为一款高性能、高吞吐量的分布式消息队列系统&#xff0c;被广泛应用于日志收集、流处理、事件驱动架构等场景。本文将详细介绍如何在Spring Boot项目中集成Kafka&…...

人形机器人通过观看视频学习人类动作的技术可行性与前景展望

摘要 本文深入探讨人形机器人通过观看视频学习人类动作这一技术路线的正确性与深远潜力。首先阐述该技术路线在模仿人类学习过程方面的优势&#xff0c;包括对人类动作、表情、发音及情感模仿的可行性与实现路径。接着从技术原理、大数据训练基础、与人类学习速度对比等角度论证…...

第三十四天打卡

DAY 34 GPU训练及类的call方法 知识点回归&#xff1a; CPU性能的查看&#xff1a;看架构代际、核心数、线程数 GPU性能的查看&#xff1a;看显存、看级别、看架构代际 GPU训练的方法&#xff1a;数据和模型移动到GPU device上 类的call方法&#xff1a;为什么定义前向传播时可…...

打卡day35

一、模型结构可视化 理解一个深度学习网络最重要的2点&#xff1a; 了解损失如何定义的&#xff0c;知道损失从何而来----把抽象的任务通过损失函数量化出来了解参数总量&#xff0c;即知道每一层的设计才能退出—层设计决定参数总量 为了了解参数总量&#xff0c;我们需要知…...

【【嵌入式开发 Linux 常用命令系列 19 -- linux top 命令的交互使用介绍】

文章目录 Overview常用的交互命令&#xff08;top 运行时可直接按键&#xff09;示例使用场景按内存排序&#xff0c;显示某个用户的前 10 个进程&#xff1a;杀死占用资源最多的进程调整刷新频率为 1 秒 提示 Overview 在linux环境下办公经常会遇到杀进程&#xff0c;查看cpu…...

配置tomcat时,无法部署工件该怎么办?

当我们第一次在IDEA中创建Java项目时&#xff0c;配置tomcat可能会出现无法部署工件的情况&#xff0c;如图&#xff1a; 而正常情况应该是&#xff1a; 那么该如何解决呢&#xff1f; 步骤一 点开右上角该图标&#xff0c;会弹出如图页面 步骤二 步骤三 步骤四...

.NET外挂系列:8. harmony 的IL编织 Transpiler

一&#xff1a;背景 1. 讲故事 前面文章所介绍的一些注入技术都是以方法为原子单位&#xff0c;但在一些罕见的场合中&#xff0c;这种方法粒度又太大了&#xff0c;能不能以语句为单位&#xff0c;那这个就是我们这篇介绍的 Transpiler&#xff0c;它可以修改方法的 IL 代码…...

基于netty实现视频流式传输和多线程传输

文章目录 业务描述业务难点流式传输客户端(以tcp为例)服务端测试类测试步骤多线程传输客户端服务端测试类测试步骤多线程流式传输总结业务描述 多台终端设备持续给数据服务器(外)发送视频数据,数据服务器(外)通过HTTP协议将数据经过某安全平台转到数据服务器(内),数据…...

全面指南:使用Node.js和Python连接与操作MongoDB

在现代Web开发中&#xff0c;数据库是存储和管理数据的核心组件。MongoDB作为一款流行的NoSQL数据库&#xff0c;以其灵活的数据模型、高性能和易扩展性广受开发者欢迎。无论是使用Node.js还是Python&#xff0c;MongoDB都提供了强大的官方驱动和第三方库&#xff0c;使得数据库…...

游戏引擎学习第308天:调试循环检测

回顾并为今天的内容做准备 我们正在进行游戏开发中的精灵&#xff08;sprite&#xff09;排序工作&#xff0c;虽然目前的实现已经有了一些改进&#xff0c;情况也在逐步好转&#xff0c;我们已经实现了一个图结构的排序算法&#xff0c;用来处理精灵渲染顺序的问题。然而&…...

Java 海康录像机通过sdk下载的视频无法在线预览问题

下载的视频格式不对&#xff0c;需将视频转码为H.264/AAC的MP4格式 使用 ffmpeg 对视频进行转码 ffmpeg可以对视频进行转码、加水印等操作&#xff0c;还是挺强大的 代码如下 public static void transcodeToMP4(String inputPath, String outputPath) throws IOException, In…...