4. 案例4
任务说明
本案例提供一个存在路由选择错误的音频通路管理模块。该模块根据当前音频策略(如通话、媒体、铃声)选择输出设备,但代码中路由判断逻辑存在缺陷,导致音频始终流向默认设备。你的任务是定位错误的路由选择逻辑,修正后使音频能根据策略正确路由到对应设备(扬声器或耳机)。
问题代码
// audio_router.c
#include <stdbool.h>
#include <string.h>
typedef enum {
DEVICE_SPEAKER = 0,
DEVICE_HEADSET = 1,
DEVICE_BLUETOOTH = 2
} audio_device_t;
typedef enum {
POLICY_MEDIA = 0,
POLICY_CALL = 1,
POLICY_RING = 2
} audio_policy_t;
typedef struct {
audio_policy_t policy;
bool headset_connected;
bool bluetooth_connected;
} audio_state_t;
// 当前路由选择函数(存在逻辑错误)
audio_device_t select_route(audio_state_t *state) {
audio_device_t device = DEVICE_SPEAKER;
// 错误点1:条件判断使用赋值而非相等比较
if (state->policy = POLICY_CALL) {
// 错误点2:通话策略下未优先检查蓝牙
if (state->headset_connected) {
device = DEVICE_HEADSET;
}
} else if (state->policy == POLICY_RING) {
// 错误点3:铃声策略下错误地优先选择扬声器
device = DEVICE_SPEAKER;
if (state->headset_connected) {
device = DEVICE_HEADSET;
}
} else {
// 媒体策略
if (state->bluetooth_connected) {
device = DEVICE_BLUETOOTH;
} else if (state->headset_connected) {
device = DEVICE_HEADSET;
}
}
return device;
}
路由规则要求
- 通话策略:优先蓝牙 → 其次耳机 → 最后扬声器
- 铃声策略:优先耳机 → 其次扬声器(不使用蓝牙)
- 媒体策略:优先蓝牙 → 其次耳机 → 最后扬声器
修正后的代码
// audio_router_fixed.c
#include <stdbool.h>
#include <string.h>
typedef enum {
DEVICE_SPEAKER = 0,
DEVICE_HEADSET = 1,
DEVICE_BLUETOOTH = 2
} audio_device_t;
typedef enum {
POLICY_MEDIA = 0,
POLICY_CALL = 1,
POLICY_RING = 2
} audio_policy_t;
typedef struct {
audio_policy_t policy;
bool headset_connected;
bool bluetooth_connected;
} audio_state_t;
// 修正后的路由选择函数
audio_device_t select_route(audio_state_t *state) {
audio_device_t device = DEVICE_SPEAKER;
if (state->policy == POLICY_CALL) {
// 通话:蓝牙优先
if (state->bluetooth_connected) {
device = DEVICE_BLUETOOTH;
} else if (state->headset_connected) {
device = DEVICE_HEADSET;
} else {
device = DEVICE_SPEAKER;
}
} else if (state->policy == POLICY_RING) {
// 铃声:耳机优先,不使用蓝牙
if (state->headset_connected) {
device = DEVICE_HEADSET;
} else {
device = DEVICE_SPEAKER;
}
} else {
// 媒体:蓝牙优先
if (state->bluetooth_connected) {
device = DEVICE_BLUETOOTH;
} else if (state->headset_connected) {
device = DEVICE_HEADSET;
} else {
device = DEVICE_SPEAKER;
}
}
return device;
}
验证方法
编写以下测试用例并编译运行,确认输出与预期一致:
// test_router.c
#include <stdio.h>
#include <assert.h>
// 此处粘贴修正后的 select_route 及类型定义
int main() {
audio_state_t st;
// 测试1:通话 + 蓝牙已连接 → 应选蓝牙
st.policy = POLICY_CALL;
st.headset_connected = false;
st.bluetooth_connected = true;
assert(select_route(&st) == DEVICE_BLUETOOTH);
// 测试2:通话 + 仅耳机 → 应选耳机
st.policy = POLICY_CALL;
st.headset_connected = true;
st.bluetooth_connected = false;
assert(select_route(&st) == DEVICE_HEADSET);
// 测试3:通话 + 无外设 → 应选扬声器
st.policy = POLICY_CALL;
st.headset_connected = false;
st.bluetooth_connected = false;
assert(select_route(&st) == DEVICE_SPEAKER);
// 测试4:铃声 + 耳机已连接 → 应选耳机(即使蓝牙也连接)
st.policy = POLICY_RING;
st.headset_connected = true;
st.bluetooth_connected = true;
assert(select_route(&st) == DEVICE_HEADSET);
// 测试5:铃声 + 无耳机 → 应选扬声器
st.policy = POLICY_RING;
st.headset_connected = false;
st.bluetooth_connected = true;
assert(select_route(&st) == DEVICE_SPEAKER);
// 测试6:媒体 + 蓝牙已连接 → 应选蓝牙
st.policy = POLICY_MEDIA;
st.headset_connected = true;
st.bluetooth_connected = true;
assert(select_route(&st) == DEVICE_BLUETOOTH);
// 测试7:媒体 + 仅耳机 → 应选耳机
st.policy = POLICY_MEDIA;
st.headset_connected = true;
st.bluetooth_connected = false;
assert(select_route(&st) == DEVICE_HEADSET);
printf("全部测试通过:路由选择逻辑正确\n");
return 0;
}
编译与运行
gcc -o test_router test_router.c -Wall
./test_router
程序输出 全部测试通过:路由选择逻辑正确 即表示修正成功。若断言失败,程序会中止并提示对应行号。
错误根因总结
- 赋值代替比较:
if (state->policy = POLICY_CALL)将常量赋给变量,表达式值恒为真,导致所有策略都进入通话分支。 - 优先级缺失:通话分支未检查蓝牙连接状态,导致蓝牙设备无法被选中。
- 铃声策略错误:铃声分支先设扬声器再判断耳机,逻辑上虽能工作但顺序混乱;且未明确排除蓝牙,实际因赋值错误从未进入此分支。