不使用strcat时,如何通过分块strncmp并组合结果模拟strcmp的行为?
不使用strcat时,如何通过分块strncmp并组合结果模拟strcmp的行为?
哈哈,这个问题确实戳中了strcmp规则的“模糊地带”!我之前做字符串匹配优化的时候也碰到过类似需求——不想用strcat拼接(怕额外内存分配或者性能损耗),但又要精准模拟完整strcmp的行为,核心难点就是不能依赖strcmp的具体返回值,只能看它是负、零还是正,还要处理各种长度边界的情况。
先给你理清楚核心逻辑,再直接上可运行的代码:
首先,我们得明确strcmp的底层规则,这是所有逻辑的基础:
- 从第一个字符开始逐位比较,直到找到第一个不同的字符,返回该字符的差值(但标准只要求返回负、零、正,具体数值不做保证)
- 如果前面所有字符都相同,短的字符串更小,返回负(如果自身更短)或正(如果自身更长),完全相同则返回零
基于这个规则,我们可以把分块比较的逻辑拆成三步:
第一步:比较前缀和目标字符串的对应前缀部分
先拿前缀和目标字符串的开头比,长度取前缀的总长度。这一步的结果如果不是零,直接就能决定最终结果——因为前面的字符已经分出大小了,后面的后缀不影响。
第二步:前缀匹配时,处理长度边界
如果前缀和目标字符串的对应部分完全匹配,就要看目标字符串的长度和前缀长度的关系:
- 要是目标字符串比前缀短:那我们的完整字符串(前缀+后缀)更长,直接返回正(符合“前面都相同,短的更小”的规则)
- 要是目标字符串和前缀一样长:接下来直接比较后缀和目标字符串的剩余部分(也就是空字符串),这和strcmp的逻辑完全一致
- 要是目标字符串比前缀长:就需要拿后缀和目标字符串的剩余部分继续比较
第三步:后缀比较的收尾逻辑
当后缀和目标字符串的剩余部分比较时,如果这部分有差异,直接返回对应符号;如果也完全匹配,就看谁还有剩余字符——目标字符串还有剩余就返回负,我们的字符串还有剩余就返回正,都没剩余就返回零。
完整代码实现
#include <string.h> #include <stdio.h> // 统一返回-1/0/1,避免依赖strcmp的具体返回值 static int get_sign(int val) { return (val > 0) - (val < 0); } int combined_strcmp(const char *prefix, const char *suffix, const char *pattern) { size_t prefix_len = strlen(prefix); size_t suffix_len = strlen(suffix); size_t pattern_len = strlen(pattern); size_t total_self_len = prefix_len + suffix_len; // 第一步:比较前缀和pattern的前prefix_len个字符 int ret1 = strncmp(prefix, pattern, prefix_len); if (ret1 != 0) { // 前缀已经分出胜负,直接返回统一后的符号 return get_sign(ret1); } // 前缀完全匹配,处理长度边界 if (pattern_len < prefix_len) { // pattern比前缀短,自身字符串更长,返回正 return 1; } else if (pattern_len == prefix_len) { // pattern和前缀等长,比较后缀和pattern的剩余部分(空字符串) return get_sign(strcmp(suffix, pattern + prefix_len)); } else { // pattern比前缀长,比较后缀和pattern的剩余部分 size_t remaining_pattern_len = pattern_len - prefix_len; int ret2 = strncmp(suffix, pattern + prefix_len, suffix_len); if (ret2 != 0) { return get_sign(ret2); } // 后缀也匹配,看谁还有剩余字符 if (remaining_pattern_len > suffix_len) { // pattern还有剩余,自身更短,返回负 return -1; } else if (remaining_pattern_len == suffix_len) { // 完全匹配 return 0; } else { // 自身还有剩余,返回正 return 1; } } } // 测试用例 int main() { const char *prefix = "super"; const char *suffix = "man"; // 测试1:和batman比较,应该返回正 printf("Test 1: %d\n", combined_strcmp(prefix, suffix, "batman")); // 测试2:和super比较,应该返回正 printf("Test 2: %d\n", combined_strcmp(prefix, suffix, "super")); // 测试3:和superman比较,应该返回0 printf("Test 3: %d\n", combined_strcmp(prefix, suffix, "superman")); // 测试4:和supermen比较,应该返回负 printf("Test 4: %d\n", combined_strcmp(prefix, suffix, "supermen")); // 测试5:和superma比较,应该返回正 printf("Test 5: %d\n", combined_strcmp(prefix, suffix, "superma")); return 0; }
关键细节说明
- get_sign函数:专门用来把strcmp/strncmp的返回值统一成-1、0、1,彻底避免依赖具体返回数值的风险,完全符合C标准的要求
- 长度用size_t:避免出现负数长度的问题,更符合C语言的类型规范
- 边界情况全覆盖:比如目标字符串比前缀短、比后缀长、刚好和完整字符串等长的情况都处理到了,完全对齐strcmp的逻辑
你可以把这个代码直接编译运行,测试用例覆盖了常见的场景,结果和直接调用strcmp("superman", pattern)完全一致。
内容来源于stack exchange
相关产品推荐
相关产品推荐

