Rekursiver Funktionsaufruf muckt rum



  • Guten Abend,

    Ich arbeite an einem Projekt und dafür ist es primär notwendig, dass sämtliche Ordner und Dateien eines Verzeichnisses samt Unterverzeichnissen ausgegeben werden.
    Doch leider klappt das mit dem rekursiven Fkt-Aufruf von DirSeek nicht.
    Leider hab ich nur geringe Programmierkenntnisse und nun seid ihr meine letzte Hoffnung. 😞

    Danke für sämtliche Bemühungen!

    Als Entwicklungsumgebung nutze ich wxdev 6.10.2

    #include <cstdlib>
    #include <iostream>
    #include <dirent.h>
    #include <direct.h>
    #include <cstdio>
    #include <windows.h>
    #include <conio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys\stat.h>
    #include <unistd.h>
    
    #define LenDirName 200
    #define Quantity 50
    
    using namespace std;
    
    typedef char FNAME[LenDirName];
    
    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);
    }
    
    void DirSeek (char *Pfad, DIR *pWDir,int Index)
    {
        int     cnt;
        char    File_List   [Quantity][LenDirName];
        char    MP3List     [Quantity][LenDirName];
        char    *WorkDir=Pfad;
        struct  dirent *pDir;
        struct  stat File_Attribut;
    
        pWDir=opendir(WorkDir);
    
        cnt     =0;
        while ((pDir=readdir(pWDir)) != NULL)
        {
            //TEST(Pfad,WorkDir,Index);
    
            if(strcmp(pDir->d_name,"..")!=0 && strcmp(pDir->d_name,".")!=0)
            {
                strcpy(&File_List [Index][0], WorkDir);
                strcat(&File_List [Index][0], pDir->d_name);
    
                if(IsDir(&File_List[Index][0]))
                {
                    if(Index>9) cout << Index <<"  "; else cout << " " << Index <<" ";
    
                    cout<<"ORDNER";
                    strcat(WorkDir, pDir->d_name);
                    strcat(WorkDir,"\\");
    /* ######## Aufruf von DirSeek ##################### */
    
                    DirSeek(WorkDir,pWDir,Index);
    
                }
                else
                {
                    if(Index>9) cout << Index <<"  "; else cout << " " << Index <<"  ";
    
                    cout <<"DATEI ";
                    cout <<"  "<<File_List[Index]<<" \n";
                }
    
            /* ####################################################################### */
            /* ################### MP3-Dateien finden ################################ */
                int NLength = strlen(File_List[Index]);
                if (strcmp(&File_List[Index][NLength-4],".mp3")==0||
                    strcmp(&File_List[Index][NLength-4],".wma")==0)
                {
                    strcpy(&MP3List[cnt][0],pDir->d_name);
                    //strcat(&MP3List[cnt][0],pDir->d_name);
                    cnt++;
                }
    
                Index++;
    
            }
        }
    
        if(cnt!=0)
        {
            cout<<"\n\n";
            cout.fill('#');cout.width(50); cout<<"\n";
            cout <<"\nGefundene Audio-Dateien\n\n";
            cout.fill('#');cout.width(50); cout<<"\n";
    
            for (int k=0;k<cnt;k++)
            {
                cout.width(7);cout.fill(' ');
                cout <<"Index"<<"  "<<k<<"  "<<MP3List[k] <<endl;
    
            }
            cout <<"\n";
         }
    }
    
    //  ###### MAIN #######################
    
    int main()
    {
        char   Pfad[LenDirName]="C:\\abc";
        int    Index=0;
        DIR   *WorkingDir;
    
        /*  cout<<"\n\nPfadangabe :-:>";
            cin>>Pfad;
        */
    
         while( !(WorkingDir=opendir(Pfad)) )
            {
                cout<<"Ordner existiert nicht, bitte gueltigen Ordner angeben!\n Pfadangabe :-:>";
                cin>>Pfad;
                WorkingDir=opendir(Pfad);
            }
        cout<<"Ordner erfolgreich geoeffnet"<<"\n\n";
    
        strcat(Pfad,"\\");
        DirSeek(Pfad,WorkingDir,Index);
    
        getch();
    }
    




  • Doch leider klappt das mit dem rekursiven Fkt-Aufruf von DirSeek nicht.
    Und was klappt nicht?



  • naja ne menge 😞

    Am besten wärs halt, wenn ihr mal den abc-Ordner unter windows erstellt und dort noch nen verzeichnis und in diesem noch eins und dann 2,3 Mp3-Files in jeden ordner reinkopiert.

    Ich kann auch nen screenshot machen aber ich find hier irgendwie keine Möglichkeit, etwas hochzuladen, oder bin ich blind?



  • erm, kanns sein, dass es an deiner IsDir() Funktion liegt?
    Ich dachte da müsste

    return ((File_Attribut.st_mode & S_IFDIR));
    

    stehen, andernfalls

    return (S_ISDIR(File_Attribut.st_mode));
    


  • Heho

    nein an der IsDirFunktion liegts nicht.

    Ich beschreib mal:
    sobald der 1. Ordner gefunden wird, dann geht DirSeek solange vor, bis es nur noch Dateien in einem Ordner findet.
    Deren Namen werden dann ausgegeben, danach müsste das Programm ja in den Ordner darüber springen und dort weitermachen.
    Das klappt nur bedingt, denn erstens wird mir ausgegeben, dass sich die nachfolgenden Ordner im Ausgangsverzeichnis alle in diesem letzten Ordner befinden.
    also: c:\abc ist das Startarchiv
    darin befinden sich

    Datei1.mp3,
    Datei2.mp3,
    Datei3.mp3
     und Ordner
    Interpret1,
    Interpret2,
    Interpret3
    

    Nachdem DirSeek also in Interpret 1 alle Mp3s ausgelesen hat, dann listet er mir auf:

    c:\abc\interpret1\Interpret2
    c:\abc\interpret1\Interpret3
    

    Und dazu kommt noch, dass diese beiden Ordner vom Programm als DATEIEN ausgegeben werden.

    Das ist die ganze Misère.



  • Hm, du veränderst da die ganze Zeit WorkDir, das ja identisch ist mit Pfad. Zeigen beide auf den gleichen Speicherbereich. Das heißt das alle Änderungen im zweiten Aufruf der Methode auch den umgebenden Aufruf beeinflusst.



  • Hallo Fellhuhn,

    Genau das ist das Problem, ich muss es also irgendwie hinbekommen, dass ich jeden Pfad, also das WorkDir auf eine neue Speicheradresse lege und dann sozusagen nur noch den Pointer um 1 erhöhen oder erniedrigen muss, damit ich dann auf die gewünschte Adresse komme.(Weiß aber leider nicht wie und ob das überhaupt funktioniert.)

    Einem Kumpel habe ich das Problem auch mal geschildert und er schickte mir seinen Lösungsansatz, der aber fast identisch mit dem meinen war, nur dem Unterschied, dass WorkDir nicht aus dem File_List-Array geholt wird, sondern gleich WorkDir an die Verzeichnisfunktion IsDir übergeben wird.
    Nun das Problem: An WorkDir wird ja Pfad übergeben doch mit jedem Funktionsaufruf wird der gefundenene Datei/Ordnername an Pfad drangehängt!!! Schlussendlich erhalte ich dann so nen Brei: c:\abc\datei1.mp3Datei2.mp3Ordner1Ornder2
    Und da dieser Mist ja auch wieder an IsDir übergeben wird, wird mir aus der ifelseSchleife auch nur ein "Datei" ausgegeben, da der Rückgabe wert von isDir 0 ist.

    Versteh ich absolut nicht, warum Pfad verändert wird.

    void DirSeek (char *Pfad)
    {
        DIR   *pWDir;
        struct  dirent *pDir;
        struct  stat File_Attribut;
        char *WorkDir;
    
        pWDir=opendir(Pfad);
        while ((pDir=readdir(pWDir)) != NULL)
        {
            WorkDir=Pfad;
            if(strcmp(pDir->d_name,"..")!=0 && strcmp(pDir->d_name,".")!=0)
            {
                strcat(WorkDir, pDir->d_name);
                if(IsDir(WorkDir))
                {
    
                    strcat(WorkDir,"\\");
    				strcat(WorkDir, pDir->d_name);
    
                    cout<<WorkDir<<"\n\n";
                    DirSeek(WorkDir);
                 }
    			else
    			{
    				cout<<"Datei: "<<pDir->d_name<<endl;
    			}
    
            }
        }
    
    }
    


  • PlattitüdenAbonennt schrieb:

    Versteh ich absolut nicht, warum Pfad verändert wird.

    Weil Du den Bereich auf den "Pfad" zeigt "WorkDir" zuweist und anschließend Text daran anfügst.

    WorkDir=Pfad;
    /* ... */
                strcat(WorkDir, pDir->d_name);
    


  • Ja aber wie kann ich das Problem denn dann beheben?

    Falls ihr eine Idee habt, wie kann ich das mit dem Problem mit der separaten Speicherung der Verzeichnispfade kombinieren?

    Vielen Dank



  • PlattitüdenAbonennt schrieb:

    Ja aber wie kann ich das Problem denn dann beheben?

    Du arbeitest nicht auf "Pfad", sondern auf einer Kopie von "Pfad".

    In etwa so etwas:

    WorkDir = malloc(strlen(Pfad) + strlen(pDir->d_name) + 2);
    strcpy(WorkDir, Pfad);
    strcat(WorkDir, "/");
    strcat(WorkDir, pDir->d_name);
    /* ... */
    free(WorkDir);
    

    EDIT:
    In C99:

    size_t lenWorkDir = strlen(Pfad) + strlen(pDir->d_name) + 2;
    char WorkDir[lenWorkDir];
    strcpy(WorkDir, Pfad);
    strcat(WorkDir, "/");
    strcat(WorkDir, pDir->d_name);
    /* ... */
    /* Keine Speicherfreigabe nötig */
    


  • Habs mittles simpelster Lösung hinbekommen:
    Ich speicher vor dem Funktionsaufruf das Arbeitsverzeichnis auf ner Temp-Variablen und setzte das WorkDir danach wieder mittels Temp zurück.
    Mir ist zwar schleierhaft, wie das nach 3 Funktionsaufrufen immer noch funktioniert, aber es KLAPPT irgendwie.

    Neues Problem:

    Übergabe von:

    char    MP3List     [Quantity][LenDirName];
    strcpy(&MP3List[cnt][0],irgendein Dateiname);
    
    ÜBER:
    
    FileCopy(MP3List,Index);
    

    an:

    void FileCopy(char MP3List[][LenDirName],int Index)
    {
        char File_Char;
        mkdir("c:\\bca");
        FILE
            *MP3_Source,
            *MP3_Target;
    
        for (int cnt=0;cnt<Index;cnt++)
        {
            MP3_Source= fopen(strcat("c:\\bca\\",MP3List[cnt]),"r");
            MP3_Target= fopen(strcat("c:\\bca\\",MP3List[cnt]),"w");
    
          while((File_Char=fgetc(MP3_Source))!= EOF)
            fputc(File_Char, MP3_Target);
    
        }
    }
    

    Ich will also den String, der in Mp3List an der gerade aktuellen Position steht an den Ordnerpfad dranbaumeln, aber Programm schmiert bei der Zeile MP3_Source=... ab.

    Vielen Dank für eure Beiträge.



  • Du solltest dir erst noch mal die Grundlagen der C Stringprogrammierung ansehen (Speicherallokation etc.).

    Es funktioniert so nicht bei dir, weil strcat den ersten Parameter als Puffer zum Anhängen benutzt, d.h. du mußt erst einen Puffer dafür anlegen und nicht einen konstanten String (Literal) übergeben.


Log in to reply