0

ディレクトリを読み取り、含まれているすべてのディレクトリと各ディレクトリのすべてのサブディレクトリを検索してデータ構造に保存するメソッドを作成したいと考えています。具体的には、名前を次のように引用したい:

フォルダ1 フォルダ11 フォルダ12 フォルダ2 フォルダ21 フォルダ22 フォルダ23

明らかに再帰を伴う関数が必要です。コンソール アプリケーションでクラス メンバー メソッドを次のように一時的に使用します。

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");

}

わかりました、最適なコードを書いたわけではありませんが、最初にキャッチされた名前を表示したいと思います。ただし、親ディレクトリの名前を複数回考慮するため、正しく機能しません。同じメソッドの呼び出しを (再帰を実行せずに) 出しても、最初の 2 つの名前は . と .. 。なんで?

説明されているプロセスを実行する関数を提案してもらえますか、またはこの関数に必要な修正を示してもらえますか?

4

2 に答える 2

4

いくつかのコメントが指摘しているように、boost::filesystemが通常の方法です。しかし、あなたのコードからは、あなたはまだC ++の初心者であるように思われるので、私はC ++の慣用的な方法で書き直し、少し便利な表示を追加しました。HTH

#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;は、再帰中に上書きするため、クラスに格納するのは明らかに間違っていることに注意してください...

于 2012-06-19T09:06:49.523 に答える
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;
    }
};
于 2012-06-19T09:08:21.343 に答える