问题
I'm trying to create a program where I can search for some files in a directory on my PC, using Visual Studio C++. As I'm not very experienced with that, I found this code (below) in another answer but couldn't find any explanation to the code. I'm having a hard time figuring it out and would strongly appreciate any help possible.
If there's another way of doing this I would be pleased to know how. Thank you!
" Now you can get file names. Just compare a file name.
while ((dirp = readdir(dp)) != NULL) {
std::string fname = dirp->d_name;
if(fname.find("abc") != std::string::npos)
files.push_back(fname);
}
Also you can use scandir function which can register filter function.
static int filter(const struct dirent* dir_ent)
{
if (!strcmp(dir_ent->d_name, ".") || !strcmp(dir_ent->d_name, ".."))
return 0;
std::string fname = dir_ent->d_name;
if (fname.find("abc") == std::string::npos) return 0;
return 1;
}
int main()
{
struct dirent **namelist;
std::vector<std::string> v;
std::vector<std::string>::iterator it;
n = scandir( dir_path , &namelist, *filter, alphasort );
for (int i=0; i<n; i++) {
std::string fname = namelist[i]->d_name;
v.push_back(fname);
free(namelist[i]);
}
free(namelist);
return 0;
}
"
回答1:
A better way of doing this would probably be using the new std::filesystem library. directory_iterators allow you to go through the contents of a directory. Since they are just iterators, you can combine them with standard algorithms like std::find_if to search for a particular entry:
#include <filesystem>
#include <algorithm>
namespace fs = std::filesystem;
void search(const fs::path& directory, const fs::path& file_name)
{
auto d = fs::directory_iterator(directory);
auto found = std::find_if(d, end(d), [&file_name](const auto& dir_entry)
{
return dir_entry.path().filename() == file_name;
});
if (found != end(d))
{
// we have found what we were looking for
}
// ...
}
We first create a directory_iterator
d
for the directory in which we want to search. We then use std::find_if()
to go through the contents of the directory and search for an entry that matches the filename we are looking for. std::find_if()
expects a function object as last argument that is applied to every visited element and returns true
if the element matches what we are looking for. std::find_if()
returns the iterator to the first element for which this predicate function returns true
, otherwise it returns the end iterator. Here, we use a lambda as predicate that returns true
when the filename component of the path of the directory entry we're looking at matches the wanted filename. Afterwards, we compare the iterator returned by std::find_if()
to the end iterator to see if we have found an entry or not. In case we did find an entry, *found
will evaluate to a directory_entry representing the respective file system object.
Note that this will require a recent version of Visual Studio 2017. Don't forget to set the language standard to /std:c++17
or /std:c++latest
in the project properties (C++/Language).
回答2:
Both methods use the find
function of a std::string
:
fname.find("abc")
This looks for "abc"
in the fname
string. If it's found it returns the index it starts at, otherwise it retruns std::string::npos
, so they both check for that substring.
You may want to see if you have an exact match, using ==
instead. It depends.
If an appropriate filename is found, it's pushed back into a vector. Your main function has
std::vector<std::string>::iterator it;
which it doesn't use. I suspect that came over with some copy/paste.
You can use a range based for
loop to see what's in your vector:
for(const std::string & name : v)
{
std::cout << name << '\n';
}
The filter
function also checks against "."
and ".."
since these have special meanings - current dir and up one dir.
At that point, th C API has returned a char *
, so they use strcmp
, rather than std::string methods.
Edit:
n = scandir( dir_path , &namelist, *filter, alphasort );
uses n
which you haven't declared.
Try
int n = scandir( dir_path , &namelist, *filter, alphasort );
Also, that uses dir_path
which needs declaring somewhere.
For a quick fix, try
const char * dir_path = "C:\\";
(or whatever path you want, watching out for escaping backslashes with an extra backslash.
You probably want to pass this in as an arg
to main.
来源:https://stackoverflow.com/questions/51378530/searching-for-files-in-a-directory-by-name-using-visual-studio-c