Реализация 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; } 

Реализация, предоставленная Крисом Доддом, имеет следующие недостатки:

  1. Он побеждает цель strnstr в том, что условие while использует неограниченную strchr функцию strchr
  2. Это зависит от того, что haystack имеет NULL, что является отклонением от обычной реализации strnstr , например, как это предусмотрено GNU-Darwin
  3. Вызов strchr является ненужным вызовом функции, когда strchar не встроен
  4. Возвращает haystack вместо NULL когда len равно нулю, отклонение от принятой семантики strstr
  5. Возвращает пустую строку вместо haystack когда длина needle равна нулю

Следующая реализация устраняет вышеупомянутые проблемы, не будучи столь же трудной для чтения, как реализация 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 не был нулевым, вам потребуются два аргумента длины:

 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, хотя старые версии не работают.