Я должен реализовать что-то как своя собственная файловая система. Одной операцией был бы FindFirstFile. Я должен проверить, если бы вызывающая сторона передала что-то как., sample*.cpp или около этого. Моя реализация "файловой системы" предоставляет список "имен файлов" как массив char*.
Есть ли какая-либо функция Windows или какой-либо исходный код, который реализует это имя файла, соответствующее?
Таких функций довольно много. Вот каталог различных реализаций, отсортированный по рекурсивным и нерекурсивным и т. Д.
Если вам не нравится там лицензирование (или у вас проблемы со ссылкой и т. Д.), Вот один из возможных реализация алгоритма сопоставления, который, по крайней мере, близко приближается к тому, что использует Windows:
#include <string.h>
#include <iostream>
bool match(char const *needle, char const *haystack) {
for (; *needle != '\0'; ++needle) {
switch (*needle) {
case '?':
if (*haystack == '\0')
return false;
++haystack;
break;
case '*': {
if (needle[1] == '\0')
return true;
size_t max = strlen(haystack);
for (size_t i = 0; i < max; i++)
if (match(needle + 1, haystack + i))
return true;
return false;
}
default:
if (*haystack != *needle)
return false;
++haystack;
}
}
return *haystack == '\0';
}
#ifdef TEST
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("Matching", "[match]") {
REQUIRE(match("a", "a") == true);
REQUIRE(match("a", "b") == false);
REQUIRE(match("a*", "a") == true);
REQUIRE(match("a?", "a") == false);
REQUIRE(match("a?", "ab") == true);
REQUIRE(match("a*b", "ab") == true);
REQUIRE(match("a*b", "acb") == true);
REQUIRE(match("a*b", "abc") == false);
REQUIRE(match("*a*??????a?????????a???????????????",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") == true);
}
#endif
Поскольку обсуждалась сложность некоторых других ответов, я отмечу, что я считаю, что это имеет сложность O (NM) и O (M) использование хранилища (где N - размер целевой строки, а M - размер шаблона).
С тестовой парой @ masterxilo:
"*a*??????*a*?????????a???????????????", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
... на моей машине это находит совпадение примерно за 3 микросекунды. Этот намного медленнее, чем типичный образец - большинство других моих тестов выполняются примерно за 300 наносекунд или около того на этой конкретной машине.
В то же время код @ masterxilo запускается на той же машине примерно за 11 микросекунд, так что он все равно примерно в 3-4 раза быстрее (не говоря уже о том, что он несколько меньше и проще).
Для сопоставления имен с помощью '*' и '?' попробуйте следующее (если вы хотите избежать boost, используйте std::tr1::regex):
#include <boost/regex.hpp>
#include <boost/algorithm/string/replace.hpp>
using std::string;
bool MatchTextWithWildcards(const string &text, string wildcardPattern, bool caseSensitive /*= true*/)
{
// Escape all regex special chars
EscapeRegex(wildcardPattern);
// Convert chars '*?' back to their regex equivalents
boost::replace_all(wildcardPattern, "\\?", ".");
boost::replace_all(wildcardPattern, "\\*", ".*");
boost::regex pattern(wildcardPattern, caseSensitive ? Regex::normal : regex::icase);
return regex_match(text, pattern);
}
void EscapeRegex(string ®ex)
{
boost::replace_all(regex, "\\", "\\\\");
boost::replace_all(regex, "^", "\\^");
boost::replace_all(regex, ".", "\\.");
boost::replace_all(regex, "$", "\\$");
boost::replace_all(regex, "|", "\\|");
boost::replace_all(regex, "(", "\\(");
boost::replace_all(regex, ")", "\\)");
boost::replace_all(regex, "{", "\\{");
boost::replace_all(regex, "{", "\\}");
boost::replace_all(regex, "[", "\\[");
boost::replace_all(regex, "]", "\\]");
boost::replace_all(regex, "*", "\\*");
boost::replace_all(regex, "+", "\\+");
boost::replace_all(regex, "?", "\\?");
boost::replace_all(regex, "/", "\\/");
}
Посмотрите на POSIX-функции fnmatch
, glob
и wordexp
.
PathMatchSpec. Хотя он страдает от ограничения MAX_PATH
(т.е. может принимать не более 260 символов). Возможно, вам будет лучше реализовать свой собственный матчер; это не очень много кода.