Implementando strnstr

Estoy tratando de implementar una función strnstr en C (strstr pero comprueba la longitud), por alguna razón no funciona (la salida siempre es no):

#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; } 

La implementación provista por Chris Dodd tiene las siguientes desventajas:

  1. Derrota el propósito de strnstr en que la condición while utiliza la función de cadena ilimitada strchr
  2. Depende de que el haystack se termine con NULL, lo que es una desviación de la implementación habitual de strnstr , por ejemplo, según lo provisto por GNU-Darwin
  3. La llamada a strchr es una llamada de función innecesaria cuando strchar no está en línea
  4. Devuelve haystack lugar de NULL cuando len es cero, una desviación de la semántica de strstr aceptada
  5. Devuelve una cadena vacía en lugar de haystack cuando la needle tiene una longitud de cero

La siguiente implementación soluciona los problemas anteriores sin ser tan difícil de leer como la implementación de GNU-Darwin, y tiene licencia de 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; } 

Qué tal si:

 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; } 

Si desea que el haystack no se termine en nulo, necesitará dos argumentos de longitud:

 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; } 

que está disponible en GNU libc, aunque las versiones anteriores están rotas.