如何优化找零C程序的硬币模块,实现高复用、低耦合与高内聚?
C找零程序优化实现方案
核心优化思路
- 用常量结构体统一封装每种货币的核心配置(硬币面值、校验规则等)
- 实现通用找零计算函数,依赖配置完成逻辑,彻底消除重复代码
- 主交互逻辑通过选择不同配置实现多货币支持,模块间耦合度极低
1. 定义货币配置常量
通过结构体存储三种货币的所有专属配置,包括面值数组、校验规则:
#include <stdio.h> #include <stdbool.h> // 货币配置结构体:封装每种货币的专属属性 typedef struct { const char* name; const int denominations[6]; // 预留空间适配最多面值数量(Euro有6种) const int denom_count; bool (*validate_amount)(int); // 金额校验函数指针 } CurrencyConfig; // AUD专属金额校验:必须是5的倍数且在1-95之间 bool validate_aud(int amount) { return (amount >= 1 && amount <= 95) && (amount % 5 == 0); } // USD/Euro通用金额校验:仅需在1-95之间 bool validate_general(int amount) { return amount >= 1 && amount <= 95; } // 定义各货币的常量配置(只读,避免意外修改) const CurrencyConfig USD_CONFIG = { .name = "USD", .denominations = {25, 10, 5, 1}, .denom_count = 4, .validate_amount = validate_general }; const CurrencyConfig AUD_CONFIG = { .name = "AUD", .denominations = {50, 20, 10, 5}, .denom_count = 4, .validate_amount = validate_aud }; const CurrencyConfig EURO_CONFIG = { .name = "Euro", .denominations = {50, 20, 10, 5, 2, 1}, .denom_count = 6, .validate_amount = validate_general };
2. 实现通用找零计算函数
这是核心复用逻辑,所有货币共享同一套计算代码,仅依赖传入的配置:
// 通用找零计算:根据货币配置返回最少硬币数,非法金额返回-1 int calculate_min_coins(const CurrencyConfig* config, int amount) { if (!config->validate_amount(amount)) { return -1; } int coin_count = 0; int remaining = amount; // 从大面值到小面值遍历,保证最少硬币数 for (int i = 0; i < config->denom_count; i++) { while (remaining >= config->denominations[i]) { remaining -= config->denominations[i]; coin_count++; } if (remaining == 0) break; } return coin_count; }
3. 重构主交互逻辑
主流程只负责用户交互、选择配置、调用通用函数,逻辑清晰:
void run_change_program() { char continue_choice; do { // 选择货币类型 printf("请选择货币类型:\n"); printf("1. USD\n2. AUD\n3. Euro\n"); int currency_choice; scanf("%d", ¤cy_choice); const CurrencyConfig* selected_config = NULL; switch (currency_choice) { case 1: selected_config = &USD_CONFIG; break; case 2: selected_config = &AUD_CONFIG; break; case 3: selected_config = &EURO_CONFIG; break; default: printf("无效的货币选择,请重新输入\n"); continue; } // 输入金额 printf("请输入金额(1-95分,AUD需为5的倍数):"); int amount; scanf("%d", &amount); // 计算并输出结果 int result = calculate_min_coins(selected_config, amount); if (result == -1) { printf("输入的金额不符合%s的要求\n", selected_config->name); } else { printf("%s找零最少需要%d枚硬币\n", selected_config->name, result); } // 询问是否继续 printf("是否继续操作?(y/n):"); scanf(" %c", &continue_choice); // 空格处理输入缓冲区的换行符 } while (continue_choice == 'y' || continue_choice == 'Y'); } int main() { run_change_program(); return 0; }
优化后的核心优势
- 代码复用:找零计算逻辑仅实现一次,三种货币完全共享,避免重复代码维护
- 低耦合:新增/修改货币只需添加/修改对应的
CurrencyConfig常量,无需改动核心计算函数 - 高内聚:货币配置、金额校验、找零计算各自封装,职责单一清晰
内容的提问来源于stack exchange,提问作者Dragon
相关产品推荐
相关产品推荐

