K&R C问题:大小写不敏感strstrci函数匹配末尾字符串返回NULL排查
问题分析与修复
核心错误
你写的strstrci函数在匹配位于字符串末尾(或中间但后续还有字符)的模式时会返回NULL,问题出在内层循环的逻辑顺序上:
你错误地把模式的结束符'\0'也纳入了字符匹配条件。按照strstr的定义,只要模式p的所有字符在s中连续匹配(大小写不敏感),就应该返回起始位置,不管s后续是否还有字符。但你的代码要求,当模式匹配到末尾时,s的对应位置也必须是'\0'才能触发返回——这就导致如果s在模式匹配完成后还有其他字符,或者测试字符串没有正确以'\0'结尾,函数就会返回NULL。
比如你提到的例子s="On a wall he sat"、p="sat",如果字符串正确以'\0'结尾,理论上你的代码应该能返回正确指针,但如果字符串末尾有隐藏字符(比如换行符),或者测试时字符串没有正确终止,就会触发错误。但函数本身的逻辑缺陷是根本问题。
修复后的代码
调整内层循环的判断顺序,先检查模式是否匹配完成,再处理字符匹配:
char * strstrci(char *s, char *p) { int i, j; // 空模式直接返回原字符串,符合strstr标准行为 if (*p == '\0') return s; for (i = 0; *(s + i) != '\0'; i++) { char s_char = *(s + i); char p_char = *p; // 判断首字符是否大小写匹配,仅对字母做转换判断 if ((s_char == p_char) || (p_char >= 'A' && p_char <= 'Z' && s_char == p_char + 32) || (p_char >= 'a' && p_char <= 'z' && s_char == p_char - 32)) { for (j = 1; ; j++) { // 模式遍历完,说明完全匹配 if (*(p + j) == '\0') return s + i; // 字符串遍历完但模式没结束,匹配失败 if (*(s + i + j) == '\0') break; s_char = *(s + i + j); p_char = *(p + j); // 当前字符不匹配,退出内层循环 if (!((s_char == p_char) || (p_char >= 'A' && p_char <= 'Z' && s_char == p_char + 32) || (p_char >= 'a' && p_char <= 'z' && s_char == p_char - 32))) { break; } } } } return NULL; }
额外优化点
- 增加了空模式处理,和标准
strstr行为一致。 - 加入字母范围判断,避免对数字、符号等非字母字符做无效的大小写转换。
- 内层循环逻辑更清晰:先确认模式是否匹配完成,再检查字符串是否结束,最后判断字符匹配,完全符合字符串匹配的逻辑顺序。
内容的提问来源于stack exchange,提问作者Vinayak Deshmukh
相关产品推荐
相关产品推荐

