Ausgabe Dateien, (und sub-)directorys, mit dirent



  • guten morgen,

    ich habe im zuge meiner Lehre die aufgabe bekommen, ein programm zu schreiben, das (unter Unix) den kompletten Dateibaum eines eingegebenen Verzeichnisses ausgibt

    (Dateien, Verzeichnisse, dessen unterverzeichnisse usw.)

    Hier die Rekursive Funktion, die diese Aufgabe übernehmen soll:

    void ausgabe(char *dirName)
    {
    
    	if (!(myDir=opendir(dirName))) 
    	{
    		cout << "Verzeichnis kann nicht geoeffnet werden: " << dirName << endl;
      	} 
    	else
    	{
    		while (entry=readdir(myDir))
    		{
    			cout << "Eintrag: " << entry->d_name << endl;
    			dirName=(*dirName+entry->d_name);
    			ausgabe((dirName));
    		}
    
    		closedir(myDir);
    	}
    

    Deklerationen/Definition der Variablen

    void ausgabe(char *dirName);
    
    	DIR *myDir;
    	char *dirName="/home/dir";
    	struct dirent *entry;
    

    Fehler: Ich bekomme einen speicherzugriffsfehler, wenn ich

    dirName=(*dirName+entry->d_name);
                ausgabe((dirName));
    

    auskommentiere zeigt er mir das Verzeichnis korrekt an.

    ich habe schon gegoogled, und auch die altanative "getcurrentdirectory" und "setcurrentdirectory" probiert, leider ohne erfolg, was villeicht auch daran lag das ich keine vernümpftige referenz dazu gefunden habe.

    jemand ne idee?

    PS: hat jemand einen link zu einer liste (referenz) der möglichen typenumwandlungsfunktionen? ich finde keine vernümpftige übersicht dazu



  • Versuchst du hier, 2 char-Zeiger (char*) zu addieren? Das geht nicht. Strings zusammenfügen kannst du z.B. mit strcat (da musst du aber dafür sorgen, dass der char-Puffer groß genug ist). Eine sinnvolle Alternative wäre std::string, das vergrößert sich automatisch und da kannst du einfach per operator+ einen String dranhängen.



  • _matze schrieb:

    [...]Eine sinnvolle Alternative wäre std::string, das vergrößert sich automatisch und da kannst du einfach per operator+ einen String dranhängen.

    das habe ich auch schon so überlegt, allerdings erwartet
    (myDir=opendir(dirName)) einen char zum öffnen, man kann das sicher umwandeln, nur weiß ich nicht wie

    (daher mein PS^^)

    mit ner guten referenz zu den typenumwandlungsfunktionen (am besten auf deutsch) wäre mir auchs chon gut geholfen^^

    edit::

    wenn ich std::string nutze, dann zeigt er mir folgenden fehelr an:

    Zeile 29 Fehler: »std::string*« kann nicht nach »const char*« für Argument »1« nach »DIR* opendir(const char*)« umgewandelt werden

    if (!(myDir=opendir(dirName)))
    

    ist besagte zeile.


  • Administrator

    http://www.cplusplus.com/reference/string/string/c_str/

    Übrigens, vielleicht wäre noch diese Bibliothek eine interessante C++ Alternative:
    http://www.boost.org/doc/libs/1_38_0/libs/filesystem/doc/index.htm

    Grüssli



  • std::string hat die Methode c_str, die gibt dir einen char-Zeiger zurück.



  • soweit so gut, leider immernoch nicht funktionstüchtig, habe leider jetzt grade leider nicht die zeit mich wirklich in die funktionsweise von c_str einzulesen...

    er wirft mir folgenden fehelr aus:

    20: Fehler: ungültige Umwandlung von »const char*« in »char*«

    cin >> temp;		//zeile 19
    	dirName=temp.c_str();	//zeile 20
    

    deklaration von "temp": string temp;



  • Benenne temp in dirName um und übergib dirName.c_str() direkt.



  • das problem war ein anderes, das ich inzwischen gelöst habe (frag mich nicht wie, ich weiß es garnicht mehr^^)

    derzeit ist das problem ein neues, er schmeißt mir als ersten wert für entry->d_name ein ".." aus.

    das problem sit nun, das er nun quasi folgendes probiert:

    statt:

    /home/(ordner/datei)

    macht er

    /home/../ordner/datei)

    2 fragen die mich quälen...

    1. wie kann ich ermitteln, ob das makierte unterobject des aktuellen verzeichnisses eine datei oder ein verzeichnis ist?

    (habe da was gefunden das nent sich S_ISDIR(), aber da blicke ich nicht so ganz durch)

    2. lässt sich der aktuelle fehelr irgendwie abfangen? habe es (so naiv wie ich bin) mit ner if abfrage probiert nach dem schema:

    if (entry->d_name!="..")
    				{
    					temp=temp+entry->d_name+"/";
    				}
    

    probiert, kein erfolg



  • Was ist denn d_name ? Wenn das ein char* ist, hast du wieder das gleiche Problem.



  • d_name ist die "datei/ordner", die grade "selektiert" ist, kommt aus dem structurelement *entry vom typ dirent



  • Ja, und was für ein Datentyp? Du vergleichst ihn schliesslich mit einem const char* .



  • Nexus schrieb:

    Ja, und was für ein Datentyp? Du vergleichst ihn schliesslich mit einem const char* .

    das ist eine gute frage, ich bin davon ausgegangen das es sichd abei um einen const char* handelt, allerdings bin ich mir nicht sicher, ich schau mal in der entsprechenden libary nach...

    ich meld mich dann,

    edit::
    ich hab mal nachgeschaut, bei entry->d_name[] handelt es sich um den typ char


  • Administrator

    Lodoss schrieb:

    1. wie kann ich ermitteln, ob das makierte unterobject des aktuellen verzeichnisses eine datei oder ein verzeichnis ist?

    Womöglich fragst du das besser im Linux/Unix Forum hier. Das ist eine Frage an die entsprechende Unix C Bibliothek.
    Oder du nimmst die C++ Bibliothek Boost.Filesystem, dann musst du dich auch nicht immer mit C rumschlagen, da alles schön in C++ gemacht ist.

    Lodoss schrieb:

    2. lässt sich der aktuelle fehelr irgendwie abfangen? habe es (so naiv wie ich bin) mit ner if abfrage probiert nach dem schema:

    if (entry->d_name!="..")
    // ...
    

    probiert, kein erfolg

    Wenn, wie du gesagt hast, d_name ein char[] ist, dann vergleichst du hier nicht zwei Inhalte sondern zwei Zeiger. Und die werden ziemlich sicher immer ungleich sein. Also diese Anweisung ergibt immer true .
    Ein Stringliteral (z.B. ".." ) ist nichts anderes als ein char const* . Wenn d_name ein char Array ist (also char[] ), dann wird dieses vor dem Vergleich implizit in einen Zeiger auf das erste Element umgewandelt. Also wird gerprüft, ob es zwei gleiche Speicheradressen sind 😉

    Die einfachste Möglichkeit, welche du hier hast, wird wohl die C Funktion strcmp sein:
    http://www.cplusplus.com/reference/clibrary/cstring/strcmp/

    Sofern natürlich d_name ein 0 terminiertes char Array ist. Was aber ziemlich wahrscheinlich ist. Sicherheitshalber solltest du das aber noch nachprüfen 😉

    Grüssli


Anmelden zum Antworten