strstr() 用于非空终止的字符串

Posted

技术标签:

【中文标题】strstr() 用于非空终止的字符串【英文标题】:strstr() for a string that is NOT null-terminated 【发布时间】:2012-01-24 23:01:32 【问题描述】:

如何在 C 中为 counted 字符串(即 not 以 null 终止)执行 in-place 等效于 strstr() ?

【问题讨论】:

您必须编写自己的版本。 哪个字符串不是以空值结尾的?正在搜索的字符串,还是子字符串? @TimCooper:正在搜索的那个(干草堆)。 你可以从BSD窃取strnstr()的实现。但请注意这个错误:mikeash.com/pyblog/dont-use-strnstr.html glibc 有 memmem(needle 和 haystack 都算在内),我相信也会有一个公共领域的实现。 【参考方案1】:

看看下面的功能是否适合你。我还没有彻底测试过,所以我建议你这样做。

char *sstrstr(char *haystack, char *needle, size_t length)

    size_t needle_length = strlen(needle);
    size_t i;
    for (i = 0; i < length; i++) 
        if (i + needle_length > length) 
            return NULL;
        
        if (strncmp(&haystack[i], needle, needle_length) == 0) 
            return &haystack[i];
        
    
    return NULL;

【讨论】:

这实际上与我目前使用的相似,但它是 O(mn),而(我假设)strstr 是 O(m + n)。所以我正在寻找一些不像我的版本那样慢得离谱的东西。 :-) 但无论如何 +1,因为这个想法有效。 @Mehrdad:看看这个实现可能也是值得的:src.gnu-darwin.org/src/lib/libc/string/strnstr.c.html 哇,我想我错了……所以strstr 通常被定义为 O(mn) 操作?感谢您指出这一点......那么我可能会接受这一点,因为它是问题的确切替代品。 @Mehrdad:我稍微整理了一下我的解决方案,如果您想再看一下。 @Mehrdad C 没有指定/定义 strstr() 的 O()。【参考方案2】:

如果您害怕 O(m*n) 行为 - 基本上,您不必担心,这种情况不会自然发生 - 这是我所使用的 KMP 实现,我已对其进行了修改以获取大海捞针。也是一个包装。如果您想重复搜索,请自己编写并重用 borders 数组。

不保证没有错误,但它似乎仍然有效。

int *kmp_borders(char *needle, size_t nlen)
    if (!needle) return NULL;
    int i, j, *borders = malloc((nlen+1)*sizeof(*borders));
    if (!borders) return NULL;
    i = 0;
    j = -1;
    borders[i] = j;
    while((size_t)i < nlen)
        while(j >= 0 && needle[i] != needle[j])
            j = borders[j];
        
        ++i;
        ++j;
        borders[i] = j;
    
    return borders;


char *kmp_search(char *haystack, size_t haylen, char *needle, size_t nlen, int *borders)
    size_t max_index = haylen-nlen, i = 0, j = 0;
    while(i <= max_index)
        while(j < nlen && *haystack && needle[j] == *haystack)
            ++j;
            ++haystack;
        
        if (j == nlen)
            return haystack-nlen;
        
        if (!(*haystack))
            return NULL;
        
        if (j == 0)
            ++haystack;
            ++i;
         else 
            do
                i += j - (size_t)borders[j];
                j = borders[j];
            while(j > 0 && needle[j] != *haystack);
        
    
    return NULL;


char *sstrnstr(char *haystack, char *needle, size_t haylen)
    if (!haystack || !needle)
        return NULL;
    
    size_t nlen = strlen(needle);
    if (haylen < nlen)
        return NULL;
    
    int *borders = kmp_borders(needle, nlen);
    if (!borders)
        return NULL;
    
    char *match = kmp_search(haystack, haylen, needle, nlen, borders);
    free(borders);
    return match;

【讨论】:

【参考方案3】:

我刚刚遇到了这个问题,我想分享我的实现。它认为它很快,因为我没有任何子调用。

它返回大海捞针中找到针的索引,如果没有找到则返回-1。

/* binary search in memory */
int memsearch(const char *hay, int haysize, const char *needle, int needlesize) 
    int haypos, needlepos;
    haysize -= needlesize;
    for (haypos = 0; haypos <= haysize; haypos++) 
        for (needlepos = 0; needlepos < needlesize; needlepos++) 
            if (hay[haypos + needlepos] != needle[needlepos]) 
                // Next character in haystack.
                break;
            
        
        if (needlepos == needlesize) 
            return haypos;
        
    
    return -1;

【讨论】:

当你在它的时候应该继续做 Boyer-Moore ;)【参考方案4】:

我用过这个方法

int memsearch(char* dataset, int datasetLength, char* target, int targetLen)
    for(int i = 0; i < datasetLength; i++)
            if(dataset[i] == target[0])
                    int found = 1;
                    for(int j = 0; j < targetLen; j++)
                            int k = i + j;
                            if(k >= datasetLength || target[j] != dataset[k])
                                    found = 0;
                                    break;
                            
                    
                    if(found) return i;
            
    
    return -1;

【讨论】:

以上是关于strstr() 用于非空终止的字符串的主要内容,如果未能解决你的问题,请参考以下文章

C 库函数 - strstr()

C 库函数 - strstr()

初始化char数组以保存非空终止字符串[重复]

C ++中的非空终止字符数组

C语言strstr()函数(在主字符串里查找子字符串,返回第一次找到的子字符串以及后面的字符串)

strstr();