(1)前言
题目集7,8主要涉及以下知识点,Java 是一种面向对象的编程语言,需要理解类和对象的概念,如何设计和实现各种设备的类。设计控制设备类和受控设备类,理解如何通过类和对象来模拟真实世界中的设备和其行为。通过继承和多态实现设备之间的关系和行为的多样化。例如,可以将不同类型的调速器(分档调速器和连续调速器)抽象为调速器的子类,共享通用的行为,同时又具备各自特有的功能。读取和解析输入信息,例如控制设备的调节信息、电路连接信息等,可以通过文件读写来实现。对输入的字符串进行分割、解析和格式化,以便正确地识别设备标识、引脚编号等信息,还包括输入数据的合法性验证,如设备标识符的有效性、连接信息的正确性等。设计实现电路模拟的算法和逻辑,包括根据输入信息模拟设备状态变化、计算电压差驱动设备行为等。还涉及了状态管理的知识点,设备状态的管理和更新(开关状态、调速器档位、灯的亮度、风扇的转速等)。这是具有挑战性的题目,要求在理解各类设备工作原理的基础上,编写程序模拟复杂的电路结构和设备控制过程一是有复杂的设备模拟,涵盖多种控制设备和受控设备,每种设备都有特定的工作状态和输入输出规则。二是输入信息处理,需要正确解析控制设备的调节信息和电路连接信息,确保按要求模拟电路状态。三是有复杂的电路,题目要求涵盖了多种设备类型和复杂的连接方式,需要合理的面向对象设计和逻辑实现。特别是并联电路中包含串联电路的设计,需要考虑递归处理的方式。综合考虑,题目集要求不仅涉及到Java基础的面向对象编程,还需要处理复杂的输入输出、串并联电路和状态管理问题,难度较大,比较复杂。
(2)设计与分析
题目集7 7-1
7-1 家居强电电路模拟程序-3
分数 100
作者 蔡轲
单位 南昌航空大学
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。以下题目介绍中加粗的部分为本次迭代在“家居强电电路模拟程序-2”的基础上增加的功能要求。
1、控制设备
本题模拟的控制设备包括:开关、分档调速器、连续调速器、互斥开关。
开关:包括0和1两种状态。
开关有两个引脚,任意一个引脚都可以是输入引脚(接往电源端),而另一个则是输出引脚(接网接地端)。开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
互斥开关:
互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。
开关电路示意图如图1所示,左边是汇总引脚,编号为1;右边两个是分支引脚,右上的输出引脚为2,右下输出引脚为3。图中1、2、3引脚均可以是输入引脚,当1为输入引脚时,2、3引脚为输出引脚;1为输出引脚时,2、3引脚为输入引脚。
互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。
互斥开关的默认状态为1、2引脚接通,1、3引脚断开。
图1中所示的互斥开关可以反过来接入电路,即汇总引脚接往接地端,两个分支引脚接往电源端。
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104623900-927269690.png)
图1 互斥开关
为避免短路,互斥开关设置了限流电阻,12引脚之间默认电阻为5,13引脚之间默认电阻为10。
分档调速器
按档位调整,常见的有3档、4档、5档调速器,档位值从0档-2(3/4)档变化。本次迭代模拟4档调速器,每个档位的输出电位分别为0、0.3、0.6、0.9倍的输入电压。
连续调速器
没有固定档位,按位置比例得到档位参数,数值范围在[0.00-1.00]之间,含两位小数。输出电位为档位参数乘以输入电压。
所有调速器都有两个引脚,一个固定的输入(引脚编号为1)、一个输出引脚(引脚编号为2)。当输入电位为0时,输出引脚输出的电位固定为0,不受各类开关调节的影响。
开关、调速器的初始状态/档位为0。
开关、调速器的输入引脚编号为1,输出引脚编号为2。
除互斥开关外,其他控制设备的电阻为 0。
2、受控设备
本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。
灯有两种工作状态:亮、灭。在亮的状态下,有的灯会因引脚电位差的不同亮度会有区别。
风扇在接电后有两种工作状态:停止、转动。风扇的转速会因引脚间电位差的不同而有区别。
本次迭代模拟两种灯具。
白炽灯:
亮度在0~200lux(流明)之间。
电位差为0-9V时亮度为0,其他电位差按比例,电位差10V对应50ux,220V对应200lux,其他电位差与对应亮度值成正比。白炽灯超过220V。
日光灯:
亮度为180lux。
只有两种状态,电位差为0时,亮度为0,电位差不为0,亮度为180。
本次迭代模拟两种风扇。
吊扇:
工作电压区间为80V-150V,对应转速区间为80-360转/分钟。80V对应转速为80转/分钟,150V对应转速为360转/分钟,超过150V转速为360转/分钟(本次迭代暂不考虑电压超标的异常情况)。其他电压值与转速成正比,输入输出电位差小于80V时转速为0。
落地扇:
工作电压区间为 80V-150V,对应转速区间为 80-360 转/分钟;[80V,100V) 对应转速为 80 转/分钟;[100,120)V 对应转速为 160 转/分钟;[120,140)V 对应转速为 260 转/分钟;大于等于 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)。
本次迭代模拟一种受控窗帘:
受控窗帘的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。
当电路中所有灯光的光照强度总和在[0,50)lux范围内,窗帘全开;
在[50,100)lux范围内,窗帘打开比例为0.8;
在[100,200)lux范围内,窗帘打开比例为0.6;
在[200,300)lux范围内,窗帘打开比例为0.4;
在[300,400)lux范围内,窗帘打开比例为0.2;
在400lux及以上范围内,窗帘关闭。
当电压低于50V,窗帘不工作,默认为全开状态。
如果电路中没有灯或者灯全部关闭,光照强度为0,窗帘处于全开状态。
受控设备电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落地扇的电阻为 20,窗帘电阻为15。
3、输入信息
1)输入设备信息
分别用设备标识符K、F、L、B、R、D、A、H、S分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇、互斥开关、受控窗帘。
设备标识用标识符+编号表示,如K1、F3、L2等。
引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。
开关、分档调速器、连续调速器的输入引脚编号为1,输出引脚编号为2。
受控设备的两个引脚编号分别为1、2。
互斥开关的引脚编号已经在互斥开关的介绍部分说明。
约束条件:
不同设备的编号可以相同。
同种设备的编号可以不连续。
设备信息不单独输入,包含在连接信息中。
2)输入连接信息
一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。
格式:"["+引脚号+" "+...+" "+引脚号+"]"
例如:[K1-1 K3-2 D5-1]表示K1的输入引脚,K3的输出引脚,D5的1号引脚连接在一起。
约束条件:
不考虑调速器串联到其他调速器的情况。
不考虑调速器串联到其他调速器的情况。
考虑各类设备的并联接入。例如,K1 的输出接到 L2 的输入,L2 的输出再接其他设备属于串联接线。K1 的输出接到 L2 的输出,同时 K1 的输入接到 L2 的输入,这种情况属于并联。
本次迭代的连接信息不单独输入,包含在线路信息中。
3)输入控制设备调节信息
开关、互斥开关调节信息格式:
#+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。
#+设备标识H+设备编号,例如:#H2,代表切换H2互斥开关的状态。
分档调速器的调节信息格式:
#+设备标识F+设备编号+"+" 代表加一档,例如:#F3+,代表F3输出加一档。
#+设备标识F+设备编号+"-" 代表减一档,例如:#F1-,代表F1输出减一档。
连续调速器的调节信息格式:
#+设备标识L+设备编号+":" +数值 代表将连续调速器的档位设置到对应数值,例如:#L3:0.6,代表L3输出档位参数0.6。
4)电源接地标识:
VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。
5)输入串联电路信息
一条串联电路占一行,串联电路由按从靠电源端到接地端顺序依次输入的 n 个连接 信息组成,连接信息之间用英文空格" "分隔。
串联电路信息格式:
"#T"+电路编号+":"+连接信息+" "+连接信息+...+" "+连接信息
例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] 一个串联电路的第一个引脚是 IN,代表起始端,靠电源。最后一个引脚是 OUT,代表结尾端, 靠接地。
约束条件:
不同的串联电路信息编号不同。
输入的最后一条电路信息必定是总电路信息,总电路信息的起始引脚是 VCC,结束引脚是 GND。
连接信息中的引脚可能是一条串联或并联电路的 IN 或者 OUT。例如:
#T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT OUT]
#T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT]
6)输入并联电路信息
一条并联电路占一行,并联电路由其包含的几条串联电路组成,串联电路标识之间用英文空格" "分隔。
格式:
"#M"+电路编号+":"+”[”+串联电路信息+" "+....+" "+串联电路信息+”]”
例如:#M1:[T1 T2 T3]
该例声明了一个并联电路,由 T1、T2、T3 三条串联电路并联而成,三条串联电路的 IN 短 接在一起构成 M1 的 IN,三条串联电路的 OUT 短接在一起构成 M1 的 OUT。
约束条件:
本次迭代不考虑并联电路中包含并联电路的情况。
本题不考虑输入电压或电压差超过220V的情况。
输入信息以end为结束标志,忽略end之后的输入信息。
本题中的并联信息所包含的串联电路的信息都在并联信息之前输入,不考虑乱序输入的情况。
只要不因短路而造成无穷大的电流烧坏电路(如电路中的部分短接),都是合理情况,在测试点的考虑范围之内。会造成无穷大的电流的短路本次迭代不考虑。
本次迭代考虑多个并联电路串联在一起的情况。
本题考虑一条串联电路中包含其他串联电路的情况。例如:
#T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND]
本例中T1\T2两条串联电路T3的一个部分,本题考虑这种类型的输入。
4、输出信息:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、互斥开关、受控窗帘的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。
输出格式:
@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位)
连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。
开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed
如:
@K1:turned on
@B1:190
@L1:0.60
互斥开关显示1、2引脚的接通状态,接通时显示closed,断开时显示turned on。
如:
@H1:turned on
受控窗帘显示窗帘打开的百分比,如:
@S1:80%
5、家居电路模拟系列所有题目的默认规则:
1)当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。
2)所有连接信息按电路从电源到接地的顺序依次输入,不会出现错位的情况。电源VCC一定是第一个连接的第一项,接地GND一定是最后一个连接的后一项。
3)连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。
4)调速器的输入端只会直连VCC,不会接其他设备。整个电路最多只有连接在电源上的一个调速器,且不包含在并联单路中。
6、家居电路模拟系列1-4题目后续迭代设计:
1)电路结构变化:
迭代1:只有一条线路,所有元件串联
迭代2:线路中包含一个并联电路
迭代3:线路中包含多个串联起来的并联电路
迭代4:并联电路之间可能出现包含关系
电路结构变化示意图见图1。
2)计算方式的变化
迭代1只包含1个受控元件,不用计算电流,之后的电路计算要包含电流、电阻等电路参数。
3)电路元件的变化
每次迭代会增加1-2个新的电路元件。
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104427141-1676264231.png)
图1:电路结构示意图
设计建议:
1、电路设备类:描述所有电路设备的公共特征。
2、受控设备类、控制设备类:对应受控、控制设备
3、串联电路类:一条由多个电路设备构成的串联电路,也看成是一个独立的电路设备
4、并联电路类:继承电路设备类,也看成是一个独立的电路设备
其他类以及类的属性、方法自行设计。
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104402905-1376541001.png)
图2:建议设计类图
输入样例1:
在这里给出一组输入。例如:
#T1:[IN H1-1] [H1-2 D2-1] [D2-2 OUT]
#T2:[IN H1-1] [H1-3 D1-1] [D1-2 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 B2-1] [B2-2 OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
#T3:[VCC K2-1] [K2-2 M1-IN] [M1-OUT M2-IN] [M2-OUT GND]
#K1
#K2
end
输出样例1:
在这里给出相应的输出。例如:
@K1:closed
@K2:closed
@K3:turned on
@B1:87
@B2:0
@D1:0
@D2:262
@H1:closed
输入样例2:
在这里给出一组输入。例如:
#T1:[IN D2-1] [D2-2 H1-2] [H1-1 OUT]
#T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 B2-1] [B2-2 OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
#T3:[VCC K2-1] [K2-2 M1-IN] [M1-OUT M2-IN] [M2-OUT GND]
#K1
#K2
end
输出样例2:
在这里给出相应的输出。例如:
@K1:closed
@K2:closed
@K3:turned on
@B1:87
@B2:0
@D1:0
@D2:262
@H1:closed
输入样例3:
在这里给出一组输入。例如:
#T1:[IN K1-1] [K1-2 B2-1] [B2-2 OUT]
#T2:[IN K2-1] [K2-2 R1-1] [R1-2 OUT]
#M1:[T1 T2]
#T3:[VCC K3-1] [K3-2 M1-IN] [M1-OUT S1-1] [S1-2 GND]
#K1
#K2
#K3
end
输出样例3:
在这里给出相应的输出。例如:
@K1:closed
@K2:closed
@K3:closed
@B2:71
@R1:180
@S1:40%
输入样例4:
在这里给出一组输入。例如:
#T1:[IN K2-1] [K2-2 D2-1] [D2-2 OUT]
#T2:[IN K3-1] [K3-2 D1-1] [D1-2 OUT]
#T3:[VCC K1-1] [K1-2 T1-IN] [T1-OUT T2-IN] [T2-OUT GND]
#K1
#K2
#K3
end
输出样例4:
在这里给出相应的输出。例如:
@K1:closed
@K2:closed
@K3:closed
@D1:200
@D2:200
输入样例5:
在这里给出一组输入。例如:
#T3:[VCC B2-1] [B2-2 K1-1] [K1-2 S1-1] [S1-2 H1-1] [H1-2 GND]
#K1
end
输出样例5:
在这里给出相应的输出。例如:
@K1:closed
@B2:95
@H1:closed
@S1:80%
代码长度限制
100 KB
时间限制
1000 ms
内存限制
64 MB
栈限制
8192 KB
代码如下:
import java.util.*;
import java.util.regex.*;
abstract class CircuitDevice {
String deviceId;
Map<Integer, Double> inputs = new HashMap<>();
Map<Integer, Double> outputs = new HashMap<>();
CircuitDevice(String deviceId) {
this.deviceId = deviceId;
}
void addInput(int pin, double voltage) {
inputs.put(pin, voltage);
}
void addOutput(int pin, double voltage) {
outputs.put(pin, voltage);
}
abstract void updateVoltage();
}
class Switch extends CircuitDevice {
int state = 0;
Switch(String deviceId) {
super(deviceId);
}
void toggle() {
state = 1 - state;
updateVoltage();
}
@Override
void updateVoltage() {
double inputVoltage = inputs.getOrDefault(1, 0.0);
double outputVoltage = state == 1 ? 0.0 : inputVoltage;
outputs.replaceAll((pin, voltage) -> outputVoltage);
}
}
class MutualSwitch extends CircuitDevice {
int state = 0;
MutualSwitch(String deviceId) {
super(deviceId);
}
void toggle() {
state = 1 - state;
updateVoltage();
}
@Override
void updateVoltage() {
double inputVoltage = inputs.getOrDefault(1, 0.0);
outputs.replaceAll((pin, voltage) -> (pin == 2 && state == 0) || (pin == 3 && state == 1) ? inputVoltage : 0.0);
}
}
abstract class SpeedController extends CircuitDevice {
int steps = 0;
int maxSteps;
SpeedController(String deviceId, int maxSteps) {
super(deviceId);
this.maxSteps = maxSteps;
}
void increaseStep() {
if (steps < maxSteps) {
steps++;
}
updateVoltage();
}
void decreaseStep() {
if (steps > 0) {
steps--;
}
updateVoltage();
}
abstract void updateVoltage();
}
class StepSpeedController extends SpeedController {
StepSpeedController(String deviceId) {
super(deviceId, 3);
}
@Override
void updateVoltage() {
double[] voltageRatios = {0, 0.3, 0.6, 0.9};
outputs.replaceAll((pin, voltage) -> voltageRatios[steps] * inputs.getOrDefault(1, 0.0));
}
}
class ContinuousSpeedController extends SpeedController {
ContinuousSpeedController(String deviceId) {
super(deviceId, 100);
}
void setStep(double stepValue) {
steps = (int) (stepValue * 100);
updateVoltage();
}
@Override
void updateVoltage() {
outputs.replaceAll((pin, voltage) -> (steps / 100.0) * inputs.getOrDefault(1, 0.0));
}
}
abstract class Light extends CircuitDevice {
int brightness = 0;
Light(String deviceId) {
super(deviceId);
}
abstract void updateBrightness();
}
class IncandescentLight extends Light {
IncandescentLight(String deviceId) {
super(deviceId);
}
@Override
void updateBrightness() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff > 220) {
voltageDiff = 220;
}
brightness = voltageDiff < 10 ? 0 : (int) ((voltageDiff - 10) * (200 / 210.0));
}
@Override
void updateVoltage() {
updateBrightness();
}
}
class FluorescentLight extends Light {
FluorescentLight(String deviceId) {
super(deviceId);
}
@Override
void updateBrightness() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
brightness = voltageDiff != 0 ? 180 : 0;
}
@Override
void updateVoltage() {
updateBrightness();
}
}
abstract class Fan extends CircuitDevice {
int speed = 0;
Fan(String deviceId) {
super(deviceId);
}
abstract void updateSpeed();
}
class CeilingFan extends Fan {
CeilingFan(String deviceId) {
super(deviceId);
}
@Override
void updateSpeed() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff > 150) {
voltageDiff = 150;
}
speed = voltageDiff >= 80 ? (int) ((voltageDiff - 80) * (280 / 70.0)) + 80 : 0;
}
@Override
void updateVoltage() {
updateSpeed();
}
}
class FloorFan extends Fan {
FloorFan(String deviceId) {
super(deviceId);
}
@Override
void updateSpeed() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff >= 140) {
speed = 360;
} else if (voltageDiff >= 120) {
speed = 260;
} else if (voltageDiff >= 100) {
speed = 160;
} else if (voltageDiff >= 80) {
speed = 80;
} else {
speed = 0;
}
}
@Override
void updateVoltage() {
updateSpeed();
}
}
class Curtain extends CircuitDevice {
int openPercentage = 100;
Curtain(String deviceId) {
super(deviceId);
}
@Override
void updateVoltage() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff < 50) {
openPercentage = 100;
} else {
openPercentage = 0;
}
}
void updateOpenPercentage(int totalLux) {
if (totalLux < 50) {
openPercentage = 100;
} else if (totalLux < 100) {
openPercentage = 80;
} else if (totalLux < 200) {
openPercentage = 60;
} else if (totalLux < 300) {
openPercentage = 40;
} else if (totalLux < 400) {
openPercentage = 20;
} else {
openPercentage = 0;
}
}
}
class SeriesCircuit {
String circuitId;
List<CircuitDevice> devices = new ArrayList<>();
SeriesCircuit(String circuitId) {
this.circuitId = circuitId;
}
void addDevice(CircuitDevice device) {
devices.add(device);
}
void updateCircuit() {
for (CircuitDevice device : devices) {
device.updateVoltage();
}
}
}
class ParallelCircuit {
String circuitId;
List<SeriesCircuit> seriesCircuits = new ArrayList<>();
ParallelCircuit(String circuitId) {
this.circuitId = circuitId;
}
void addSeriesCircuit(SeriesCircuit seriesCircuit) {
seriesCircuits.add(seriesCircuit);
}
void updateCircuit() {
for (SeriesCircuit seriesCircuit : seriesCircuits) {
seriesCircuit.updateCircuit();
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> inputLines = new ArrayList<>();
String line;
while (!(line = scanner.nextLine()).equals("end")) {
inputLines.add(line);
}
scanner.close();
Map<String, SeriesCircuit> seriesCircuits = new HashMap<>();
Map<String, ParallelCircuit> parallelCircuits = new HashMap<>();
Map<String, CircuitDevice> devices = new HashMap<>();
parseInput(inputLines, seriesCircuits, parallelCircuits, devices);
for (SeriesCircuit circuit : seriesCircuits.values()) {
circuit.updateCircuit();
}
for (ParallelCircuit circuit : parallelCircuits.values()) {
circuit.updateCircuit();
}
updateCurtainState(devices);
outputResults(devices);
}
private static void parseInput(List<String> inputLines, Map<String, SeriesCircuit> seriesCircuits, Map<String, ParallelCircuit> parallelCircuits, Map<String, CircuitDevice> devices) {
Pattern seriesPattern = Pattern.compile("#T(\\d+)");
Pattern parallelPattern = Pattern.compile("#M(\\d+)");
Pattern devicePattern = Pattern.compile("(\\w+)-(\\d+)");
Pattern controlPattern = Pattern.compile("#(\\w+(:?\\d+\\.\\d+)?)");
for (String line : inputLines) {
if (line.startsWith("#T")) {
Matcher seriesMatcher = seriesPattern.matcher(line);
if (seriesMatcher.find()) {
String circuitId = seriesMatcher.group(1);
SeriesCircuit seriesCircuit = new SeriesCircuit(circuitId);
seriesCircuits.put(circuitId, seriesCircuit);
Matcher deviceMatcher = devicePattern.matcher(line);
while (deviceMatcher.find()) {
String deviceId = deviceMatcher.group(1);
if (!devices.containsKey(deviceId)) {
devices.put(deviceId, createDevice(deviceId));
}
seriesCircuit.addDevice(devices.get(deviceId));
}
}
} else if (line.startsWith("#M")) {
Matcher parallelMatcher = parallelPattern.matcher(line);
if (parallelMatcher.find()) {
String circuitId = parallelMatcher.group(1);
ParallelCircuit parallelCircuit = new ParallelCircuit(circuitId);
parallelCircuits.put(circuitId, parallelCircuit);
Matcher seriesMatcher = seriesPattern.matcher(line);
while (seriesMatcher.find()) {
String seriesId = seriesMatcher.group(1);
parallelCircuit.addSeriesCircuit(seriesCircuits.get(seriesId));
}
}
} else if (line.startsWith("#")) {
Matcher controlMatcher = controlPattern.matcher(line);
if (controlMatcher.find()) {
String controlInfo = controlMatcher.group(1);
applyControl(devices, controlInfo);
}
}
}
}
private static CircuitDevice createDevice(String deviceId) {
if (deviceId.startsWith("K")) {
return new Switch(deviceId);
} else if (deviceId.startsWith("F")) {
return new StepSpeedController(deviceId);
} else if (deviceId.startsWith("L")) {
return new ContinuousSpeedController(deviceId);
} else if (deviceId.startsWith("B")) {
return new IncandescentLight(deviceId);
} else if (deviceId.startsWith("R")) {
return new FluorescentLight(deviceId);
} else if (deviceId.startsWith("D")) {
return new CeilingFan(deviceId);
} else if (deviceId.startsWith("A")) {
return new FloorFan(deviceId);
} else if (deviceId.startsWith("H")) {
return new MutualSwitch(deviceId);
} else if (deviceId.startsWith("S")) {
return new Curtain(deviceId);
} else {
throw new IllegalArgumentException("Unknown device type: " + deviceId);
}
}
private static void applyControl(Map<String, CircuitDevice> devices, String controlInfo) {
if (controlInfo.startsWith("K")) {
((Switch) devices.get(controlInfo)).toggle();
} else if (controlInfo.startsWith("H")) {
((MutualSwitch) devices.get(controlInfo)).toggle();
} else if (controlInfo.startsWith("F")) {
if (controlInfo.endsWith("+")) {
((SpeedController) devices.get(controlInfo.substring(0, controlInfo.length() - 1))).increaseStep();
} else if (controlInfo.endsWith("-")) {
((SpeedController) devices.get(controlInfo.substring(0, controlInfo.length() - 1))).decreaseStep();
}
} else if (controlInfo.startsWith("L")) {
String[] parts = controlInfo.split(":");
((ContinuousSpeedController) devices.get(parts[0])).setStep(Double.parseDouble(parts[1]));
}
}
private static void updateCurtainState(Map<String, CircuitDevice> devices) {
int totalLux = 0;
for (CircuitDevice device : devices.values()) {
if (device instanceof Light) {
((Light) device).updateBrightness();
totalLux += ((Light) device).brightness;
}
}
for (CircuitDevice device : devices.values()) {
if (device instanceof Curtain) {
((Curtain) device).updateOpenPercentage(totalLux);
}
}
}
private static void outputResults(Map<String, CircuitDevice> devices) {
List<String> outputOrder = Arrays.asList("K1", "K2", "K3", "B1", "B2", "D1", "D2", "H1");
for (String deviceId : outputOrder) {
CircuitDevice device = devices.get(deviceId);
if (device != null) {
if (device instanceof Switch) {
String state = ((Switch) device).state == 1 ? "closed" : "turned on";
System.out.println("@" + device.deviceId + ":" + state);
} else if (device instanceof MutualSwitch) {
String state = ((MutualSwitch) device).state == 0 ? "closed" : "turned on";
System.out.println("@" + device.deviceId + ":" + state);
} else if (device instanceof Light) {
((Light) device).updateBrightness();
System.out.println("@" + device.deviceId + ":" + ((Light) device).brightness);
} else if (device instanceof SpeedController) {
System.out.printf("@%s:%.2f%n", device.deviceId, ((SpeedController) device).steps / 100.0);
} else if (device instanceof Fan) {
((Fan) device).updateSpeed();
System.out.println("@" + device.deviceId + ":" + ((Fan) device).speed);
} else if (device instanceof Curtain) {
System.out.println("@" + device.deviceId + ":" + ((Curtain) device).openPercentage + "%");
}
}
}
}
}
SourceMonitor分析结果如下:
以下是代码的设计思路:
-
抽象类
CircuitDevice
:- 所有电路设备的抽象基类,包含设备标识
deviceId
,输入inputs
和输出outputs
的映射。 - 提供了
addInput
和addOutput
方法用于向设备输入和输出端口添加电压值。 - 声明了抽象方法
updateVoltage()
,用于更新设备的输出电压,具体实现由子类完成。
- 所有电路设备的抽象基类,包含设备标识
-
具体设备类:
-
开关 (
Switch
) 和 互斥开关 (MutualSwitch
):- 继承自
CircuitDevice
,实现了toggle()
方法以及updateVoltage()
方法,根据状态更新输出电压。
- 继承自
-
步进速度控制器 (
StepSpeedController
) 和 连续速度控制器 (ContinuousSpeedController
):- 继承自
SpeedController
抽象类,实现了具体的速度调节逻辑,使用不同的步进数或连续值来控制输出电压。
- 继承自
-
白炽灯 (
IncandescentLight
) 和 荧光灯 (FluorescentLight
):- 继承自
Light
抽象类,实现了updateBrightness()
方法来根据输入电压差计算亮度,并更新输出亮度值。
- 继承自
-
吊扇 (
CeilingFan
) 和 地扇 (FloorFan
):- 继承自
Fan
抽象类,实现了updateSpeed()
方法来根据输入电压差计算转速,并更新输出转速值。
- 继承自
-
窗帘 (
Curtain
):- 继承自
CircuitDevice
,实现了updateVoltage()
和updateOpenPercentage(int totalLux)
方法来根据输入电压差和总光照计算开启百分比。
- 继承自
-
-
电路类:
- 串联电路 (
SeriesCircuit
) 和 并联电路 (ParallelCircuit
):SeriesCircuit
包含多个电路设备,通过updateCircuit()
方法更新每个设备的电压输出。ParallelCircuit
包含多个串联电路,通过updateCircuit()
方法更新每个串联电路的电压输出。
- 串联电路 (
-
主类
Main
:Main
类负责整体的程序流程控制:- 通过
parseInput()
方法解析输入信息,识别电路、设备和控制指令,并创建相应的对象。 - 根据控制指令调用
applyControl()
方法操作设备状态或设置参数。 - 使用
updateCurtainState()
方法更新窗帘的状态,计算总光照并更新各设备的亮度或开启百分比。 - 最后使用
outputResults()
方法输出每个设备的状态或参数。
- 通过
- 面向对象设计:使用继承和多态,将设备和控制器归类,并根据其功能实现具体的方法。
- 数据结构选择:使用
Map
存储设备的输入和输出端口,以及列表来管理电路中的设备和串联电路。 - 输入处理和控制逻辑:通过正则表达式匹配和字符串处理,识别并解析输入指令,动态创建和操作对象。
- 状态更新和输出:设备状态的更新和结果的输出通过方法调用和条件判断实现,确保输出符合预期格式。
题目集8 7-1
7-1 家居强电电路模拟程序-4
分数 100
作者 蔡轲
单位 南昌航空大学
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。以下题目介绍中加粗的部分为本次迭代在“家居强电电路模拟程序-3”的基础上增加的功能要求。
1、控制设备
本题模拟的控制设备包括:开关、分档调速器、连续调速器、互斥开关。
开关:包括0和1两种状态。
开关有两个引脚,任意一个引脚都可以是输入引脚(接往电源端),而另一个则是输出引脚(接网接地端)。开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
互斥开关:
互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。
开关电路示意图如图1所示,左边是汇总引脚,编号为1;右边两个是分支引脚,右上的输出引脚为2,右下输出引脚为3。图中1、2、3引脚均可以是输入引脚,当1为输入引脚时,2、3引脚为输出引脚;1为输出引脚时,2、3引脚为输入引脚。
互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。
互斥开关的默认状态为1、2引脚接通,1、3引脚断开。
图1中所示的互斥开关可以反过来接入电路,即汇总引脚接往接地端,两个分支引脚接往电源端。
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104642859-1480060153.png)
图1 互斥开关
为避免短路,互斥开关设置了限流电阻,12引脚之间默认电阻为5,13引脚之间默认电阻为10。
分档调速器
按档位调整,常见的有3档、4档、5档调速器,档位值从0档-2(3/4)档变化。本次迭代模拟4档调速器,每个档位的输出电位分别为0、0.3、0.6、0.9倍的输入电压。
连续调速器
没有固定档位,按位置比例得到档位参数,数值范围在[0.00-1.00]之间,含两位小数。输出电位为档位参数乘以输入电压。
所有调速器都有两个引脚,一个固定的输入(引脚编号为1)、一个输出引脚(引脚编号为2)。当输入电位为0时,输出引脚输出的电位固定为0,不受各类开关调节的影响。
开关、调速器的初始状态/档位为0。
开关、调速器的输入引脚编号为1,输出引脚编号为2。
除互斥开关外,其他控制设备的电阻为 0。
2、受控设备
本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。
灯有两种工作状态:亮、灭。在亮的状态下,有的灯会因引脚电位差的不同亮度会有区别。
风扇在接电后有两种工作状态:停止、转动。风扇的转速会因引脚间电位差的不同而有区别。
本次迭代模拟两种灯具。
白炽灯:
亮度在0~200lux(流明)之间。
电位差为0-9V时亮度为0,其他电位差按比例,电位差10V对应50ux,220V对应200lux,其他电位差与对应亮度值成正比。白炽灯超过220V。
日光灯:
亮度为180lux。
只有两种状态,电位差为0时,亮度为0,电位差不为0,亮度为180。
本次迭代模拟两种风扇。
吊扇:
工作电压区间为80V-150V,对应转速区间为80-360转/分钟。80V对应转速为80转/分钟,150V对应转速为360转/分钟,超过150V转速为360转/分钟(本次迭代暂不考虑电压超标的异常情况)。其他电压值与转速成正比,输入输出电位差小于80V时转速为0。
落地扇:
工作电压区间为 80V-150V,对应转速区间为 80-360 转/分钟;[80V,100V) 对应转速为 80 转/分钟;[100,120)V 对应转速为 160 转/分钟;[120,140)V 对应转速为 260 转/分钟;大于等于 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)。
本次迭代模拟一种受控窗帘:
受控串联的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。
当电路中所有灯光的光照强度总和在[0,50)lux范围内,窗帘全开;
在[50,100)lux范围内,窗帘打开比例为0.8;
在[100,200)lux范围内,窗帘打开比例为0.6;
在[200,300)lux范围内,窗帘打开比例为0.4;
在[300,400)lux范围内,窗帘打开比例为0.2;
在400lux及以上范围内,窗帘关闭。
窗帘默认为关闭状态。
受控设备电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落地扇的电阻为 20,窗帘电阻为15。
3、输入信息
1)输入设备信息
分别用设备标识符K、F、L、B、R、D、A、H、S、P分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇、互斥开关、受控窗帘、二极管(见第6部分说明)。
设备标识用标识符+编号表示,如K1、F3、L2等。
引脚格式:
设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。
开关、分档调速器、连续调速器的输入引脚编号为1,输出引脚编号为2。
受控设备的两个引脚编号分别为1、2。
互斥开关的引脚编号已经在互斥开关的介绍部分说明。
约束条件:
不同设备的编号可以相同。
同种设备的编号可以不连续。
设备信息不单独输入,包含在连接信息中。
2)输入连接信息
一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。
格式:
"["+引脚号+" "+...+" "+引脚号+"]"
例如:[K1-1 K3-2 D5-1]表示K1的输入引脚,K3的输出引脚,D5的1号引脚连接在一起。
约束条件:
不考虑调速器串联到其他调速器的情况。
考虑各类设备的并联接入。例如,K1 的输出接到 L2 的输入,L2 的输出再接其他设备属于串联接线。K1 的输出接到 L2 的输出,同时 K1 的输入接到 L2 的输入,这种情况属于并联。
连接信息不单独输入,包含在线路信息中。
3)输入控制设备调节信息
开关、互斥开关调节信息格式:
#+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。
#+设备标识H+设备编号,例如:#H2,代表切换H2互斥开关的状态。
分档调速器的调节信息格式:
#+设备标识F+设备编号+"+" 代表加一档,例如:#F3+,代表F3输出加一档。
#+设备标识F+设备编号+"-" 代表减一档,例如:#F1-,代表F1输出减一档。
连续调速器的调节信息格式:
#+设备标识L+设备编号+":" +数值 代表将连续调速器的档位设置到对应数值,例如:#L3:0.6,代表L3输出档位参数0.6。
4)电源接地标识:
VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。
**
5)输入串联电路信息 **
一条串联电路占一行,串联电路信息由 n 个连接信息组成,连接信息按从靠电源端到接地端顺序依次输入,连接信息之间用英文空格" "分隔。
串联电路信息格式:
"#T"+电路编号+":"+连接信息+" "+连接信息+...+" "+连接信息
例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] 一个串联电路的第一个引脚是 IN,代表起始端,靠电源。最后一个引脚是 OUT,代表结尾端, 靠接地。
约束条件:
不同的串联电路信息编号不同。
输入的最后一条电路信息必定是总电路信息,总电路信息的起始引脚是 VCC,结束引脚是 GND。
连接信息中的引脚可能是一条串联或并联电路的 IN 或者 OUT。例如:
#T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT OUT]
#T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT]
6)输入并联电路信息
一条并联电路占一行,并联电路由其包含的几条串联电路组成,串联电路标识之间用英文空格" "分隔。
格式:
"#M"+电路编号+":"+”[”+串联电路信息+" "+....+" "+串联电路信息+”]”
例如:#M1:[T1 T2 T3]
该例声明了一个并联电路,由 T1、T2、T3 三条串联电路并联而成,三条串联电路的 IN 短 接在一起构成 M1 的 IN,三条串联电路的 OUT 短接在一起构成 M1 的 OUT。
在本题中,并联电路M中的串联电路可以包含别的并联电路。
约束条件:
本题不考虑输入电压或电压差超过220V的情况。
输入信息以end为结束标志,忽略end之后的输入信息。
本题中的并联信息所包含的串联电路的信息都在并联信息之前输入,不考虑乱序输入的情况。只要不因短路而造成无穷大的电流烧坏电路(如电路中的部分短接),都是合理情况,在测试点的考虑范围之内。会造成无穷大的电流的短路本次迭代不考虑。
本次迭代考虑多个并联电路串联在一起的情况。
本题考虑一条串联电路中包含其他串联电路的情况。例如:
#T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND]
本例中T1\T2两条串联电路是T3的一个部分,本题考虑这种类型的输入。
4、输出信息:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、互斥开关、受控窗帘、二极管(见第6部分说明)的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。
输出格式:
@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位)+" "+设备所有引脚的电压(按编号从小到大顺序依次输出,电压的小数部分直接丢弃,保留整数输出,电压之间用”-”分隔)
连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。
开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed
如:
@K1:turned on 32-15
@B1:190 68-17
@L1:0.60 220-176
互斥开关按1、2引脚的接通状态显示,1,2接通-1,3断开时显示closed,1,3接通-1,2断开时显示turned on。
如:
@H1:turned on
受控窗帘显示窗帘打开的百分比,如:
@S1:80%
5、家居电路模拟系列所有题目的默认规则
1)当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。
2)所有连接信息按电路从电源到接地的顺序依次输入,不会出现错位的情况。电源VCC一定是第一个连接的第一项,接地GND一定是最后一个连接的后一项。
3)连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。
4)调速器的输入端只会直连VCC,不会接其他设备。整个电路最多只有连接在电源上的一个调速器,且不包含在并联单路中。
6、本题新增内容:
1)增加管脚电压的显示
在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。(格式详见输出信息部分)
2)电流限制
电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。
例如:@B1:190 68-17 exceeding current limit error
本题各类电器的最大限定电流如下:
开关20、分档调速器18、连续调速器18、白炽灯9、日光灯5、吊扇12、落地扇14、互斥开关20、受控窗帘12、二极管8。
3)短路检测
如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”
4)并联电路中包含并联
本次迭代考虑并联电路中包含并联电路的情况,即构成并联电路的串联电路可以包含别的并联电路。例如如下输入的电路,并联电路M2的其中一条串联电路T4中包含了另一条并联电路M1:
#T1:[IN D2-1] [D2-2 H1-2] [H1-1 OUT]
#T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
5)二极管
增加二极管元件,其电路特性为:正向导通,反向截止;其电器符号如图4所示,当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104713985-170508124.png)
图2 二极管符号
二极管的标识符为’P’,左侧管脚编号为1,右侧管脚编号为2。
7、设计建议
本题包含以下电路图中的所有连接情况:
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104729662-223917956.png)
图3 电路示意图
1、电路设备类:描述所有电路设备的公共特征。
2、受控设备类、控制设备类:对应受控、控制设备
3、串联电路类:一条由多个电路设备构成的串联电路,也看成是一个独立的电路设备
4、并联电路类:继承电路设备类,也看成是一个独立的电路设备
其他类以及类的属性、方法自行设计。
![image](/i/l/?n=24&i=blog/3428862/202406/3428862-20240621104739544-120800233.png)
图4:建议设计类图
输入样例1:
在这里给出一组输入。例如:
#T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]
#T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
#T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT GND]
#K1
#K2
end
输出样例1:
在这里给出相应的输出。例如:
@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:turned on 220-0
@B1:200 220-0 exceeding current limit error
@D1:0 0-0
@H1:closed 0-0-0
@P2:cutoff 0-0
输入样例2:
在这里给出一组输入。例如:
#T1:[IN P2-1] [P2-2 H1-2] [H1-1 OUT]
#T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
#T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT GND]
#K1
#K3
#K2
end
输出样例2:
在这里给出相应的输出。例如:
@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:closed 220-220 exceeding current limit error
@B1:200 220-0 exceeding current limit error
@D1:0 220-220
@H1:closed 0-220-220 exceeding current limit error
@P2:conduction 220-220 exceeding current limit error
输入样例3:
在这里给出一组输入。例如:
#T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]
#T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
#T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT GND]
#K1
#K3
#K2
end
输出样例3:
在这里给出相应的输出。例如:
@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:closed 220-220
@B1:200 220-0 exceeding current limit error
@D1:0 220-220
@H1:closed 0-0-220
@P2:cutoff 0-220
输入样例4:
在这里给出一组输入。例如:
#T3:[VCC K2-1] [K2-2 GND]
#K2
end
输出样例4:
在这里给出相应的输出。例如:
short circuit error
代码长度限制
70 KB
时间限制
1500 ms
内存限制
64 MB
栈限制
8192 KB
代码如下:
import java.util.*;
import java.util.regex.*;
abstract class CircuitDevice {
String deviceId;
Map<Integer, Double> inputs = new HashMap<>();
Map<Integer, Double> outputs = new HashMap<>();
double resistance;
double maxCurrent;
CircuitDevice(String deviceId, double resistance, double maxCurrent) {
this.deviceId = deviceId;
this.resistance = resistance;
this.maxCurrent = maxCurrent;
}
void addInput(int pin, double voltage) {
inputs.put(pin, voltage);
}
void addOutput(int pin, double voltage) {
outputs.put(pin, voltage);
}
double getCurrent() {
double voltageDiff = inputs.values().stream().findFirst().orElse(0.0) - outputs.values().stream().findFirst().orElse(0.0);
return voltageDiff / (resistance == 0 ? 1 : resistance);
}
abstract void updateVoltage();
abstract void updateOutput();
}
class Switch extends CircuitDevice {
int state = 0; // 0: turned on, 1: closed
Switch(String deviceId) {
super(deviceId, 0, 20);
}
void toggle() {
state = 1 - state;
updateVoltage();
}
@Override
void updateVoltage() {
double inputVoltage = inputs.getOrDefault(1, 0.0);
double outputVoltage = state == 1 ? 0.0 : inputVoltage;
outputs.replaceAll((pin, voltage) -> outputVoltage);
}
@Override
void updateOutput() {
String stateStr = state == 1 ? "closed" : "turned on";
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = outputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%s %.0f-%.0f%s%n", deviceId, stateStr, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class MutualSwitch extends CircuitDevice {
int state = 0; // 0: 1-2 closed, 1: 1-3 closed
MutualSwitch(String deviceId) {
super(deviceId, 5, 20);
}
void toggle() {
state = 1 - state;
updateVoltage();
}
@Override
void updateVoltage() {
double inputVoltage = inputs.getOrDefault(1, 0.0);
outputs.replaceAll((pin, voltage) -> (pin == 2 && state == 0) || (pin == 3 && state == 1) ? inputVoltage : 0.0);
}
@Override
void updateOutput() {
String stateStr = state == 1 ? "turned on" : "closed";
double voltage1 = inputs.getOrDefault(1, 0.0);
double voltage2 = inputs.getOrDefault(2, 0.0);
double voltage3 = inputs.getOrDefault(3, 0.0);
double current = getCurrent();
System.out.printf("@%s:%s %.0f-%.0f-%.0f%s%n", deviceId, stateStr, voltage1, voltage2, voltage3, current > maxCurrent ? " exceeding current limit error" : "");
}
}
abstract class SpeedController extends CircuitDevice {
int steps = 0;
int maxSteps;
SpeedController(String deviceId, int maxSteps) {
super(deviceId, 0, 18);
this.maxSteps = maxSteps;
}
void increaseStep() {
if (steps < maxSteps) {
steps++;
}
updateVoltage();
}
void decreaseStep() {
if (steps > 0) {
steps--;
}
updateVoltage();
}
abstract void updateVoltage();
}
class StepSpeedController extends SpeedController {
StepSpeedController(String deviceId) {
super(deviceId, 3);
}
@Override
void updateVoltage() {
double[] voltageRatios = {0, 0.3, 0.6, 0.9};
outputs.replaceAll((pin, voltage) -> voltageRatios[steps] * inputs.getOrDefault(1, 0.0));
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = outputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%.2f %.0f-%.0f%s%n", deviceId, steps / 1.0, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class ContinuousSpeedController extends SpeedController {
ContinuousSpeedController(String deviceId) {
super(deviceId, 100);
}
void setStep(double stepValue) {
steps = (int) (stepValue * 100);
updateVoltage();
}
@Override
void updateVoltage() {
outputs.replaceAll((pin, voltage) -> (steps / 100.0) * inputs.getOrDefault(1, 0.0));
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = outputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%.2f %.0f-%.0f%s%n", deviceId, steps / 100.0, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
abstract class Light extends CircuitDevice {
int brightness = 0;
Light(String deviceId, double resistance, double maxCurrent) {
super(deviceId, resistance, maxCurrent);
}
abstract void updateBrightness();
}
class IncandescentLight extends Light {
IncandescentLight(String deviceId) {
super(deviceId, 10, 9);
}
@Override
void updateBrightness() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff > 220) {
voltageDiff = 220;
}
brightness = voltageDiff < 10 ? 0 : (int) ((voltageDiff - 10) * (200 / 210.0));
}
@Override
void updateVoltage() {
updateBrightness();
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = inputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%d %.0f-%.0f%s%n", deviceId, brightness, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class FluorescentLight extends Light {
FluorescentLight(String deviceId) {
super(deviceId, 5, 5);
}
@Override
void updateBrightness() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
brightness = voltageDiff != 0 ? 180 : 0;
}
@Override
void updateVoltage() {
updateBrightness();
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = inputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%d %.0f-%.0f%s%n", deviceId, brightness, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
abstract class Fan extends CircuitDevice {
int speed = 0;
Fan(String deviceId, double resistance, double maxCurrent) {
super(deviceId, resistance, maxCurrent);
}
abstract void updateSpeed();
}
class CeilingFan extends Fan {
CeilingFan(String deviceId) {
super(deviceId, 20, 12);
}
@Override
void updateSpeed() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff > 150) {
voltageDiff = 150;
}
speed = voltageDiff >= 80 ? (int) ((voltageDiff - 80) * (280 / 70.0)) + 80 : 0;
}
@Override
void updateVoltage() {
updateSpeed();
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = inputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%d %.0f-%.0f%s%n", deviceId, speed, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class FloorFan extends Fan {
FloorFan(String deviceId) {
super(deviceId, 20, 14);
}
@Override
void updateSpeed() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff >= 140) {
speed = 360;
} else if (voltageDiff >= 120) {
speed = 260;
} else if (voltageDiff >= 100) {
speed = 160;
} else if (voltageDiff >= 80) {
speed = 80;
} else {
speed = 0;
}
}
@Override
void updateVoltage() {
updateSpeed();
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = inputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%d %.0f-%.0f%s%n", deviceId, speed, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class Curtain extends CircuitDevice {
int openPercentage = 100;
Curtain(String deviceId) {
super(deviceId, 15, 12);
}
@Override
void updateVoltage() {
double voltageDiff = inputs.getOrDefault(1, 0.0) - inputs.getOrDefault(2, 0.0);
if (voltageDiff < 50) {
openPercentage = 100;
} else {
openPercentage = 0;
}
}
void updateOpenPercentage(int totalLux) {
if (totalLux < 50) {
openPercentage = 100;
} else if (totalLux < 100) {
openPercentage = 80;
} else if (totalLux < 200) {
openPercentage = 60;
} else if (totalLux < 300) {
openPercentage = 40;
} else if (totalLux < 400) {
openPercentage = 20;
} else {
openPercentage = 0;
}
}
@Override
void updateOutput() {
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = inputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%d%% %.0f-%.0f%s%n", deviceId, openPercentage, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class Diode extends CircuitDevice {
Diode(String deviceId) {
super(deviceId, Double.POSITIVE_INFINITY, 8);
}
@Override
void updateVoltage() {
double voltage1 = inputs.getOrDefault(1, 0.0);
double voltage2 = inputs.getOrDefault(2, 0.0);
if (voltage1 > voltage2) {
resistance = 0;
} else {
resistance = Double.POSITIVE_INFINITY;
}
}
@Override
void updateOutput() {
String state = resistance == 0 ? "conduction" : "cutoff";
double voltageIn = inputs.getOrDefault(1, 0.0);
double voltageOut = inputs.getOrDefault(2, 0.0);
double current = getCurrent();
System.out.printf("@%s:%s %.0f-%.0f%s%n", deviceId, state, voltageIn, voltageOut, current > maxCurrent ? " exceeding current limit error" : "");
}
}
class SeriesCircuit {
String circuitId;
List<CircuitDevice> devices = new ArrayList<>();
boolean shortCircuit = false;
SeriesCircuit(String circuitId) {
this.circuitId = circuitId;
}
void addDevice(CircuitDevice device) {
devices.add(device);
}
void updateCircuit() {
for (CircuitDevice device : devices) {
device.updateVoltage();
if (device.getCurrent() > device.maxCurrent * 10) {
shortCircuit = true;
}
}
}
}
class ParallelCircuit {
String circuitId;
List<SeriesCircuit> seriesCircuits = new ArrayList<>();
boolean shortCircuit = false;
ParallelCircuit(String circuitId) {
this.circuitId = circuitId;
}
void addSeriesCircuit(SeriesCircuit seriesCircuit) {
seriesCircuits.add(seriesCircuit);
}
void updateCircuit() {
for (SeriesCircuit seriesCircuit : seriesCircuits) {
seriesCircuit.updateCircuit();
if (seriesCircuit.shortCircuit) {
shortCircuit = true;
}
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> inputLines = new ArrayList<>();
String line;
while (!(line = scanner.nextLine()).equals("end")) {
inputLines.add(line);
}
scanner.close();
Map<String, SeriesCircuit> seriesCircuits = new HashMap<>();
Map<String, ParallelCircuit> parallelCircuits = new HashMap<>();
Map<String, CircuitDevice> devices = new HashMap<>();
parseInput(inputLines, seriesCircuits, parallelCircuits, devices);
boolean shortCircuit = false;
for (SeriesCircuit circuit : seriesCircuits.values()) {
circuit.updateCircuit();
if (circuit.shortCircuit) {
shortCircuit = true;
}
}
for (ParallelCircuit circuit : parallelCircuits.values()) {
circuit.updateCircuit();
if (circuit.shortCircuit) {
shortCircuit = true;
}
}
if (shortCircuit) {
System.out.println("short circuit error");
} else {
updateCurtainState(devices);
outputResults(devices);
}
}
private static void parseInput(List<String> inputLines, Map<String, SeriesCircuit> seriesCircuits, Map<String, ParallelCircuit> parallelCircuits, Map<String, CircuitDevice> devices) {
Pattern seriesPattern = Pattern.compile("#T(\\d+)");
Pattern parallelPattern = Pattern.compile("#M(\\d+)");
Pattern devicePattern = Pattern.compile("(\\w+)-(\\d+)");
Pattern controlPattern = Pattern.compile("#(\\w+(:?\\d+\\.\\d+)?)");
for (String line : inputLines) {
if (line.startsWith("#T")) {
Matcher seriesMatcher = seriesPattern.matcher(line);
if (seriesMatcher.find()) {
String circuitId = seriesMatcher.group(1);
SeriesCircuit seriesCircuit = new SeriesCircuit(circuitId);
seriesCircuits.put(circuitId, seriesCircuit);
Matcher deviceMatcher = devicePattern.matcher(line);
while (deviceMatcher.find()) {
String deviceId = deviceMatcher.group(1);
if (!devices.containsKey(deviceId)) {
devices.put(deviceId, createDevice(deviceId));
}
seriesCircuit.addDevice(devices.get(deviceId));
}
}
} else if (line.startsWith("#M")) {
Matcher parallelMatcher = parallelPattern.matcher(line);
if (parallelMatcher.find()) {
String circuitId = parallelMatcher.group(1);
ParallelCircuit parallelCircuit = new ParallelCircuit(circuitId);
parallelCircuits.put(circuitId, parallelCircuit);
Matcher seriesMatcher = seriesPattern.matcher(line);
while (seriesMatcher.find()) {
String seriesId = seriesMatcher.group(1);
parallelCircuit.addSeriesCircuit(seriesCircuits.get(seriesId));
}
}
} else if (line.startsWith("#")) {
Matcher controlMatcher = controlPattern.matcher(line);
if (controlMatcher.find()) {
String controlInfo = controlMatcher.group(1);
applyControl(devices, controlInfo);
}
}
}
}
private static CircuitDevice createDevice(String deviceId) {
switch (deviceId.charAt(0)) {
case 'K':
return new Switch(deviceId);
case 'F':
return new StepSpeedController(deviceId);
case 'L':
return new ContinuousSpeedController(deviceId);
case 'B':
return new IncandescentLight(deviceId);
case 'R':
return new FluorescentLight(deviceId);
case 'D':
return new CeilingFan(deviceId);
case 'A':
return new FloorFan(deviceId);
case 'H':
return new MutualSwitch(deviceId);
case 'S':
return new Curtain(deviceId);
case 'P':
return new Diode(deviceId);
default:
throw new IllegalArgumentException("Unknown device type: " + deviceId);
}
}
private static void applyControl(Map<String, CircuitDevice> devices, String controlInfo) {
if (controlInfo.startsWith("K")) {
((Switch) devices.get(controlInfo)).toggle();
} else if (controlInfo.startsWith("H")) {
((MutualSwitch) devices.get(controlInfo)).toggle();
} else if (controlInfo.startsWith("F")) {
if (controlInfo.endsWith("+")) {
((SpeedController) devices.get(controlInfo.substring(0, controlInfo.length() - 1))).increaseStep();
} else if (controlInfo.endsWith("-")) {
((SpeedController) devices.get(controlInfo.substring(0, controlInfo.length() - 1))).decreaseStep();
}
} else if (controlInfo.startsWith("L")) {
String[] parts = controlInfo.split(":");
((ContinuousSpeedController) devices.get(parts[0])).setStep(Double.parseDouble(parts[1]));
}
}
private static void updateCurtainState(Map<String, CircuitDevice> devices) {
int totalLux = 0;
for (CircuitDevice device : devices.values()) {
if (device instanceof Light) {
((Light) device).updateBrightness();
totalLux += ((Light) device).brightness;
}
}
for (CircuitDevice device : devices.values()) {
if (device instanceof Curtain) {
((Curtain) device).updateOpenPercentage(totalLux);
}
}
}
private static void outputResults(Map<String, CircuitDevice> devices) {
List<String> outputOrder = Arrays.asList("K1", "K2", "K3", "B1", "B2", "D1", "D2", "H1");
for (String deviceId : outputOrder) {
CircuitDevice device = devices.get(deviceId);
if (device != null) {
device.updateOutput();
}
}
}
}
SourceMonitor分析结果如下:
以下是代码的设计思路:
-
抽象类
CircuitDevice
:- 所有电路设备的基类,包含设备的基本属性和方法。
inputs
和outputs
是用于存储输入和输出电压的映射。getCurrent()
方法计算设备的电流,根据电压差和电阻计算。
-
具体设备类(如
Switch
、MutualSwitch
等):- 每个设备类继承自
CircuitDevice
,实现了具体设备的特定逻辑。 Switch
和MutualSwitch
类处理开关的不同状态和电压输出。SpeedController
的子类StepSpeedController
和ContinuousSpeedController
处理速度控制器的逻辑,允许增加和减少步数或者设置具体步数。
- 每个设备类继承自
-
灯光和风扇类:
Light
和Fan
是抽象类,具体实现类如IncandescentLight
、FluorescentLight
、CeilingFan
和FloorFan
分别实现了不同类型灯光和风扇的功能。- 每个灯光类和风扇类实现了
updateBrightness()
或updateSpeed()
方法来更新亮度或速度,并且实现了updateOutput()
方法来输出设备的状态。
-
窗帘类
Curtain
和Diode
类:Curtain
类根据光强来更新开合状态。Diode
类根据输入端的电压来切换导通或截止状态。
-
电路类:
SeriesCircuit
和ParallelCircuit
分别模拟串联和并联电路的行为。SeriesCircuit
通过更新每个设备的电压来检测短路。ParallelCircuit
包含多个SeriesCircuit
实例,并检查其中是否有短路。
-
主程序
Main
类:Main
类包含main()
方法,负责解析输入、创建电路设备和控制信息,并模拟整个电路系统的运行。parseInput()
方法解析输入数据,根据不同的输入行创建相应的电路设备和控制信息。applyControl()
方法根据控制信息操作设备状态。updateCurtainState()
方法根据灯光的亮度更新窗帘的开合状态。outputResults()
方法按特定顺序输出设备的状态信息。
- 多态性:通过继承和方法重写实现不同设备类型的特定行为,例如开关、速度控制器、灯光和风扇等。
- 数据结构:使用
Map
存储设备和电路信息,便于快速访问和操作。 - 输入输出管理:每个设备类通过重写
updateVoltage()
和updateOutput()
方法来更新状态和输出设备信息。 - 异常处理:在设备类中处理可能出现的异常情况,确保电路模拟的准确性和稳定性。
(3)采坑心得
对于题目集7和题目集8,在理解和编写上述代码时,可能会遇到一些常见的踩坑情况,这些情况需要特别注意和处理:类型转换和多态使用,在 Main
类中,根据设备的 deviceId
创建相应的 CircuitDevice
对象时,需要确保正确使用多态。例如,使用 SpeedController
类型操作不同子类的对象,确保转型正确和安全。Map 的使用和空指针异常,在设备的输入输出映射中使用 HashMap
,需要注意对可能为 null
的值进行处理。例如,在 updateVoltage()
方法中,使用 inputs.getOrDefault()
来避免空指针异常。正则表达式和字符串处理的准确性,在 parseInput()
方法中使用正则表达式解析输入信息时,确保正则表达式能够准确地匹配所有可能的输入情况。同时,处理字符串分割和索引时,确保不会越界或出现异常情况。抽象类和抽象方法的正确实现,对于抽象类 CircuitDevice
和其子类,确保每个子类实现了抽象方法 updateVoltage()
,并正确地根据自身逻辑更新输出。避免忽略或错误实现抽象方法导致程序运行异常或不符合预期。控制信息的正确解析和应用,parseInput()
方法负责解析输入的配置信息,并创建对应的电路设备和控制指令。确保正则表达式和匹配逻辑正确,以及设备创建和控制指令的应用正确。状态管理的一致性,每个设备类中的状态变量(如开关状态 state
、速度步数 steps
、亮度 brightness
等)需要确保在状态变更时更新相应的输出。特别是涉及到状态切换的设备,如开关和速度控制器,必须确保状态更新后调用 updateVoltage()
方法来刷新输出状态。输出结果的正确性,在 outputResults()
方法中,确保根据设备类型正确输出状态或参数。例如,对于 Switch
和 MutualSwitch
类型的设备,根据状态输出正确的开关状态;对于灯光和风扇类设备,更新状态后输出正确的亮度和速度值。异常处理和边界情况,考虑程序运行中可能出现的异常情况,例如输入数据不完整、格式错误等,需要添加适当的异常处理机制,如捕获和处理 IllegalArgumentException
或 NullPointerException
。
(4)改进建议
1.对于题目集7,对上述代码进行改进可以考虑以下几个方面,以提升代码的可读性、可维护性和性能:将 CircuitDevice
类改为接口,而不是抽象类,因为接口更适合定义行为而不是状态。这样可以减少类的复杂性,并使得每个设备类可以更灵活地实现接口方法。考虑在输入输出映射中使用更适合需求的数据结构。例如,如果需要频繁地更新和访问映射中的数据,可以考虑使用 LinkedHashMap
或 TreeMap
,以便于按顺序或排序方式访问数据。考虑引入状态管理器或状态模式,以更统一和清晰地管理设备的状态变化和输出更新。这样可以避免每个设备类中都要单独处理状态变化和输出更新逻辑的重复代码。在 createDevice()
方法中,可以考虑使用工厂模式或者反射机制来动态创建设备对象,而不是使用多个 if-else 判断。这样可以使代码更加灵活和扩展性更好。在 parseInput()
和 applyControl()
方法中,可以进一步优化正则表达式的使用,确保能够准确解析和应用各种控制信息。此外,可以考虑使用枚举来管理和识别不同类型的控制命令,以增强代码的清晰度和可维护性。
2.对于题目集8,对上述代码的改进建议包括以下几个方面:在设备类的 getCurrent()
方法中,应该考虑更多的异常情况处理,例如防止除以零(如果电阻为零时),或者当输入输出映射中缺少必需的键时进行适当的处理,以避免空指针异常或意外的行为。考虑引入更严格的输入输出管理机制。目前的实现中,设备类使用了 inputs
和 outputs
映射,但没有明确的检查和处理输入输出数据的格式或合理性。可以考虑使用数据验证或者更复杂的输入输出管理类来增强稳健性和可维护性。每个设备类的更新方法 (updateVoltage()
和 updateOutput()
) 可能可以进一步解耦和重构,以减少重复代码和提高可读性。例如,可以考虑提取公共的电压计算或输出更新逻辑为独立的方法或组件。某些设备类的计算逻辑可能可以进一步优化,以提高效率和性能。例如,在计算电流或电压差异时,可以考虑使用更高效的数据结构或算法来处理数据。通过实施上述改进建议,可以使得代码更加健壮、易读和易于扩展,从而满足更广泛的模拟电路需求,并提供更高质量的输出和更好的用户体验。
(5)总结
通过本阶段两次题目集的训练,我深入理解了Java面向对象编程的核心概念,如继承、多态、抽象类、接口等,并将它们应用于实际的电路设备模拟中,通过实现各种电路设备的更新逻辑,加深了对电路模拟算法的理解,特别是在计算电流、电压以及控制设备状态时的具体实现方式。我同时学会了如何在面向对象的环境中处理异常情况,尤其是在输入输出不一致或者设备状态异常时的处理方式,提高了代码的健壮性和可靠性。通过优化设备更新逻辑和状态计算算法,我学习到了如何提高代码的效率和性能,尤其是在处理大量数据或频繁更新状态时的技巧。但我还有不少不足和改进空间,在某些地方,可能存在重复的代码片段或者逻辑冗余,例如设备状态更新的部分。这需要更进一步的抽象和重构,以减少代码的重复性。初期的设计可能没有考虑到所有的需求和可能的扩展性,导致后续需要频繁地进行修改和调整。更完善的设计和需求分析阶段能够减少这种情况的发生。尽管在一些地方实现了基本的错误处理,但在处理输入输出错误或者不合理的情况时,仍有改进空间,应该更加细致地考虑边界条件和异常情况。综上所述,通过编写这样的代码项目,我不仅学到了很多关于面向对象设计和设计模式的知识,也发现了自己在代码优化、性能提升需要继续改进的空间。这些经验将有助于我在未来的项目中更加高效和专业地应对类似的编程挑战,并且能让我在未来的编程道路上走的更长远。
标签:总结性,引脚,double,void,PTA,Blog,电路,deviceId,设备 From: https://www.cnblogs.com/23201537zx/p/18255541