改进用于确定可用值的strcmp() if/else阶梯结构
更高效的月份字符串转数值方案
当然有比嵌套if/else+反复调用strcmp()更优的方案,既能提升查找效率,又能简化代码、轻松处理缩写/大小写变体,下面是几种实用的实现思路:
1. 哈希表映射(O(1) 查找效率)
哈希表是最快的方案,查找时间复杂度接近常数。C标准库没有内置哈希表,但可以用轻量的第三方库(比如uthash)或者自己实现简单的哈希映射逻辑,把所有月份全称、缩写(如"March"、"MAR"、"Mar")和对应的数值绑定,一次查找就能得到结果。
示例代码(基于uthash):
#include <stdio.h> #include <string.h> #include "uthash.h" typedef struct { char *name; int month; UT_hash_handle hh; } MonthMap; MonthMap *map = NULL; void init_month_map() { // 批量插入所有月份的全称、缩写 MonthMap entries[] = { {"January", 1}, {"Jan", 1}, {"JAN", 1}, {"February", 2}, {"Feb", 2}, {"FEB", 2}, {"March", 3}, {"Mar", 3}, {"MAR", 3}, // ... 其他月份同理 {"December", 12}, {"Dec", 12}, {"DEC", 12} }; int i; for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) { MonthMap *entry = malloc(sizeof(MonthMap)); entry->name = strdup(entries[i].name); entry->month = entries[i].month; HASH_ADD_STR(map, name, entry); } } int get_month_from_str(const char *str) { MonthMap *entry; HASH_FIND_STR(map, str, entry); return entry ? entry->month : -1; // 找不到返回-1 } // 使用示例 int main() { init_month_map(); printf("%d\n", get_month_from_str("April")); // 输出4 printf("%d\n", get_month_from_str("MAR")); // 输出3 return 0; }
优点:查找速度最快,添加/修改月份变体非常灵活;缺点:需要引入第三方哈希库,或者自己实现哈希函数(比如基于字符串首字符+长度的简单哈希)。
2. 预排序数组+二分查找(O(log n) 查找效率)
把所有月份名称(含缩写)存入结构体数组,提前排序后用标准库的bsearch()函数进行二分查找,效率远高于线性的if/else阶梯,代码也更整洁。
示例代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { const char *name; int month; } MonthEntry; // 所有月份的全称、缩写,按字典序排序 MonthEntry month_list[] = { {"April", 4}, {"Apr", 4}, {"APR", 4}, {"August", 8}, {"Aug", 8}, {"AUG", 8}, {"December", 12}, {"Dec", 12}, {"DEC", 12}, // ... 其他月份按字典序排列 {"March", 3}, {"Mar", 3}, {"MAR", 3} }; // 二分查找的比较函数 int compare_month(const void *a, const void *b) { return strcmp(((MonthEntry*)a)->name, ((MonthEntry*)b)->name); } int get_month_from_str(const char *str) { MonthEntry key = {str, 0}; MonthEntry *result = bsearch(&key, month_list, sizeof(month_list)/sizeof(month_list[0]), sizeof(MonthEntry), compare_month); return result ? result->month : -1; } // 使用示例 int main() { printf("%d\n", get_month_from_str("February")); // 输出2 printf("%d\n", get_month_from_str("Feb")); // 输出2 return 0; }
优点:无需第三方库,依赖标准库即可实现,代码可移植性强;缺点:数组必须提前按字典序排序,新增变体后需要重新排序。
3. 前缀分支优化(轻量场景首选)
如果不想引入额外数据结构,可以利用月份名称的前缀特征快速缩小范围,减少strcmp()的调用次数,代码比全量if/else简洁很多,同时提升效率。
示例代码:
#include <stdio.h> #include <string.h> #include <ctype.h> // 先统一转小写,避免大小写敏感 void str_tolower(char *str) { while (*str) { *str = tolower((unsigned char)*str); str++; } } int get_month_from_str(char *str) { str_tolower(str); switch(str[0]) { case 'j': if (strcmp(str, "january") == 0 || strcmp(str, "jan") == 0) return 1; if (strcmp(str, "june") == 0 || strcmp(str, "jun") == 0) return 6; if (strcmp(str, "july") == 0 || strcmp(str, "jul") == 0) return 7; break; case 'f': if (strcmp(str, "february") == 0 || strcmp(str, "feb") == 0) return 2; break; case 'm': if (strcmp(str, "march") == 0 || strcmp(str, "mar") == 0) return 3; if (strcmp(str, "may") == 0) return 5; break; // ... 其他首字母分支同理 case 'd': if (strcmp(str, "december") == 0 || strcmp(str, "dec") == 0) return 12; break; } return -1; }
优点:无需额外数据结构,代码轻量,适合资源受限的场景;缺点:查找效率略低于前两种方案,新增变体需要手动修改分支。
另外,无论用哪种方案,建议先将输入字符串统一转为小写(或大写),避免大小写敏感的问题,比如把"MAR"、"Mar"都转为"mar"再匹配。
内容的提问来源于stack exchange,提问作者user17592432
相关产品推荐
相关产品推荐

