C语言大小写敏感/不敏感子串删除代码异常排查求助
C语言删除指定子串代码的问题排查
我写了一段C语言代码,用于删除字符串中的指定子串,通过case_sensitive参数控制是否区分大小写(0表示不区分,1表示区分),但运行结果不符合预期。
预期效果
- 输入字符串
"abcdef cde AbCDE"、子串"abc":- 当
case_sensitive=1时,应返回"def cde AbCDE" - 当
case_sensitive=0时,应返回"def cde DE"
- 当
- 输入字符串
"xYXyXYXY"、子串"xy"且case_sensitive=0时,应返回空串
原代码
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int erase_once(char *input_string, const char *substring, int case_sensitive) { size_t string_length = strlen(input_string); size_t substring_length = strlen(substring); if (string_length < substring_length || substring_length == 0) return 0; size_t i; for (i = 0; i < string_length - substring_length + 1; i++) { int match_found = 1; for (size_t j = i; j < i + substring_length; j++) { if ((case_sensitive == 0 && tolower(input_string[j]) != tolower(substring[j-i])) || input_string[j] != substring[j-i]) { match_found = 0; break; } } if (!match_found) continue; for (; i < string_length - substring_length; i++) { input_string[i] = input_string[i + substring_length]; } input_string[i] = '\0'; return 1; } return 0; } int erase(char *input_string, const char *substring, int case_sensitive) { int count; for (count = 0; erase_once(input_string, substring, case_sensitive); count++); return count; } int main(void) { char main_string[] = "abcdef cde AbCDE"; const char *substring_to_erase = "abc"; erase(main_string, substring_to_erase, 0); printf("%s\n", main_string); return 0; }
错误分析与修正
1. 匹配逻辑核心错误
原代码中字符匹配的条件逻辑完全颠倒:
if ((case_sensitive == 0 && tolower(input_string[j]) != tolower(substring[j-i])) || input_string[j] != substring[j-i])
这个条件会导致不管是否区分大小写,只要原字符与子串字符不相等,就判定不匹配。即使不区分大小写时转小写匹配成功,只要原字符不一致,仍会标记为不匹配,完全违背需求。
正确逻辑应该是分支判断:
- 区分大小写:直接比较原字符
- 不区分大小写:转小写后比较
修正后的匹配代码:
for (size_t j = 0; j < substring_length; j++) { // j从0开始对应子串索引,更清晰 char c1 = input_string[i + j]; char c2 = substring[j]; if (case_sensitive) { if (c1 != c2) { match_found = 0; break; } } else { // 转unsigned char避免tolower处理负数字符(如扩展ASCII) if (tolower((unsigned char)c1) != tolower((unsigned char)c2)) { match_found = 0; break; } } }
2. 删除子串的代码优化(次要)
原代码用手动循环移动字符,可替换为memmove,代码更简洁且不易出错:
memmove(input_string + i, input_string + i + substring_length, string_length - i - substring_length + 1);
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int erase_once(char *input_string, const char *substring, int case_sensitive) { size_t string_length = strlen(input_string); size_t substring_length = strlen(substring); if (string_length < substring_length || substring_length == 0) return 0; for (size_t i = 0; i <= string_length - substring_length; i++) { int match_found = 1; for (size_t j = 0; j < substring_length; j++) { char c1 = input_string[i + j]; char c2 = substring[j]; if (case_sensitive) { if (c1 != c2) { match_found = 0; break; } } else { if (tolower((unsigned char)c1) != tolower((unsigned char)c2)) { match_found = 0; break; } } } if (!match_found) continue; memmove(input_string + i, input_string + i + substring_length, string_length - i - substring_length + 1); return 1; } return 0; } int erase(char *input_string, const char *substring, int case_sensitive) { int count = 0; while (erase_once(input_string, substring, case_sensitive)) { count++; } return count; } int main(void) { // 测试用例1:不区分大小写删除"abc" char main_string1[] = "abcdef cde AbCDE"; const char *sub1 = "abc"; erase(main_string1, sub1, 0); printf("测试1结果:%s\n", main_string1); // 输出"def cde DE" // 测试用例2:区分大小写删除"abc" char main_string2[] = "abcdef cde AbCDE"; erase(main_string2, sub1, 1); printf("测试2结果:%s\n", main_string2); // 输出"def cde AbCDE" // 测试用例3:不区分大小写删除"xy",结果为空串 char main_string3[] = "xYXyXYXY"; const char *sub2 = "xy"; erase(main_string3, sub2, 0); printf("测试3结果:'%s'\n", main_string3); // 输出空串 return 0; }
验证结果
运行修正后的代码,三个测试用例均符合预期效果。
内容的提问来源于stack exchange,提问作者eminbihh
相关产品推荐
相关产品推荐

