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()保持不变,调用方无需任何修改。

验证方法

  1. 将重构前后代码分别编译(gcc -c sensor.c),确认无警告错误。
  2. 编写测试桩:对同一组输入分别调用重构前/后的三个更新函数,比较各结构体字段(raw、filtered、scaled、valid)是否完全一致。
  3. 边界测试:输入raw_value = 0、65535、阈值临界值(如温度阈值100,输入使filtered恰好为100和101),确认行为一致。
  4. 通过条件:所有测试用例中,重构前后各传感器结构体字段逐一相等,且scaled值无符号溢出。

重构后代码行数由约45行降至约30行,且新增传感器类型时只需增加一个sensor_t实例和一个调用process_sensor()的薄封装,无需复制整段处理逻辑。