我正在尝试将一个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;
}
答案 0 :(得分:9)
Chris Dodd提供的实施具有以下缺点:
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;
}
答案 1 :(得分:3)
怎么样:
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
不被终止,则需要两个长度args:
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中可用,但旧版本已损坏。
答案 2 :(得分:0)
strnstr
函数未在C标准中定义,它在BSD和某些其他系统上作为扩展提供。
这是OS / X上的手册页:
NAME
strstr
,strcasestr
,strnstr
-在字符串中找到子字符串库
标准C库(libc,-lc)
简介
#include <string.h>
[...]
char *strnstr(const char *haystack, const char *needle, size_t len);
[...]
说明
[...]
strnstr()
函数在字符串needle
中查找以空值终止的字符串haystack
的第一个匹配项,在此不多 超过len
个字符。不会搜索'\0'
字符之后出现的字符。由于strnstr()
函数 是FreeBSD专用的API,仅在不考虑可移植性时才应使用。返回值
如果
needle
为空字符串,则返回haystack
;如果needle
在haystack
中无处发生,则返回NULL
;否则一个指针 返回第一个needle
的第一个字符。示例
以下内容将指针
ptr
设置为"Bar Baz"
的{{1}}部分:largestring
以下内容将指针
const char *largestring = "Foo Bar Baz"; const char *smallstring = "Bar"; char *ptr; ptr = strstr(largestring, smallstring);
设置为ptr
,因为只搜索了NULL
的前4个字符:largestring
该规范不够简洁,(Linux内核版本的man page更加不精确),但是BSD系统上的示例(尤其是上面的示例)很清楚: const char *largestring = "Foo Bar Baz";
const char *smallstring = "Bar";
char *ptr;
ptr = strnstr(largestring, smallstring, 4);
是最大的在len
中要考虑的字节数,而不是haystack
中要考虑的字节数,后者只是一个常规的以null结尾的C字符串。
您的功能无法正常运行有多种原因:
needle
限制length
而不是s2
时,语义是不正确的s1
是无用的,并且适得其反:s1
(如果非result
,将指向分配的副本,该副本在从函数返回之前已释放),因此访问返回值所指向的字符串将具有未定义的行为。NULL
个字符,则strncpy
不会终止目标数组。您必须为自己的工作方式设置length
,但是真实的ss2[length] = '\0';
函数的工作方式也有所不同。strnstr()
和malloc()
可能不是您期望的,并且无法测试潜在的分配失败是一个错误。这是更正的版本:
free()