我有一项任务,我必须创建一个包含通配符'?'的搜索模式。我们还没有涉及字符串库的循环和属性,所以我的老师不希望我使用数组或任何我们没有涉及的内容。
我的问题是为特殊字符'?'创建算法。您是否知道如何在不使用更高级技巧的情况下将其集成到我的程序中?我尝试的一切都是完全错误或者有一些错误。
程序应该请求用户输入源字符串,然后请求搜索字符串的另一个输入,其中包括“?”在里面。例如:
源字符串:光荣 搜索字符串:?r?o
在index:2处找到匹配的字符串 匹配的字符串是:orio
答案 0 :(得分:2)
可能你最好创造两个功能。一个检查模式是否匹配某个给定位置的字符串,另一个使用第一个函数检查输入字符串中的所有位置。
检查匹配模式的函数将遍历模式中的所有字符,并且对于每个字符检查它是?
还是与输入字符串中相应位置的字符相同
答案 1 :(得分:2)
我只对暗示回复和评论中的递归感到难过。这是一个解释:
专注于 wilcards之间的令牌(通配符不应该匹配)。
有递归(余数类匹配(....)递归)。
有回溯(如果递归匹配不成功,我们尝试下一个令牌子匹配)
仅使用循环和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");
}
答案 2 :(得分:0)
或许将通配符视为匹配每个字符,直到到达下一个字符或字符串的结尾。所以算法将是:
if NextCharToMatch is ? then
get the next search char
loop until the input equals the new char to match
答案 3 :(得分:0)
这是我提出的功能。最后,我发现了一种使用有限知识的方法。它有效,但可能表现非常糟糕。
感谢您的帮助,他们激励了我,即使我不能直接使用它们,因为我的技术先进。
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;
}
}
}
答案 4 :(得分:0)
请参阅我的回答here,它对于大多数用途来说也应该足够快(它尽可能地避免堆分配,并且它基本上是一个非确定性的有限状态自动机)。
答案 5 :(得分:0)
在过去的一周里,我开始移动我的私人&amp;来自bitbucket的公共存储库,我记得这个。
C ++通配符的开放实现。原生C / C ++&amp; .NET
现在,除了慢速正则表达式引擎等之外,它还是从我的沙盒中分成了一个新的项目,作为轻量级,快速和强大的通配符。
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}
};
如何实现自己的等。请看这里:
但是,对于.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"));
...
因此,我更新了我的旧答案。享受。