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?


  • Mod

    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.


  • Mod

    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.


Log in to reply