Реализация strnstr
Я пытаюсь реализовать функцию strnstr в C (strstr, но она проверяет длину), по какой-то причине она не работает (выход всегда нет):
#include <stdio.h>
char *searchingFor = "stackdummy";
char *in = "la dandoo a dannow here comes the stacknok there it was.n";
char *strnstr(char *s1, char *s2, int length) {
if(s1 == NULL || s2 == NULL) return NULL;
printf("searching nn"%s"n for %.*sn", 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: %sn", strnstr(in, searchingFor, 5) ? "yes" : "no");
printf("found: %sn", strnstr(in, searchingFor, 5) ? "yes" : "no");
printf("found: %sn", strnstr(in, searchingFor, 5) ? "yes" : "no");
return 0;
}
2 ответов
реализация предусмотренных Крис Додд имеет следующие недостатки:
- он побеждает цель
strnstr
в том, чтоwhile
условие использует неограниченную строковую функциюstrchr
- это зависит от того
haystack
будучи NULL завершается, что является отклонением от обычной реализацииstrnstr
, например, как предусмотрено GNU-Darwin - вызов
strchr
- это ненужная функция позвоните, когдаstrchar
не встроен - возвращает
haystack
вместоNULL
, когдаlen
равно нулю, отклонение от принятогоstrstr
семантика - возвращает пустую строку вместо
haystack
, когдаneedle
имеет длину ноль
следующая реализация устраняет вышеуказанные проблемы, не становясь такой же трудной для чтения, как реализация GNU-Darwin, и лицензируется Creative Commons:
#include <string.h>
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, вам понадобятся два аргумента длины:
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, хотя более старые версии сломаны.