如何在字节数组中搜索模式
How to search in a BYTE array for a pattern?
我有一个字节数组:
BYTE Buffer[20000];
这个数组包含以下数据:
00 ffffffffffff0010ac4c4053433442341401030a2f1e78eeee95a3544c99260f5054a54b00714f8180b3000101010101010101010121399030621a274068b03600da281100001c000000ff003457314d44304353423443530a000000fc0044454c4c2050323231300a2020000000fd00384b1e5310000a20202020202000fa
我的问题是如何搜索这个数组的模式,如"000000FC
"?我真的不认为这是重要的,但我需要索引,我可以找到我的模式。
既然你是用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
}
您想要memmem
(该代码使用GPL许可)。
然而,你自己卷应该不难。像memmem
的实现一样,您需要一个循环,使用memchr
在干草堆中找到针的第一个字符,并使用memcmp
测试每次命中并查看是否所有针都在那里。
可以在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)等
试试这个,只是需要它:
// 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;
}
这是一个使用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
算法,但实现也更复杂。
使用C++17
,我发现最快的解决方案是使用std::search
和boyer_moore_horspool_searcher。
'Tarion'他发布的函数几乎是完美的。但是它做了一个'memcmp'(再次检查第一个字符),它已经用'memchr'做了。如果更多的第一个字符将在数组中,然后不总是指针字节,它就不起作用了。这里你看到了两个帖子,把它复制到你的c++项目中然后调用函数testt ()
你可以根据自己的意愿修改它。还要知道,char*只是一个char[]数组,但作为一个指针。所以如果你在一个char变量前面看到一个'&'它只是使用char*作为一个普通的char[]通过索引通过返回指向该索引的指针。另外,要重新定义不是固定大小的数组,请使用'malloc' c++函数。永远不要听从c++程序员的建议,让你使用C字符串函数来搜索二进制数据。他们太差劲了。只使用c++函数。
如何使用。:搜索字节程序的c++(第1/2部分和第2/2部分)为您的查找字节函数并将其复制到您的c++项目中,您必须复制它所有(也在白色区域上方的标题行,以及在白色区域中看到'}'字符的第2/2部分下方),我不能上传它所有因为StackOverflow帖子错误,我很着急。
c++搜索字节例程(PART 1/2) -将下面的代码复制到你的c++项目中
// Returns a int with the starting position of the bytes found
int FindBytesPosInCharPointer(char* bytSourceBuffer, size_t lngSourceBufferStartPos, size_t lngSourceBufferTotalLen, char* bytBytesToFind, size_t lngBytesToFindLen) {
//when calling this function bytSourceBuffer must always point to index [0]
//use the lngSourceBufferStartPos to use a starting point index
if (lngBytesToFindLen <= 0 || lngBytesToFindLen > lngSourceBufferTotalLen - lngSourceBufferStartPos) {
return -1;
}
if (lngSourceBufferStartPos < 0) {
return -1;
}
if (lngSourceBufferStartPos >= lngSourceBufferTotalLen) {
return -1;
}
if (lngSourceBufferTotalLen <= 0) {
return -1;
}
//memchr returns a pointer to the array
size_t lngFoundPos = 0;
size_t lngFirstPosFound = 0;
size_t lngCurStartPos = 0;
char* lngPointerPos;
int intMustExitLoop = 0;
//this can change underway but used only internal
lngCurStartPos = lngSourceBufferStartPos;
//find first byte
lngPointerPos = NULL;
lngPointerPos = (char*)memchr(&bytSourceBuffer[lngCurStartPos], bytBytesToFind[0], lngSourceBufferTotalLen - lngCurStartPos);
//validate
if (lngPointerPos == NULL) {
//karakter niet gevonden
lngFoundPos = -1;
lngFirstPosFound = -1;
}
else {
//current position where char has been found
lngFoundPos = (lngPointerPos - &bytSourceBuffer[lngCurStartPos]);
lngFirstPosFound = lngFoundPos; //we need this to skip bytes
//zoeken
if (lngBytesToFindLen == 1) {
//we only want to find 1 char, so we dont need to use memcmp
//is done now
}
else {
//check if (remaining) bytBytesToFind bytes matching
if (lngBytesToFindLen <= ((lngSourceBufferTotalLen - lngCurStartPos) - lngFoundPos)) { //(lngSourceBufferLen - lngCurStartPos) = remaining bytes
//memcmp = 0 is blocks zijn hetzelfde
if (memcmp(lngPointerPos + 1, &bytBytesToFind[1], lngBytesToFindLen - 1) == 0) {
//BYTES MATCHING, lngFoundPos will return the result
}
else {
//MessageBox(NULL, "BLOCKS DO NOT MATCH", "Info", 0);
lngFoundPos = -1;
}
}
else {
//MessageBox(NULL, "NOT ENOUGH BYTES", "Info", 0);
lngFoundPos = -1;
}
//validate the result, if bytes did not match we start the loop
if (lngFoundPos == -1) {
//new position to start searching from
lngCurStartPos = lngFirstPosFound + 1;
lngFirstPosFound = -1;
//validate if startpos is still valid
if (lngCurStartPos < 0 || (lngSourceBufferStartPos + lngCurStartPos) >= lngSourceBufferTotalLen) {
lngFoundPos = -1;
}
else {
if (lngBytesToFindLen > lngSourceBufferTotalLen - (lngSourceBufferStartPos + lngCurStartPos)) {
lngFoundPos = -1;
}
else {
//condition
intMustExitLoop = 0;
//start loop
do {
//validate if startpos is still valid
if (lngCurStartPos < 0 || (lngSourceBufferStartPos + lngCurStartPos) >= lngSourceBufferTotalLen) {
lngFoundPos = -1;
intMustExitLoop = 1;
break;
}
else {
if (lngBytesToFindLen > lngSourceBufferTotalLen - (lngSourceBufferStartPos + lngCurStartPos)) {
lngFoundPos = -1;
intMustExitLoop = 1;
break;
}
else {
//search for first byte again, memchr returns a pointer
lngPointerPos = NULL;
lngPointerPos = (char*)memchr(&bytSourceBuffer[lngCurStartPos], bytBytesToFind[0], lngSourceBufferTotalLen - lngCurStartPos);
//afhandelen
if (lngPointerPos == NULL) {
//character not found
lngFoundPos = -1;
intMustExitLoop = 1;
break;
}
else {
//this is the current position where character has been found
lngFoundPos = (lngPointerPos - &bytSourceBuffer[lngCurStartPos]);
lngFirstPosFound = lngFoundPos; //we need this to skip bytes
//MessageBoxA(NULL, std::to_string(lngFirstPosFound).c_str(), "Caption", 0);
//check if (remaining) bytBytesToFind bytes matching
if (lngBytesToFindLen <= ((lngSourceBufferTotalLen - (lngSourceBufferStartPos + lngCurStartPos)) - lngFoundPos)) { //(lngSourceBufferLen - lngCurPos) = remaining bytes
//memcmp = 0 is blocks zijn hetzelfde
if (memcmp(lngPointerPos + 1, &bytBytesToFind[1], lngBytesToFindLen - 1) == 0) {
//BYTES MATCHING
//This is the real position in the array from starting point lngSourceBufferStartPos
lngFoundPos = (lngPointerPos - &bytSourceBuffer[lngCurStartPos]) + (lngCurStartPos - lngSourceBufferStartPos);
//is done now
intMustExitLoop = 1;
break;
}
else {
//MessageBoxA(NULL, "BLOCKS DO NOT MATCH", "Caption", 0);
//will loop again for next search
lngFoundPos = -1;
lngCurStartPos = lngCurStartPos + (lngFirstPosFound + 1);
lngFirstPosFound = -1;
}
}
else {
//MessageBoxA(NULL, "NOT ENOUGH BYTES", "Caption", 0);
//is meteen klaar dan
lngFoundPos = -1;
lngFirstPosFound = -1;
intMustExitLoop = 1;
break;
}
}
}
}
} while (intMustExitLoop == 0);
}
}
}
}
}
//-1 is nothing found
return lngFoundPos;
}
c++搜索字节例程(第2/2部分)-将下面的代码复制到你的c++项目中(将这些行放到testt函数中,或者您喜欢的任何东西中)。然后调用函数。我在向StackOverflow添加函数名时遇到了问题,但第一行应该是"int testt (){"最后两行应该是&;return 1;&;和"}"
//test
char* bytTest;
bytTest = (char*)malloc(10);
bytTest[0] = 0;
bytTest[1] = 0;
bytTest[2] = 70;
bytTest[3] = 70;
bytTest[4] = 65; //A
bytTest[5] = 66; //B
bytTest[6] = 1;
bytTest[7] = 70;
bytTest[8] = 68;
bytTest[9] = 69;
//bytTest[10] = 0;
//bytes to find
char bytFindBytes[3];
bytFindBytes[0] = 70;
bytFindBytes[1] = 68;
bytFindBytes[2] = 69;
int lngFindPos = 0;
lngFindPos = FindBytesPosInCharPointer(&bytTest[0], 0, 10, &bytFindBytes[0], sizeof bytFindBytes);
MessageBoxA(NULL, std::to_string(lngFindPos).c_str(), "Caption", 0);
//我知道我可以只传递bytTest和bytFindBytes没有'&'和[0]的函数,但它是向您展示如何使用指针,使用bytTest[0]只会传递数组中第一个字节的值给函数(这无论如何会给出编译错误),其中添加'&'传递数组中第一个字节的指针给函数。为了让你们更清楚。
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 有根的二进制搜索树.保留与其父级的链接
- 为什么在保护模式下继承升级不起作用
- 如何在全屏模式下(在OpenGL中)使背景透明
- 在C++中搜索嵌套多映射值
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 如何使用配置模式进行find_package搜索并在模块模式下回退?
- 使用拉宾·卡普进行模式搜索
- C++ 中用于搜索字符串模式的正则表达式
- C 搜索模式在2个字符串中,而无需串联
- 搜索单词时的字母模式逻辑
- 使用 bin 搜索查找排序数组的模式
- 在复合模式中搜索特定元素
- QRegExp :搜索不包含其他模式的模式
- 找不到c++正则表达式搜索模式
- 如何在点击模式下搜索并解密部分流
- 在函数搜索模式中引用二维数组时出错
- 如何在字节数组中搜索模式
- 在巨大的日志文件中搜索数百种模式