如何在BYTE数组中搜索模式?

时间:2011-09-06 11:47:18

标签: c++ c windows pattern-matching

我有一个字节数组:

BYTE Buffer[20000];此数组包含以下数据:

  

00FFFFFFFFFFFF0010AC4C4053433442341401030A2F1E78EEEE95A3544C99260F5054A54B00714F8180B3000101010101010101010121399030621A274068B03600DA281100001C000000FF003457314D44304353423443530A000000FC0044454C4C2050323231300A2020000000FD00384B1E5310000A20202020202000FA

我的问题是如何在此数组中搜索“000000FC”这样的模式?我真的不认为它很重要,但我需要索引,我也可以找到我的模式。有人可以为此提供一个例子,因为我真的不明白这一点:(

5 个答案:

答案 0 :(得分:24)

由于您使用的是C ++,因此请使用C ++方式:

char a[] = { 0, 0, 0, 0xFC };
char Buffer[20000] = ...

std::string needle(a, a + 4);
std::string haystack(Buffer, Buffer + 20000);  // or "+ sizeof Buffer"

std::size_t n = haystack.find(needle);

if (n == std::string::npos)
{
    // not found
}
else
{
    // position is n
}

您也可以使用算法直接搜索数组:

#include <algorithm>
#include <iterator>

auto it = std::search(
    std::begin(Buffer), std::end(Buffer),
    std::begin(a), std::end(a));

if (it == std::end(Buffer))
{
    // not found
}
else
{
    // subrange found at std::distance(std::begin(Buffer), it)
}

或者,在C ++ 17中,您可以使用字符串视图:

std::string_view sv(std::begin(Buffer), std::end(Buffer));

if (std::size_t n = sv.find(needle); n != sv.npos)
{
    // found at position n
}
else
{
    // not found
}

答案 1 :(得分:7)

您需要类似memmem的内容(该代码已获得GPL许可)。

然而,推出自己的应该并不困难。就像在memmem的实现中一样,你需要一个循环使用memchr来查找大海捞针的第一个字符,并memcmp来测试每个命中,看看是否所有的针就在那里。

答案 2 :(得分:2)

试试这个,只需要它:

// Returns a pointer to the first byte of needle inside haystack, 
static uint8_t* bytes_find(uint8_t* haystack, size_t haystackLen, uint8_t* needle, size_t needleLen) {
    if (needleLen > haystackLen) {
        return false;
    }
    uint8_t* match = memchr(haystack, needle[0], haystackLen);
    if (match != NULL) {
        size_t remaining = haystackLen - ((uint8_t*)match - haystack);
        if (needleLen <= remaining) {
            if (memcmp(match, needle, needleLen) == 0) {
                return match;
            }
        }
    }
    return NULL;
}

答案 3 :(得分:1)

这是一个使用C缓冲区的简单/天真的解决方案:

const char *find_needle(const char *haystack, size_t haystack_length, const char *needle, size_t needle_length) {
    for (size_t haystack_index = 0; haystack_index < haystack_length; haystack_index++) {

        bool needle_found = true;
        for (size_t needle_index = 0; needle_index < needle_length; needle_index++) {
            const auto haystack_character = haystack[haystack_index + needle_index];
            const auto needle_character = needle[needle_index];
            if (haystack_character == needle_character) {
                continue;
            } else {
                needle_found = false;
                break;
            }
        }

        if (needle_found) {
            return &haystack[haystack_index];
        }
    }

    return nullptr;
}

例如,更有效的解决方案是使用Knuth-Morris-Pratt algorithm,但实现也更加复杂。

答案 4 :(得分:0)

可以在 STL std::search() 中使用原始指针。

例如

#include <algorithm>

BYTE Buffer[20000] = { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC };
PBYTE pBufferLast = Buffer + sizeof(Buffer);
BYTE Pattern[] = { 0x00, 0x00, 0x00, 0xFC };
PBYTE pPatternLast = Pattern + sizeof(Pattern);

PBYTE pOccurrence = std::search(Buffer, pBufferLast, Pattern, pPatternLast);

BOOL fFound = (pOccurrence != pBufferLast);

从C++17开始,std::search()可以使用Boyer-Moore搜索(boyer_moore_searcher)等