Verzeichnisaufruf - Rekursion?
-
Hallo liebes Forum,
ich habe eine Verzeichnisausgabe programmiert, diese gibt aber bis jetzt nur den Inhalt des Verzeichnisses an, in welchem sich die Datei befindet. Ich möchte, dass alle Unterverzeichnisse auch noch ausgegeben werden. Wie kann ich dies realisieren?Code:
Verzeichnisse.h
#define _CRT_SECURE_NO_DEPRECATE #define _SCL_SECURE_NO_DEPRECATE #include <iostream> #include <vector> #include <string> #include <time.h> #include <io.h> using namespace std; class clFile; class clDir; // ++++++++++++++++++++++++++++++++++++++++++++++++++++ /** @brief represents a file manager */ // ++++++++++++++++++++++++++++++++++++++++++++++++++++ class clFileManager { public: clFileManager(); virtual ~clFileManager(); void Read(); virtual void PrintTree(); string sGetName(); _fsize_t ulGetSize(); char* pcGetTime(); unsigned int iGetAttr(); protected: vector<clFileManager*>m_aFileList; //!< saves all files into a vector struct _finddata_t m_fFile; //!< file structure intptr_t m_hFile; //!< file handler string m_sName; //!< filename _fsize_t m_ulSize; //!< filesize char* m_pcTimeWrite; //!< last modified unsigned int m_iAttrib; //!< attributes }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++ /** @brief represents a file */ // ++++++++++++++++++++++++++++++++++++++++++++++++++++ class clFile : public clFileManager { public: clFile(); clFile(string, _fsize_t, char*, unsigned int); virtual ~clFile(); virtual void PrintTree(); }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++ /** @brief represents a directory */ // ++++++++++++++++++++++++++++++++++++++++++++++++++++ class clDir : public clFile { public: clDir(string, char*); virtual ~clDir(); virtual void PrintTree(); };
Verzeichnisse.cpp
#include "Verzeichnisse.h" // ------------------------------------------------ /** @brief Constructor for clFileManager */ // ------------------------------------------------ clFileManager::clFileManager() { m_ulSize = NULL; m_pcTimeWrite = NULL; m_iAttrib = NULL; } // ------------------------------------------------ /** @brief Destructor for clFileManager */ // ------------------------------------------------ clFileManager::~clFileManager() { for (unsigned int i = 0; i < m_aFileList.size(); i++) { delete m_aFileList.at(i); } // end for (int i = 0; i < m_aFileList.size(); i++) { while (!m_aFileList.empty()) { m_aFileList.pop_back(); } // end while (!m_aFileList.empty()) { } // ------------------------------------------------ /** @brief Constructor for clDir */ // ------------------------------------------------ clDir::clDir(string sName, char* pTimeWrite) { m_sName = sName; m_pcTimeWrite = pTimeWrite; } // ------------------------------------------------ /** @brief Destructor for clDir */ // ------------------------------------------------ clDir::~clDir() { } // ------------------------------------------------ /** @brief Constructor for clFile (empty) */ // ------------------------------------------------ clFile::clFile() { } // ------------------------------------------------ /** @brief Constructor for clFile (overloaded) */ // ------------------------------------------------ clFile::clFile(string sName, _fsize_t ulSize, char* pcTimeWrite, unsigned int iAttrib) { m_sName = sName; m_ulSize = ulSize; m_pcTimeWrite = pcTimeWrite; m_iAttrib = iAttrib; } // ------------------------------------------------ /** @brief Destructor for clFile */ // ------------------------------------------------ clFile::~clFile() { } // ------------------------------------------------ /** @brief The sGetName function. It simply * returns a file's name. * @return a filename (string) * * @param nothing. * * @author TC * @date 12.03.2013 */ // ----------------------- string clFileManager::sGetName() { return m_sName; } // ------------------------------------------------ /** @brief The ulGetSize function. It simply * returns a file's size. * @return a file's size * (_fsize_t / unsigned long). * @param nothing. * * @author TC * @date 12.03.2013 */ // ----------------------- _fsize_t clFileManager::ulGetSize() { return m_ulSize; } // ------------------------------------------------ /** @brief The iGetTime function. It * returns the date a file * was last modified. * @return last modified date (__time64_t -> char*). * @param nothing. * * @author TC * @date 12.03.2013 */ // ----------------------- char* clFileManager::pcGetTime() { return m_pcTimeWrite; } // ------------------------------------------------ /** @brief The iGetAttr function. It simply * returns a file's attributes. * @return a file's attributes (uint). * @param nothing. * * @author TC * @date 12.03.2013 */ // ----------------------- unsigned int clFileManager::iGetAttr() { return m_iAttrib; } // ------------------------------------------------ /** @brief The Read function. It saves a * directory's contents in a vector. * @return nothing. * @param nothing. * * @author TC * @date 12.03.2013 */ // ----------------------- void clFileManager::Read() { clDir* pDir = NULL; clFile* pFile = NULL; if((m_hFile = _findfirst("*.*", &m_fFile )) == -1L) { // FEHLERQUELLE: m_hFile / m_fFile?! std::cout << "No files in current directory!" << endl; } else { if (!(m_fFile.attrib & _A_ARCH)) { pDir = new clDir(m_fFile.name, ctime(&(m_fFile.time_write))); m_aFileList.push_back(pDir); } else { pFile = new clFile(m_fFile.name, m_fFile.size, ctime(&m_fFile.time_write), m_fFile.attrib); m_aFileList.push_back(pFile); } // end if (m_fFile.size == 0) { while (_findnext(m_hFile, &m_fFile) == 0) { if (!(m_fFile.attrib & _A_ARCH)) { pDir = new clDir(m_fFile.name, ctime(&m_fFile.time_write)); m_aFileList.push_back(pDir); } else { pFile = new clFile(m_fFile.name, m_fFile.size, ctime(&m_fFile.time_write), m_fFile.attrib); m_aFileList.push_back(pFile); } // end if (m_fFile.size == 0) { } // end while (_findnext(m_hFile, &m_fFile) == 0) { _findclose(m_hFile); m_hFile = NULL; } // end if((m_hFile = _findfirst("*.*", &m_fFile )) == -1L) { for (unsigned int i = 0; i < m_aFileList.size(); i++) { m_aFileList.at(i)->PrintTree(); } // end for (unsigned int i = 0; i < m_aFileList.size(); i++) { return; } // ------------------------------------------------ /** @brief The main PrintTree function. * It shouldn't be displayed. * @return nothing. * @param nothing. * * @author TC * @date 21.03.2013 */ // ----------------------- void clFileManager::PrintTree() { cout << "This text shouldn't be displayed." << endl; return; } // ------------------------------------------------ /** @brief The PrintTree function for * the clFile class. Shows * the files' attributes. * @return nothing. * @param nothing. * * @author TC * @date 21.03.2013 */ // ----------------------- void clFile::PrintTree() { std::cout << "|-> " << this->sGetName() << endl; std::cout << "| + " << this->ulGetSize() << " Bytes" << endl; if (this->iGetAttr() & _A_RDONLY) { std::cout << "| + read-only" << endl; } else { std::cout << "| +" << endl; } // end if (this->ulGetSize() & _A_RDONLY) { std::cout << "| + Last modified:\t" << this->pcGetTime() << endl; return; } // ------------------------------------------------ /** @brief The PrintTree function for * the clDir class. Shows * directories' properties and elements. * @return nothing. * @param nothing. * * @author TC * @date 21.03.2013 */ // ----------------------- void clDir::PrintTree() { std::cout << "|--> " << this->sGetName() << endl; std::cout << "| [Folder]" << endl; if (!(this->sGetName() == "." || this->sGetName() == "..")) { this->Read(); } // end if (!(this->sGetName == "." || this->sGetName == "..")) { return; }
main.cpp
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include "Verzeichnisse.h" int main() { clFileManager* Manager = new clFileManager(); Manager->Read(); delete Manager; _CrtDumpMemoryLeaks(); system("PAUSE"); return 0; }
Die einzige Idee, die ich bis jetz hatte, war in der Verzeichnisse.cpp in der Funktion clDir::PrintTree() einen Aufruf this->Read() zu machen - klappt aber nicht, wird zur Endlosschleife, weil er nicht in den Unterordner geht...
Danke schon mal im Voraus.
LG taiBsu
-
Es ist jedesmal ein Graus, solchen Code mit ungarischer Notation zu sehen. Kannst du nicht wenigstens den Code fürs Forum so anpassen, dass wir das nicht zu Gesicht bekommen?
-
Mach mal so:
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include "Verzeichnisse.h" int main() { clFileManager Manager; Manager.Read(); clFileManager Manager2(Manager); _CrtDumpMemoryLeaks(); system("PAUSE"); return 0; }
Zuerst freust Du Dich, dass Du nicht mehr manuell mit delete aufräumen musst, weil der Compiler das für dich tut. Dann überlegst Du Dir, warum das Programm so auf die Nase fällt. Wenn Du das raus gefunden hast, dann nimm ein gutes Buch über C++ und lerne, wofür der Copy-Konstruktor und der Zuweisungsoperator sind.
Und wenn wir schon mal dabei sind:while (!m_aFileList.empty()) { m_aFileList.pop_back();
Das kannst Du entweder so schreiben:
m_aFileList.clear()
oder noch besser ganz weg lassen. Warum sollst Du den Vektor leeren, wenn er sowieso anschließend gelöscht wird.
-
Und was dein new/delete betrifft: http://www.c-plusplus.net/forum/p2308764#2308764
-
Danke für die Tips zur Verbesserung der Codequalität, mir geht's aber im Moment doch eher um die Sache mit der Rekursion, kann mir da erstmal jemand helfen?
-
Bevor du neue Features einbaust, solltest du erst einmal zusehen, dass der Code korrekt ist. Mir fallen da schon beim quer durchlesen Dutzende Fehler auf. Außerdem Designtodsünden. Ich kann gar nicht alles aufzählen. Lies dir ganz dringend mal Bücher über modernes C++ durch (zweiter Link in meiner Signatur). So als Faustregel darfst du mitnehmen, dass du sämtliche new aus deinem Code entfernen solltest, dann wäre schon viel gewonnen. new brauchst du in C++ so gut wie nie und dein Code ist ein Paradebeispiel, wie man es ganz besonders nicht benutzen sollte. Außerdem sollte man genau wissen, wie man mit char-Arrays umgeht, wenn man sie statt std::string benutzt (warum sollte man?). Du zeigerst fröhlich auf sich verändernden statischen Speicher.
Ach, ich könnte noch stundenlang weiter schreiben.
Zu deinem Featurewusch: Rekursion? Du nennst das Stichwort doch schon selber. Wo ist das Problem?
-
SeppJ schrieb:
Bevor du neue Features einbaust, solltest du erst einmal zusehen, dass der Code korrekt ist. Mir fallen da schon beim quer durchlesen Dutzende Fehler auf. Außerdem Designtodsünden. Ich kann gar nicht alles aufzählen. Lies dir ganz dringend mal Bücher über modernes C++ durch (zweiter Link in meiner Signatur). So als Faustregel darfst du mitnehmen, dass du sämtliche new aus deinem Code entfernen solltest, dann wäre schon viel gewonnen. new brauchst du in C++ so gut wie nie und dein Code ist ein Paradebeispiel, wie man es ganz besonders nicht benutzen sollte. Außerdem sollte man genau wissen, wie man mit char-Arrays umgeht, wenn man sie statt std::string benutzt (warum sollte man?). Du zeigerst fröhlich auf sich verändernden statischen Speicher.
Ach, ich könnte noch stundenlang weiter schreiben.
Zu deinem Featurewusch: Rekursion? Du nennst das Stichwort doch schon selber. Wo ist das Problem?
Ich werde mich den Fehlern und Todsünden annehmen, muss aber vorher diese Aufgabe erst mal fertig bekommen. Das Problem ist, dass ich scheinbar nicht darauf komme, an der richtigen Stelle die Rekursion anzusetzen. Da brauche ich ein paar Gedankenstützen.
-
taiBsu schrieb:
Ich werde mich den Fehlern und Todsünden annehmen, muss aber vorher diese Aufgabe erst mal fertig bekommen.
Du weißt schon, was ein Fehler ist, oder? Der TÜV hat dir gerade gesagt, dass bei deinem Auto die Bremsschläuche lecken und Benzin in den Fahrgastraum fließt, aber du möchtest nun stattdessen erst einmal die Lowrider-Aufhängung und die drehende Radkappen einbauen. Komische Prioritäten. Sag hinterher nicht, dass du nicht gewarnt worden wärst.