Я пытаюсь реализовать функцию 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; }
Реализация, предоставленная Крисом Доддом, имеет следующие недостатки:
strnstr
в том, что условие while
использует неограниченную strchr
функцию strchr
haystack
имеет NULL, что является отклонением от обычной реализации strnstr
, например, как это предусмотрено GNU-Darwin strchr
является ненужным вызовом функции, когда strchar
не встроен haystack
вместо NULL
когда len
равно нулю, отклонение от принятой семантики strstr
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, хотя старые версии не работают.