PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Verzeichnisinhalt auslesen mit C++



Nicolas
18-08-2002, 20:43
Hallo!

Gibt es eigentlich unter C++ Funktionen um ein Verzeichnis auszulesen oder muss ich da auf die :mad: C Funktionen zurückgreifen?
Danke schon im Vorraus!

Nicolas

tkortkamp
18-08-2002, 22:07
Da musst du die C-Funktionen nehmen.

c ya,
Tobias

tkortkamp
18-08-2002, 22:24
He hab ich gerade bei mir im Projekte/ Ordner gefunden ;)


/*
Copyright (c) 2002 Tobias Kortkamp

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <dirent.h>
#include <iostream>
#include <string>
#include <vector>

namespace std {
class dir
{
public:
dir(const char *dir)
{
directory = opendir(dir);
}

std::vector<std::string> getEntries()
{
struct dirent *dirEntry;
std::vector<std::string> retVal;
if(directory == 0)
{
return retVal;
}

while((dirEntry=readdir(directory)))
{
curDirEntry = dirEntry;
if(selectDirEntry())
{
std::string str(dirEntry->d_name);
retVal.push_back(str);
}

}
return retVal;
}

~dir()
{
closedir(directory);
}

virtual bool selectDirEntry()
{
//Check wheter we want this particular directory entry.
//all informations are in the struct curDirEntry
return true;
}

protected:
struct dirent* curDirEntry;
DIR *directory;
};
}

int main(void)
{
std::dir dir("./");

std::vector<std::string> ret = dir.getEntries();

std::cout << ret[6] << std::endl;
}

Vielleicht findest du das ja nützlich.

c ya,
Tobias

Nicolas
19-08-2002, 14:09
Danke für deine gute Antwort. Aber wäre es nicht einfacher, einfach eine Funktion zu bauen statt eine ganze Klasse? Ich benutze ja die Klasse nur ein einziges Mal zum Auslesen des Verzeichnisinhaltes.

Nicolas

tkortkamp
19-08-2002, 14:13
Hab das glaub ich mal so gemacht, dass man mit selectDirEntry() bestimmt Einträge im Verzeichnis zulassen bzw. weglassen kann. Dafür hilft dann curDirEntry. Sonst müsste man das über Funktionspointer machen.

c ya,
Tobias

Nicolas
19-08-2002, 15:28
Ach so. Ich hab das jetzt als eigene Funktion, denn das mit dem Eintrag auswählen brauch ich ja eh nicht. Nur weiß ich halt nicht genau, ob es überhaupt sinnvoll ist, in C++ Funktionen zu verwenden.

Nicolas

nobody0
19-08-2002, 21:06
Original geschrieben von tkortkamp
He hab ich gerade bei mir im Projekte/ Ordner gefunden ;)


/*
Copyright (c) 2002 Tobias Kortkamp

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <dirent.h>
#include <iostream>
#include <string>
#include <vector>

namespace std {
class dir
{
public:
dir(const char *dir)
{
directory = opendir(dir);
}

std::vector<std::string> getEntries()
{
struct dirent *dirEntry;
std::vector<std::string> retVal;
if(directory == 0)
{
return retVal;
}

while((dirEntry=readdir(directory)))
{
curDirEntry = dirEntry;
if(selectDirEntry())
{
std::string str(dirEntry->d_name);
retVal.push_back(str);
}

}
return retVal;
}

~dir()
{
closedir(directory);
}

virtual bool selectDirEntry()
{
//Check wheter we want this particular directory entry.
//all informations are in the struct curDirEntry
return true;
}

protected:
struct dirent* curDirEntry;
DIR *directory;
};
}

int main(void)
{
std::dir dir("./");

std::vector<std::string> ret = dir.getEntries();

std::cout << ret[6] << std::endl;
}

Vielleicht findest du das ja nützlich.

c ya,
Tobias

Also kompieren kann ich das mit dem g++, aber in /tmp, wo viel drinnsteht, bekomme ich damit nur:

targetMap_e

:confused:

tkortkamp
19-08-2002, 21:13
Ja ist klar, dass gibt nur den 7. Eintrag im Verzeichnis aus. (6+1)



//ret ist ein std::vector, in dem stehen alle Verzeichniseinträge(inkl . und ..)
std::vector<std::string> ret = dir.getEntries();
//Hier bekommen wir mit ret[6] das 7. Element aus dem std::vector
std::cout << ret[6] << std::endl;

Ersetzt du das jetzt mit:


for(int i=0; i < ret.size(); i++)
{
std::cout << ret[i] << std::endl;
}

bekommst du alle Verzeichniseinträge.

c ya,
Tobias

nobody0
20-08-2002, 15:38
Original geschrieben von tkortkamp
Ja ist klar, dass gibt nur den 7. Eintrag im Verzeichnis aus. (6+1)



//ret ist ein std::vector, in dem stehen alle Verzeichniseinträge(inkl . und ..)
std::vector<std::string> ret = dir.getEntries();
//Hier bekommen wir mit ret[6] das 7. Element aus dem std::vector
std::cout << ret[6] << std::endl;

Ersetzt du das jetzt mit:


for(int i=0; i < ret.size(); i++)
{
std::cout << ret[i] << std::endl;
}

bekommst du alle Verzeichniseinträge.

c ya,
Tobias

Klar, das mit dem 7. Eintrag hatte ich zu schnell quergelesen, danke für den Hinweis.
Alledings ist das ret.size() unbekannt: `ret' undeclared (first use this function).
Es soll wohl eine Funktion sein, die die Grösse des Vektors bestimmt, aber ret.size() wird vom g++ nicht akzeptiert. :confused:

Wieso kann der gcc das Programm nicht kompilieren? Der ist doch auch ein C++-Kompiler, oder? :confused:

tkortkamp
20-08-2002, 15:43
Nö ist er nicht, g++ ist der C++-Compiler, gcc der C-Compiler.
Und bei mir mit g++ 2.95.4 kompiliert der Code einwandfrei...

c ya,
Tobias

nobody0
21-08-2002, 02:09
Ok, aber was ist mit ret.size()
?

:confused:

tkortkamp
21-08-2002, 06:11
Was soll damit sein? Ich hab doch schon geschrieben, dass das bei mir einwandfrei funktioniert... Deinen Fehler kann ich nicht reproduzieren.

Welche g++ version hast du? (mit g++ --version bekommst du die Versionsnummer)

EDIT: Sieht die main-Funktion bei dir so aus?


int main(void)
{
std::dir dir("./");

std::vector<std::string> ret = dir.getEntries();
for(int i=0; i < ret.size(); i++)
{
std::cout << ret[i] << std::endl;
}
}


c ya,
Tobias

nobody0
21-08-2002, 21:51
Ok, ich hatte auch die Zeile mit ret= auskommentiert, das war das Problem :rolleyes:

Übrigens gibt der g++ einige warnings:

dirlist0.cpp:80: warning: `class dir' has virtual functions but non-virtual destructor
dirlist0.cpp: In function `int main()':
dirlist0.cpp:89: warning: comparison between signed and unsigned

tkortkamp
21-08-2002, 22:00
Aha :)

Um die Warnungen wegzubekommen änder die Zeiel:
for(int i=0; i < ret.size(); i++) in for(unsigned int i=0; i < ret.size(); i++)
und die zeile ~dir() in virtual ~dir()

c ya,
Tobias

nobody0
21-08-2002, 22:07
Aha, funktioniert, danke.

Ich verstehe nicht ganz, wieso Du überhaupt virtual reingeschrieben hast, aber es funktioniert ja.

tkortkamp
21-08-2002, 22:36
/*
Copyright (c) 2002 Tobias Kortkamp

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <dirent.h>
#include <iostream>
#include <string>
#include <vector>

namespace std {
class dir
{
public:
dir(const char *dir)
{
directory = opendir(dir);
}

std::vector<std::string> getEntries()
{
struct dirent *dirEntry;
std::vector<std::string> retVal;
if(directory == 0)
{
return retVal;
}

while((dirEntry=readdir(directory)))
{
curDirEntry = dirEntry;
if(selectDirEntry())
{
std::string str(dirEntry->d_name);
retVal.push_back(str);
}

}
return retVal;
}

virtual ~dir()
{
closedir(directory);
}

virtual bool selectDirEntry()
{
//Check wheter we want this particular directory entry.
//all informations are in the struct curDirEntry
return true;
}

protected:
struct dirent* curDirEntry;
DIR *directory;
};
}

class customDir : public std::dir
{
public:
customDir(const char *dir) : std::dir(dir)
{
}
~customDir()
{
}

bool selectDirEntry()
{
std::string filename = curDirEntry->d_name;
if(filename == "." || filename == "..")
return false;
return true;
}
};

int main(void)
{
std::dir dir("./");
customDir dir2("./");

std::vector<std::string> ret = dir.getEntries();
std::vector<std::string> ret2 = dir2.getEntries();

std::cout << "Alle Einträge: \n";
for(unsigned int i=0; i < ret.size(); i++)
{
std::cout << ret[i] << std::endl;
}
std::cout << "Alle Einträge außer . und ..:\n";
for(unsigned int i=0; i < ret2.size(); i++)
{
std::cout << ret2[i] << std::endl;
}
}

In der Klasse customDir filtert er die Einträge . und .. raus. Kompilier das mal und teste mal, du wirst sehen, dass das funktioniert. Aber jetzt nimm mal virtual bei selectDirEntry in std::dir weg. Du wirst sehen das, dass jetzt nicht mehr funktioniert, da wir ja die Funktion getEntries() nicht in customDir mit überladen haben. Somit ruft er die selectDirEntry()-Funktion von std::dir auf und nicht die von customDir, das virtual keyword hilft hier.
Nähere Infos dazu findest du z.B. in Thinking in C++ (http://www.mindview.net )

c ya,
Tobias