Strnstr関数をCに実装しようとしています(strstrですが、長さをチェックします)。何らかの理由で機能しません(出力は常にnoです)。
#include <stdio.h>
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で終了するかどうかに依存します。これは、たとえば GNU-Darwin によって提供されるstrnstr
の通常の実装からの逸脱です。strchr
の呼び出しは、strchar
がインライン化されていない場合の不要な関数呼び出しです。haystack
がゼロの場合、NULL
の代わりにlen
を返します。これは、受け入れられているstrstr
セマンティクスからの逸脱です。haystack
の長さがゼロの場合、needle
の代わりに空の文字列を返します次の実装は、GNU-Darwin実装ほど読みにくくなることなく上記の問題を解決し、クリエイティブコモンズライセンスが付与されています。
#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で終了させたくない場合は、2つの長さの引数が必要です。
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で利用できますが、古いバージョンは壊れています。