c++中简单的通配符搜索算法
Simple wildcard search algorithm in C++
我有一个任务,我必须创建一个搜索模式,包括通配符'?'。除了循环和字符串库的属性,我们还没有讲到更多的东西,所以我的老师不希望我使用数组或者任何我们没有讲到的东西。
我的问题是为特殊字符'?'创建一个算法。你知道如何在不使用更高级技巧的情况下将它集成到我的程序中吗?我所做的每件事不是完全错误就是有一些错误。
程序应该请求用户输入源字符串,然后请求另一个输入搜索字符串,其中可以包括'?在里面。例如:
源字符串:光荣搜索字符串:?r?o
在索引2处找到匹配的字符串匹配的字符串是:orio
我为在注释中只给提示回溯和递归而感到难过。下面是解释:
策略:
关注通配符之间的标记(通配符不是应该匹配的)。
- 从模式 提取第一个令牌
- 成功退出没有(更多)令牌
- 用于输入中的每个令牌匹配
- 将模式的剩余部分与输入 的剩余部分进行匹配
- 如果没有成功的子匹配,则失败,否则完成
存在递归(递归地匹配剩余类match(....))。
有回溯(如果递归匹配不成功,我们尝试下一个标记子匹配)
样本(见https://ideone.com/yApYp )
只使用循环和std::string
接口(好,iostreams
显示测试输出):)
#include <iostream>
#include <string>
typedef std::string::const_iterator It;
/*
* Extract sequences of non-wildcard characters from pattern range
*/
std::string extract_token(It &s, It e) // [s,e) is (sub)pattern
{
It wcard;
for (wcard=s; wcard!=e; ++wcard)
if ('?' == *wcard) break;
std::string token(s,wcard);
for (s=wcard; s!=e; ++s)
if ('?' != *s) break; // treat '??' as '?' in pattern
return token;
}
/*
* Match a (sub)pattern against a (sub)input
*
* (See "Strategy" above)
*/
bool match(It patb, It pate, const std::string& input)
{
while (patb != pate)
{
// get next token from pattern, advancing patb
std::string token = extract_token(patb, pate); // updates patb
if (!token.empty()) // could happen if pattern begins/ends with redundant '?'
{
size_t submatch = input.find(token); // first submatch please
while (std::string::npos != submatch) // while we have a submatch
{
if (match(patb, pate, input.substr(token.size())))
return true; // match completed successfully
// look for later potential submatches (*backtrack*)
submatch = input.find(token, submatch+1);
}
return false; // required token not found
}
}
return true; // no (remaining) pattern, always match
}
bool match(const std::string& pattern, const std::string& input)
{
// just relay to overload more suited for recursion
return match(pattern.begin(), pattern.end(), input);
}
//////////////////////
// TEST PROGRAM
void test(const std::string& pattern, const std::string& input)
{
std::cout << std::boolalpha;
std::cout << "match("" << pattern << "", "" << input << "") => "
<< match(pattern, input) << std::endl;
}
int main()
{
// matches
test("?????", "");
test("?????", "?????");
test("", "");
test("", "glorious");
test("?r?o", "glorious");
test("some?words?exist", "some silly words should, most definitely, be existing");
test("some??words?exist?", "some silly words should, most definitely, be existing");
// failing matches
test("_", "");
test("_", "glorious");
test("_", "glorious");
test("glorious", "glo?ious");
test("?some??words?exist?", "bogus");
}
最好创建两个函数。一个用于检查模式是否与某个给定位置的字符串匹配,另一个使用第一个函数检查输入字符串中的所有位置。
检查匹配模式的函数将循环遍历模式中的所有字符,并检查每个字符是否为?
或与输入字符串中相应位置的字符相同。
这是我想出的函数。最后我利用我有限的知识找到了一个方法。它可以工作,但可能性能真的很差。
谢谢你所有的帮助,他们启发了我,即使我不能直接使用他们,因为先进的技术对我来说。
void wildcard(string source, string search)
{
unsigned int j = 0, i = 0, z = 0;
string s1 = "", search2 = search;
//Starting with a null string and adding found parts to it
/*************************IF IT STARTS WITH QUESTION MARK*************************/
if(search.find('?') == 0)
{
for(; search.at(z) == '?'; z++)
//loop make search string start without question marks.
{
search2 = search.substr(z + 1, search.length());
}
for(; j <= source.length()-search2.length(); ++j)
//application of Brute Force Search Algoritm for this case.
{
while(i < search2.length() && (source.at(z+i+j) == search2.at(i) || search2.at(i) == '?'))
{
s1 = s1 + source.at(z+j+i);
i++;
}
}
if(s1.length() == search2.length())
//showing results for this case.
{
cout << "The matched string was found at index: " << source.find(s1) - z << endl;
cout << "The matched string is: " << source.substr((source.find(s1)-z), search.length()) << endl << endl;
}
else
{
cout << "The search string could not found in the source string." << endl << endl;
}
}
/********************IF IT DOES NOT START WITH QUESTION MARK**********************/
else
//If it doesnot start with ?, use normal test.
{
for(; j <= source.length()-search.length(); ++j)
//application of Brute Force Search Algoritm for this case.
{
while(i < search.length() && (source.at(i+j) == search.at(i) || search.at(i) == '?'))
{
s1 = s1 + source.at(j+i);
i++;
}
}
if(s1.length() == search.length())
//results
{
cout << "The matched string was found at index: " << source.find(s1) << endl;
cout << "The matched string is: " << s1 << endl << endl;
}
else
{
cout << "The search string could not found in the source string." << endl << endl;
}
}
}
可以认为通配符匹配每个字符,直到到达下一个字符或字符串的末尾。所以算法是:
if NextCharToMatch is ? then
get the next search char
loop until the input equals the new char to match
在这里查看我的答案,它对于大多数用途来说也应该足够快(它尽可能地避免堆分配,并且它基本上是一个不确定的有限状态自动机)。
在过去的一周里,我开始移动我的私人&我想起来了
c++通配符的开放实现。本地C/c++ &net
现在它从我的沙盒中分离出来,作为轻量级,快速和强大的通配符,除了慢速的regex引擎等。
enum MetaSymbols
{
MS_ANY = _T('*'), // {0, ~}
MS_SPLIT = _T('|'), // str1 or str2 or ...
MS_ONE = _T('?'), // {0, 1}, ??? - {0, 3}, ...
MS_BEGIN = _T('^'), // [str... or [str1... |[str2...
MS_END = _T('$'), // ...str] or ...str1]| ...str2]
MS_MORE = _T('+'), // {1, ~}
MS_SINGLE = _T('#'), // {1}
MS_ANYSP = _T('>'), // as [^/]* //TODO: >>/ i.e. '>' + {symbol}
};
如何实现自己的等。看这里:
- https://github.com/3F/regXwild
但是,对于。net用户来说,它也可以通过Conari引擎实现。
一般情况下,参见实现"如何工作"或使用"原样"(MIT许可)
#include "regXwildAPI.h"
using namespace net::r_eg::regXwild;
...
if(searchEssC(_T("regXwild"), _T("reg?wild"), true)) {
// ...
}
searchEss(data, _T("^main*is ok$"));
searchEss(data, _T("^new*pro?ection"));
searchEss(data, _T("pro*system"));
searchEss(data, _T("sys###s"));
searchEss(data, _T("new+7+system"));
searchEss(data, _T("some project|open*and*star|system"));
...
因此,我更新了我的旧答案。享受。
- 表示"accepting anything for this template argument" C++概念的通配符
- 当使用通配符和null指针调用函数时,对输出的说明
- C++17 文件系统::remove_all 带有通配符路径
- 如何允许通配符模板参数
- 使用通配符的跨平台文件列表
- 如何检索由带通配符的字符串索引的对象
- 有效地查找通配符条目
- 具有不同输入和输出名称的生成文件通配符
- MinGW GCC通配符编译所有文件(Windows)
- Windows 上带有通配符的目录中的文件
- 查找第一个文件W通配符匹配
- 在某些情况下,通配符模式匹配失败
- 实现通配符后没有输入文件错误
- 使用通配符搜索QTableWidget时出现问题
- 在三元搜索树中搜索(NOT with)通配符
- 在字符串中搜索通配符年份C++
- 带星号*通配符的字符串搜索
- c++中简单的通配符搜索算法
- 通配符匹配递归算法
- 通配符字符串搜索算法