Rekursive Ordnersuche und Listenspeicherung



  • Hallo

    Habe mir ein Programm geschrieben, welches einen Ordner samt Unterordner durchsuchen soll und alle gefundenen mp3 und wma Dateien in eine Liste speichert.

    Leider werden die darin befindlichen Ordner nicht durchsucht und das Programm stürzt leider auch ab.

    Seltsamerweise enthält das letzte Listenelement keine Mp3-Datei sondern nur einen '-'.

    Habe mir den Code an Hand vom Galileo-Book erarbeitet.

    Bitte, bitte helft mir, ich bin echt am abkacken.

    vielen Dank

    #include <cstdlib>
    #include <iostream>
    #include <dirent.h>
    #include <direct.h>
    #include <cstdio>
    #include <windows.h>
    #include <conio.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    #define LengthName 200
    #define Quantity 50
    
    using namespace std;
    
    typedef char FNAME[LengthName];
    
    char NeuerOrdner(){
    
        FNAME PfadNeu;
    
        cout<<"\n\nNeuen Ordner angeben!\n:-:> ";
        cin>>PfadNeu;
        _mkdir(PfadNeu);
    }
    
    bool IsDir(char* pFName) {
    
        struct stat File_Attribut;
    
        File_Attribut.st_mode = 0;
        stat(pFName, &File_Attribut);
    
        return ((File_Attribut.st_mode & S_IFDIR) == S_IFDIR);
    }
    
    struct MP3_List{
    
        FNAME Pfad;
        struct MP3_List *Next;
    
    } *Anfang=NULL, *pMP3_List, *Next=NULL; ;
    
    void DirSeek (char *WorkDir , DIR *pWorkDir, int cnt){
    
        FNAME   File_Location;
        struct  dirent *pDir;
        struct  stat File_Attribut;
    
        cout <<Anfang<<"\n";
    
        if(Anfang == NULL) {
    
          if( (Anfang = (struct MP3_List *)malloc(sizeof(struct MP3_List))) == NULL ) {
             fprintf(stderr, "Kein Speicherplatz für anfang vorhanden!\n");
             return;
          }
          pMP3_List = Anfang;
        }
    
        WorkDir= strcat(WorkDir,"\\");
        cout<<"\n\nGerade geoeffnet: "<<WorkDir<<endl<<endl;
    
        while ((pDir=readdir(pWorkDir)) != NULL){
    
            if(strcmp(pDir->d_name,"..")!=0 && strcmp(pDir->d_name,".")!=0){
    
                strcpy(File_Location, WorkDir);
                strcat(File_Location, pDir->d_name);            
    
                if(IsDir(File_Location)){
    
                    cout<<"\tORDNER";
                    DirSeek(WorkDir,pWorkDir,cnt);
    
                }
                else {
                    cout <<"\tDATEI ";
                    cout <<cnt;
    
            //######### MP3-Dateien finden ####################################//
    
                    int NLength = strlen(File_Location);      
    
                    if (strcmp(&File_Location[NLength-4],".mp3")==0||
                        strcmp(&File_Location[NLength-4],".wma")==0){
    
                            strcpy(pMP3_List->Pfad,File_Location);
                            cnt++;
                    }
                    cout <<pMP3_List->Pfad<<"\n";
                }
    
                if( (pMP3_List->Next = (struct MP3_List *)malloc(sizeof(struct MP3_List))) == NULL ) {
                     fprintf(stderr, "Kein Speicherplatz für weitere MP3-Datei vorhanden!\n");
                     return;
                }
    
                pMP3_List    = pMP3_List->Next;
            }
        }
    
        cout <<"\n";
        cout.fill('#');cout.width(50); cout<<"\n";
        cout <<"\n\tGefundene Audio-Dateien\n\n";
        cout.fill('#');cout.width(50); cout<<"\n";
        cout <<"\n";
    
        int k=0;
        pMP3_List = Anfang;
        while (k<=cnt){             
    
            cout <<"\tIndex"<<"  "<<k<<"  "<<pMP3_List->Pfad <<endl;
            pMP3_List = pMP3_List->Next;
            k++;
        }
    }
    
    //  ###### MAIN #######################
    
    int main(){
    
        FNAME  WorkDir="c:\\abc";
        int    pIndex=0;
        DIR    *pWorkDir;
        int    MP3_Counter   =0;
    
         while(!(pWorkDir=opendir(WorkDir)))
            {
                cout<<"Nix Ordner, ein Neuer muss her! /: ";
                cin>>WorkDir;
                pWorkDir=opendir(WorkDir);
            }
        cout<<"Ordner erfolgreich geoeffnet"<<"\n";
    
        DirSeek(WorkDir,pWorkDir,MP3_Counter);
    
        getch();
    }
    


  • PlattitüdenAbonennt schrieb:

    [cpp]
    cout<<"\n\nNeuen Ordner angeben!\n:-:> ";

    das ist schon mal falsch. einen string kann man nicht als shift-count benutzen. auch falls es gehen würde, so ist dieser ganze ausdruck sinnlos, weil eine zuweisung fehlt (das ergebnis der shift-operation wird von diesem code ignoriert).
    🙂



  • #include <windows.h>
    

    Kann die Datei auf meinem System nicht finden. Was war nochmal Windows?

    bool IsDir(char* pFName) {
    

    Sollte nur gehen, wenn man stdbool.h inkludiert.

    fprintf(stderr, "Kein Speicherplatz für anfang vorhanden!\n");
    

    Die Alternative zu den ungültigen Shifts hast du selbst vorgeschlagen. Mein Buttler wollte mir gerade etwas von cerr erzählen, aber ich hab ihn aus dem Zimmer gejagt.

    int main()
    

    Der heilige Standard befielt, daß bla bla bla.

    using namespace std;
    

    Kompiliert nur, wenn ich vorher sage: #define using // .
    🙂

    Bitte, bitte helft mir, ich bin echt am abkacken.

    Bis die C-Variante läuft, empfehle ich etwas in der Art:

    dir /s /b | grep mp3 > nirvana
    


  • ich würde sagen das du im falschen forum bist.. da das kein ansi-c sonden imho c++ ist.

    nix für ungut 😉



  • operatoren-freak schrieb:

    PlattitüdenAbonennt schrieb:

    [cpp]
    cout<<"\n\nNeuen Ordner angeben!\n:-:> ";

    das ist schon mal falsch. einen string kann man nicht als shift-count benutzen. auch falls es gehen würde, so ist dieser ganze ausdruck sinnlos, weil eine zuweisung fehlt (das ergebnis der shift-operation wird von diesem code ignoriert).
    🙂



  • Hallo

    Danke erstmal für die Tipps 😉
    Wir hatten im Studium C und dann C++, deswegen ist das so ein Code-Mischmasch geworden.

    Gleich zum 1.:

    cout<<"\n\nNeuen Ordner angeben!\n:-:> ";
    

    Das soll nichts weiter als eine stinknormale Textausgabe sein. Da ich ein C-Einsteiger bin, könnte es sein, dass diese ":-:>"-Zeichenkette noch eine andre Bedeutung in C hat? War nur als markanter Platzhalter gedacht.

    2.: Die bool Isdir-Funktion funktioniert bei mir tadellos.

    3.:

    c-flamer schrieb:

    fprintf(stderr, "Kein Speicherplatz für anfang vorhanden!\n");
    

    Die Alternative zu den ungültigen Shifts hast du selbst vorgeschlagen. Mein Buttler wollte mir gerade etwas von cerr erzählen, aber ich hab ihn aus dem Zimmer gejagt.

    Das hab ich einfach aus dem Tutorial kopiert. Ungültige Shifts, diese Aufzeichnung findet sich in meiner Großhirnrinde leider (noch) nicht. Bitte um Erläuterung.

    4.:

    c-flamer schrieb:

    Bis die C-Variante läuft, empfehle ich etwas in der Art:

    dir /s /b | grep mp3 > nirvana
    

    Sorry, aber da steig ich nicht dahinter.

    Die eigentlichen Probleme sind aber: Der rekursive Funktionsaufruf funktioniert nicht wie gewollt, d.h. das Programm sucht nicht in den Unterordnern und es stürzt nach der Ausgabe des letzten Listenelements ab.

    Ich werde mich zu Hause erst mal hinsetzen und die kleinen Schönheitsfehler korrigieren.

    Vielen Dank für die Aufmerksamkeit.



  • zu 1:
    << ist einer der beiden bitweisen Shift-Operatoren. Ist aber in C++ auch so (zumindest für naive Datentypen), aber in C++ ist er eben für Streams überladen.

    zu 2:
    C kennt keinen bool-Typ. Seit C99 gibt es aber man: stdbool.h, wo ein boolscher Typ nachgerüstet wird.
    Wenn's tadellos funktioniert, dann hast du einen C++-Compiler verwendet.

    zu 3:
    man: printf und alles was ähnlich klingt ist in C für formatierte Ausgabe zuständig, also für alles, was du sonst mit cout, cerr und Freunden machen würdest.

    zu 4:
    Normalerweise macht man sowas mit einem kurzen Shell-Script, zB auf die skizzierte Weise.

    Mehr als den Code in Ruhe lesen kann ich hier auch nicht, weil ich kein Windows hier hab. Aber das werd ich einmal machen.



  • scherzkeks-flamer schrieb:

    zu 1:
    << ist einer der beiden bitweisen Shift-Operatoren. Ist aber in C++ auch so (zumindest für naive Datentypen), aber in C++ ist er eben für Streams überladen.

    was diese komische faxensprache der malloc-caster für seltsame dinge macht, sollte ein c-progrämmchen aber eher weniger jucken.
    🙂



  • esotericlanguage-freak schrieb:

    was diese komische faxensprache der malloc-caster für seltsame dinge macht, sollte ein c-progrämmchen aber eher weniger jucken.

    Da hast du recht, mein Räuberhauptmann. Aber ich wollte wieder einmal ein bißchen nett sein...

    Man gibt einmal zu, daß man sich in einem früheren Leben mit esoterischen Sprachen befasst hat, und:
    sofort schämt man sich.
    🙂



  • flamer schrieb:

    Man gibt einmal zu, daß man sich in einem früheren Leben mit esoterischen Sprachen befasst hat, und:
    sofort schämt man sich.

    kein grund zur verzweiflung. manche müssen erst in die hölle hinabgestiegen sein, um danach die eleganz und schönheit von C zu erkennen.
    🙂



  • Bau dir am besten ein kleines Baumsystem dafür, denn Rekursion ist doof weil laaahm.
    Lieber eine bis zwei while Schleifen mehr.



  • Rekursionsverweigerer schrieb:

    denn Rekursion ist doof weil laaahm.

    Ignorant! 😡
    ( 🕶 )



  • Javaner schrieb:

    Rekursionsverweigerer schrieb:

    denn Rekursion ist doof weil laaahm.

    Ignorant! 😡
    ( 🕶 )

    Ignorant von was ?
    Von Tatschen, die sich in jedem Fachbuch, in jedem zweiten Onlineartikel über rekursive Programmierung nachlesen lassen ?



  • Rekursionsverweigerer schrieb:

    Ignorant von was ?
    Von Tatschen, die sich in jedem Fachbuch, in jedem zweiten Onlineartikel über rekursive Programmierung nachlesen lassen ?

    Und was ist mit der anderen Hälfte der Bücher?

    Sorry, aber ich bin in (vernünftige) Rekursionen sogar verliebt.

    Wobei eine rekursive Fakultätsberechnung (das häufigste
    Beispiel zur Einführung von Rekursionen) natürlich schwachsinnig ist.



  • Wobei eine rekursive Fakultätsberechnung (das häufigste
    Beispiel zur Einführung von Rekursionen) natürlich schwachsinnig ist.

    Warum denn? Brauchst dazu ja nur die beiden Definitionen aus dem Mathebuch abzuschreiben.

    Die meisten Argumente a la rekursiv geht schief bauen ja darauf, daß mein C-Compiler keine Endrekursionsoptimierung schafft. Wie kommt ihr da eigentlich drauf?



  • So hab endlich mal wieder zeitgefunden mich mit dem Programm zu beschäftigen.

    if(IsDir(File_Location)){
                    strcpy(Temp, WorkDir);
    
                    cout<<"\tORDNER";
                    strcat(WorkDir,pDir->d_name);
                    DirSeek(WorkDir,pWorkDir,cnt);
    
                    strcpy(WorkDir, Temp);
    
                }
    

    Damit mein Programm nach dem rekursiven Aufruf wieder mit dem alten Verzeichnis weiterarbeiten kann habe ich noch eine Temp-variable vom typ char mit der Länge von 200 eingebracht, ihr seht ja was ich meine.
    Aber leider enthält dieses Temp nach dem Reinkopieren von WorkDir eben diesen Pfad und noch haufenweise kryptische Zeichen, eben soviele, bis die 200 Zeichen voll sind.
    Wie kann ich das elegant lösen, dass wirklich nur der Pfad in Temp enthalten ist?

    dank euch



  • wenn kein stuss in Temp stehen soll, darf auch kein stuss WorkDir stehen, denn es wird ja nur kopiert.
    ansonsten sind 200 zeichen zu wenig. windows hat ne konstante, MAX_PATH, für sowas.



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum DOS und Win32-Konsole verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Ich hab zwar keine Ahnung, warum mein Thread verschoben worden ist, aber solange man mir hier auch weiterhelfen kann, ist mir das gleich.

    Zu der Tempvariable: beim Debugging sieht Workdir z.B. so aus "c:\\abc\", beim aufruf von strcpy(Tempt, WorkDir) habe ich in Temp aber leider solchen Mist drinstehen: "c:\\abc\'§/"(§()&&&&$$/"("("!!(§§&§$$/(§/&...." also lauter Werte die eben der Speicher vor der Deklarierung von Temp enthielt.

    Wie kann ich das Bewerkstelligen, dass in Temp wirklich nur das drinsteht was in WorkDir enthalten ist?

    danke



  • PlattitüdenAbonennt schrieb:

    Ich hab zwar keine Ahnung, warum mein Thread verschoben worden ist, aber solange man mir hier auch weiterhelfen kann, ist mir das gleich.

    Dein Problem bezieht sich einfach nicht auf ANSI/ISO C. Die verwendeten Funktionen opendir etc. sind nicht Teil des C Standards, sondern Windows spezifisch. Daher habe ich dich hierher verschoben.

    Der Misst liegt übrigens daran, dass du den String nicht richtig 0 terminiert hast.



  • Hallo,

    was bedeutet 0 terminieren ?


Anmelden zum Antworten