1. 识别并消除重复代码块
任务说明
给定一个嵌入式C源文件,其中包含三处高度相似的代码块:分别对三组不同传感器原始值进行滤波、刻度转换并更新状态结构体。要求提取公共逻辑为独立函数,消除重复代码,同时保持行为完全一致。
重构前代码
/* sensor.c — 重构前:包含三份重复代码块 */
#include <stdint.h>
typedef struct {
uint16_t raw;
uint16_t filtered;
int16_t scaled;
uint8_t valid;
} sensor_t;
static sensor_t temp_sensor, press_sensor, humid_sensor;
void update_temp_sensor(uint16_t raw_value) {
uint32_t sum = 0;
for (int i = 0; i < 4; i++) { /* 简单滑动平均 */
sum += raw_value;
}
temp_sensor.raw = raw_value;
temp_sensor.filtered = (uint16_t)(sum / 4);
temp_sensor.scaled = (int16_t)(temp_sensor.filtered * 10 / 4); /* 温度: 0.1°C/LSB */
temp_sensor.valid = (temp_sensor.filtered > 100) ? 1 : 0;
}
void update_press_sensor(uint16_t raw_value) {
uint32_t sum = 0;
for (int i = 0; i < 4; i++) {
sum += raw_value;
}
press_sensor.raw = raw_value;
press_sensor.filtered = (uint16_t)(sum / 4);
press_sensor.scaled = (int16_t)(press_sensor.filtered * 25 / 10); /* 压力: 0.1kPa/LSB */
press_sensor.valid = (press_sensor.filtered > 50) ? 1 : 0;
}
void update_humid_sensor(uint16_t raw_value) {
uint32_t sum = 0;
for (int i = 0; i < 4; i++) {
sum += raw_value;
}
humid_sensor.raw = raw_value;
humid_sensor.filtered = (uint16_t)(sum / 4);
humid_sensor.scaled = (int16_t)(humid_sensor.filtered * 5 / 2); /* 湿度: 0.1%RH/LSB */
humid_sensor.valid = (humid_sensor.filtered > 200) ? 1 : 0;
}
重构后代码
/* sensor.c — 重构后:提取公共处理函数 */
#include <stdint.h>
typedef struct {
uint16_t raw;
uint16_t filtered;
int16_t scaled;
uint8_t valid;
} sensor_t;
static sensor_t temp_sensor, press_sensor, humid_sensor;
/* 公共处理:滑动平均滤波 + 刻度转换 + 有效性判断 */
static void process_sensor(sensor_t *s, uint16_t raw_value,
uint16_t scale_num, uint16_t scale_den,
uint16_t valid_threshold) {
uint32_t sum = 0;
for (int i = 0; i < 4; i++) {
sum += raw_value;
}
s->raw = raw_value;
s->filtered = (uint16_t)(sum / 4);
s->scaled = (int16_t)((uint32_t)s->filtered * scale_num / scale_den);
s->valid = (s->filtered > valid_threshold) ? 1 : 0;
}
void update_temp_sensor(uint16_t raw_value) {
process_sensor(&temp_sensor, raw_value, 10, 4, 100);
}
void update_press_sensor(uint16_t raw_value) {
process_sensor(&press_sensor, raw_value, 25, 10, 50);
}
void update_humid_sensor(uint16_t raw_value) {
process_sensor(&humid_sensor, raw_value, 5, 2, 200);
}
重构要点
- 三份重复代码的差异仅为:目标结构体指针、刻度转换系数(分子/分母)、有效性阈值。将这些差异参数化后提取为
process_sensor()。 - 滤波窗口(4次平均)与原始值读取逻辑完全一致,属于纯重复部分,直接合并。
- 刻度转换使用
uint32_t中间量避免16位乘法溢出(原代码中filtered * 25可能超过16位范围,重构后显式提升精度)。 - 对外接口
update_*_sensor()保持不变,调用方无需任何修改。
验证方法
- 将重构前后代码分别编译(
gcc -c sensor.c),确认无警告错误。 - 编写测试桩:对同一组输入分别调用重构前/后的三个更新函数,比较各结构体字段(
raw、filtered、scaled、valid)是否完全一致。 - 边界测试:输入
raw_value = 0、65535、阈值临界值(如温度阈值100,输入使filtered恰好为100和101),确认行为一致。 - 通过条件:所有测试用例中,重构前后各传感器结构体字段逐一相等,且
scaled值无符号溢出。
重构后代码行数由约45行降至约30行,且新增传感器类型时只需增加一个sensor_t实例和一个调用process_sensor()的薄封装,无需复制整段处理逻辑。