实现strnstr
我试图将一个strnstr函数实现为C(strstr,但它检查长度),由于某种原因它不起作用(输出总是没有):
#include char *searchingFor = "stackdummy"; char *in = "la da\ndoo a da\nnow here comes the stack\nok there it was.\n"; char *strnstr(char *s1, char *s2, int length) { if(s1 == NULL || s2 == NULL) return NULL; printf("searching \n\n\"%s\"\n for %.*s\n", s1, length, s2); char *ss1 = malloc(strlen(s1) + 1); strcpy(ss1, s1); char *ss2 = malloc(length + 1); strncpy(ss2, s2, length); char *result = strstr(ss1, ss2); free(ss1); free(ss2); return result; } int main(void) { printf("found: %s\n", strnstr(in, searchingFor, 5) ? "yes" : "no"); printf("found: %s\n", strnstr(in, searchingFor, 5) ? "yes" : "no"); printf("found: %s\n", strnstr(in, searchingFor, 5) ? "yes" : "no"); return 0; }
Chris Dodd提供的实现具有以下缺点:
- 它违背了
strnstr
的目的,因为while
条件使用无界字符串函数strchr
- 它取决于
haystack
是NULL终止,这是与strnstr
的通常实现的strnstr
,例如由GNU-Darwin提供的 - 当
strchar
没有内联时,对strchr
的调用是一个不必要的函数调用 - 当
len
为零时,返回haystack
而不是NULL
,这是与接受的strstr
语义的偏差 - 当
needle
长度为零时,返回空字符串而不是haystack
以下实现解决了上述问题,而不像GNU-Darwin实现那样难以阅读,并且Creative Commons获得许可:
#include char *strnstr(const char *haystack, const char *needle, size_t len) { int i; size_t needle_len; if (0 == (needle_len = strnlen(needle, len))) return (char *)haystack; for (i=0; i<=(int)(len-needle_len); i++) { if ((haystack[0] == needle[0]) && (0 == strncmp(haystack, needle, needle_len))) return (char *)haystack; haystack++; } return NULL; }
怎么样:
char *strnstr(char *haystack, char *needle, size_t len) { if (len == 0) return haystack; /* degenerate edge case */ while (haystack = strchr(haystack, needle[0])) { if (!strncmp(haystack, needle, len)) return haystack; haystack++; } return 0; }
如果你希望haystack
不被null终止,你需要两个长度args:
char *memmem(char *haystack, size_t hlen, char *needle, size_t nlen) { if (nlen == 0) return haystack; /* degenerate edge case */ if (hlen < nlen) return 0; /* another degenerate edge case */ char *hlimit = haystack + hlen - nlen + 1; while (haystack = memchr(haystack, needle[0], hlimit-haystack)) { if (!memcmp(haystack, needle, nlen)) return haystack; haystack++; } return 0; }
这在GNU libc中可用,但旧版本已损坏。