Ниже я создаю как сломанный код, так и его фиксированную версию. Проблема в том, что я не могу полностью объяснить себе, почему первое не работает, а второе работает. Мне, очевидно, нужно пересмотреть некоторые очень базовые концепции языка C ++: не могли бы вы указать, что мне следует проверить, и, возможно, также объяснить, почему я получаю результаты, которые получаю с неработающим кодом.
В каталоге '../docs/', упомянутом в коде, я просто использовал команду 'touch' в Linux для создания нескольких файлов doc ...... html различной длины.
#include <iostream>
#include <regex>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main() {
fs::path p("../docs/");
for (auto& dir_it : fs::directory_iterator(p)) {
std::regex re = std::regex("^(doc[a-z]+)\\.html$");
std::smatch matches;
// BROKEN HERE:
if (std::regex_match(dir_it.path().filename().string(), matches, re)) {
std::cout << "\t\t" <<dir_it.path().filename().string();
std::cout << "\t\t\t" << matches[1] << std::endl;
}
}
return 0;
}
Производит:
documentati.html ati
documentationt.html �}:ationt
document.html document
documenta.html documenta
docume.html docume
documentat.html documentat
docum.html docum
documentatio.html ��:atio
documen.html documen
docu.html docu
documentation.html ��:ation
documaeuaoeu.html ��:aoeu
Примечание 1. Указанная выше ошибка возникает, если имена файлов превышают определенную длину. Я понимаю это только потому, что объект std :: string сам меняет размер.
Примечание 2. Приведенный выше код очень похож на код, используемый в следующем вопросе, но с boost :: regex_match вместо std :: regex_match: Могу ли я использовать маску для итерации файлов в каталоге с Boost?
Раньше это работало для меня и раньше, но теперь я использую GCC 5.4 вместо GCC 4.6, std :: regex вместо boost :: regex, C ++ 11 и гораздо более новую версию boost :: filesystem. Какое изменение актуально, из-за которого рабочий код сломался?
Фиксированный:
#include <iostream>
#include <regex>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
int main() {
fs::path p("../docs/");
for (auto& dir_it : fs::directory_iterator(p)) {
std::regex re = std::regex("^(doc[a-z]+)\\.html$");
std::smatch matches;
std::string p = dir_it.path().filename().string();
if (std::regex_match(p, matches, re)) {
std::cout << "\t\t" <<dir_it.path().filename().string();
std::cout << "\t\t\t" << matches[1] << std::endl;
}
}
return 0;
}
производит:
documentati.html documentati
documentationt.html documentationt
document.html document
documenta.html documenta
docume.html docume
documentat.html documentat
docum.html docum
documentatio.html documentatio
documen.html documen
docu.html docu
documentation.html documentation
documaeuaoeu.html documaeuaoeu
При использовании boost 1.62.0-r1 и gcc (Gentoo 5.4.0-r3) документация boost :: filesystem не дает четких указаний относительно того, какой путь (). Filename (). String () возвращает: http://www.boost.org/doc/libs/1_62_0/libs/filesystem/doc/reference.html#path-filename
Похоже, что это зависит от:
Почему boost :: filesystem :: path :: string () возвращается по значению в Windows и по ссылке в POSIX?