2012-06-19 5 views
0

Я хочу создать метод, который читает каталог и находит и сохраняет в структуре данных все указанные каталоги, а также все подкаталоги каждой директории. В частности я хочу, чтобы имена цитировать:Найти каталоги и подкаталоги через рекурсию в C++

folder1 folder11 folder12 folder2 folder21 folder22 folder23

мне нужно, очевидно, функции с рекурсией. Я использую временный метод члена класса в консольном приложении, как:

private: 
struct dirent *ep; 


void DirectoryReader::parseDirectory(char* readingDirectory) 
{ 
char* tempDirectory = (char*)malloc(sizeof(readingDirectory) + 200); 
string temp = readingDirectory; 

DIR *dp; 
dp = opendir (readingDirectory); 
    if (dp != NULL) 
    { 
     while (ep = readdir (dp)) 
     { 
     puts (ep->d_name); 

     temp += readingDirectory; 
     temp += "/"; 
     temp += ep->d_name; 

     char * buffer = new char[temp.length()]; 
     strcpy(buffer,temp.c_str()); 
     parseDirectory(buffer); 
     } 
     (void) closedir (dp); 
    } 
    else 
    perror ("Couldn't open the directory"); 

}

Хорошо, я не знаю, лучше всего написанного кода, но я хочу сначала иметь представление имена пойманных. Однако он не работает должным образом, поскольку он рассматривает имя родительского каталога более одного раза. Даже если я выложу вызов того же метода (не выполняя рекурсию), первые два имени. а также .. . Зачем?

Не могли бы вы предложить мне функцию, выполняющую описанный процесс, или указать исправление, требуемое для этой функции?

+0

Можете вы рассказать о неправильном выходе? –

+0

У вас проблема в отдельности: при распределении «буфера» вы не выделяете пространство для завершающего символа '' \ 0''. Вы также не освобождаете выделенную память. Но вместо использования временного буфера, почему бы не передать 'temp.c_str()' непосредственно на рекурсивный вызов? –

+0

Кроме того, вы пытаетесь перезаписать файлы _all_. Вы должны проверить, действительно ли это _is_ каталог, который можно проверить с помощью 'ep-> d_type == DT_DIR'. Или, если не существует поля 'ep-> d_type', вы, например, 'stat', чтобы получить тип. –

ответ

4

как заметил какой-то комментарий, boost :: filesystem - это обычно путь. Но из вашего кода кажется, что вы все еще новичок на C++, поэтому я переписал идиоматический образ C++, добавив немного полезного отображения. НТН

#include <dirent.h> 
#include <iostream> 
#include <string> 
using namespace std; 

struct DirectoryReader 
{ 
    static void parseDirectory(string readingDirectory, int level); 
}; 

void DirectoryReader::parseDirectory(string readingDirectory, int level) 
{ 
    if (DIR *dp = opendir(readingDirectory.c_str())) 
    { 
     cout << string(level, ' ') << readingDirectory << endl; 
     while (struct dirent *ep = readdir(dp)) 
      if (ep->d_type == DT_DIR && ep->d_name[0] != '.') 
       parseDirectory(readingDirectory + "/" + ep->d_name, level + 1); 
     closedir(dp); 
    } 
    else 
     cerr << "Couldn't open the directory " << readingDirectory << endl; 
} 

int main_parsedir(int argc, char **argv) 
{ 
    if (argc > 1) 
     DirectoryReader::parseDirectory(argv[1], 0); 
    return 0; 
} 

обратите внимание, что в вашем коде, хранение struct dirent *ep; в классе совершенно неправильно, потому что вы перезаписать его в то время как рекурсивный ...

2

функции перечисления каталогов, как правило, возвращает текущий каталог (.) И родительский каталог (..) ссылки. Вы должны игнорировать их. Кроме того, вам нужно проверить ep-> d_type. Я написал для вас следующую функцию. Проверьте, работает ли это так, как ожидалось. Я не использовал разделитель пространства для вывода, так как отдельные папки могут иметь в них пробельный символ. Кроме того, я не уверен, как вы собираетесь использовать этот вывод, поскольку он теряет древовидную структуру.

#include "dirent.h" 

const string theDelimiter = "\\"; 

class DirectoryReader 
{ 
public: 
    string DirectoryReader::parseDirectory(string readingDirectory, const string& aCurrentFolderName) 
    { 
     string aChildren; 
     aChildren += theDelimiter; 
     aChildren += aCurrentFolderName; 

     DIR *dp = opendir (readingDirectory.c_str()); 
     if (dp != NULL) 
     { 
      struct dirent *ep = NULL; 
      while ((ep = readdir (dp)) && ep->d_type == DT_DIR) 
      { 
       string aDirName = ep->d_name; 

       // Ignore current directory and the parent directory links 
       if(!aDirName.compare(".") || !aDirName.compare("..")) 
        continue; 

       // Form the full directory path 
       string aFullFolderName = readingDirectory; 
       aFullFolderName += string("\\"); 
       aFullFolderName += aDirName; 

       string aChildrenFolders = parseDirectory(aFullFolderName, aDirName); 
       if(aChildrenFolders.compare("")) 
       { 
        aChildren += aChildrenFolders; 
       } 
      } 

      (void) closedir (dp); 
     } 
     else 
      perror ("Couldn't open the directory"); 

     return aChildren; 
    } 
}; 
Смежные вопросы