-2

I'm currently stuck using dirent.h extension. The goal is to give the function a path directory to start from. That function would then look through all the subfolders from that directory and find files in it. It all works until there are two folders in the same directory. Then the program stubbornly chooses one folder and ignores the other. Here goes my mess of a code. (The issue is commented at the bottom of the code)

    #include <iostream>
    #include "dirent.h"
    #include <windows.h>

    DWORD getPathType(const char *path); //checks if path leads to folder or file
    const char *dirlist[20];  //contains all directories (not files, only dir's)
    int dirAm = 0;            //specifies amount of directories

    void loadTextures(const char *loaddir) {

        dirlist[dirAm] = loaddir;  //specifies starting directory
        dirAm++;

        for(int i = 0; i<20; i++) {
            DIR *dir;
            struct dirent *ent;
            const char *currentdir = dirlist[i];  //stores current directory
            dir = opendir(currentdir);            //opens current directory

            if (dir != NULL) {
                std::cout << "[OPENING dir]\t" << currentdir << std::endl;

                while ((ent = readdir(dir)) != NULL) {
                    const char *filename;  //stores current file/folder name
                    char fullDirName[100]; //stores full path name (current dir+file name, for example /images/+image1.png)
                    DWORD filetype;        //checking path type (file/folder)
                    filename = ent->d_name; //gets current file name

                    strcpy(fullDirName, currentdir); //concats current directory and file name to get full path, for example /images/image1.png
                    strcat(fullDirName, filename);

                    filetype = getPathType(fullDirName); //gets path type
                    if (filetype == FILE_ATTRIBUTE_DIRECTORY) {
                        //if its a directory add it to the list of directories, dirlist, the naming process is the same as above
                        const char *filenameIn;
                        char fullDirNameIn[100];

                        filenameIn = ent->d_name;

                        strcpy(fullDirNameIn, currentdir);
                        strcat(fullDirNameIn, filenameIn);
                        strcat(fullDirNameIn, "/");
                        std::cout << "[FOUND dir]\t" << fullDirNameIn<<std::endl;

                        dirlist[dirAm] = fullDirNameIn;
                        dirAm++;

                        /* Here is the problem! The cout line above finds all
 folders in a directory and saves them in the array, but as soon as the new for
 loop iteration starts, the values in the dirlist array... change? And I have no
 idea what is going on */

                    } else {
                        std::cout << "[FOUND file]\t" << fullDirName << std::endl;
                    }
                }
            }
        }

And here is the getPathType() function. Pretty straight forward, I guess.

DWORD getPathType(const char *path) {
    DWORD fileat;
    fileat = GetFileAttributesA(path);
    return fileat;
}

Finally, here is the console output:

[OPENING dir]   img/                 <- opens starting dir
[FOUND dir]     img/lvl0/            <- finds lvl0, should store it in dirlist
[FOUND dir]     img/lvl1/            <- finds lvl1
[OPENING dir]   img/lvl1/
[FOUND file]    img/lvl1/player2.png
[OPENING dir]   img/lvl1/            <- only opens lvl1
[FOUND file]    img/lvl1/player2.png

I know this is a very big question, but I would be quite thankful if someone could share ideas on this.

user4581301
  • 33,082
  • 7
  • 33
  • 54
Ziphold
  • 21
  • 5
  • I recommend adding a [mcve]. Not only is making one likely to answer your question, they also make questions and answers more applicable to a wider pool of future askers. – user4581301 Jul 18 '18 at 18:43
  • 2
    I suggest you use string variables such as `std::string`, not `char *` to store names. In addition, it would cut out the `strcat` / `strcpy` that's going on. You're using C++ -- any reason why you're resorting to `C`-like programming? – PaulMcKenzie Jul 18 '18 at 18:46
  • When you are producing the MCVE, keep an eye on the scope of your variables and resist the urge to store pointers to tightly scoped Automatics. – user4581301 Jul 18 '18 at 18:47
  • 1
    Also `char fullDirName[100];` -- directory names can be greater than 100 characters on most operating systems. – PaulMcKenzie Jul 18 '18 at 18:50
  • `dirent.h` ? Ew. You're on Windows, filenames are not ASCII. – MSalters Jul 18 '18 at 20:16

1 Answers1

1

You are ignoring the scope of your char arrays. Effectively you are doing this

const char *dirlist[20];

while (...)
{
    char fullDirNameIn[100];
    ....
    dirlist[dirAm] = fullDirNameIn;
}

The problem is that your array is scoped to the body of while loop but you are storing a pointer to that array outside the while loop. After you exit the body of the loop (i.e. when you iterate) then contents of your array become undefined, but you still have a pointer to it.

The solution is easy and this should be a lesson well learned. Don't use pointers, do what experienced programmers do and use std::string instead.

std::string dirlist[20];

while (...)
{
    std::string fullDirNameIn;
    ....
    dirlist[dirAm] = fullDirNameIn;
}
john
  • 85,011
  • 4
  • 57
  • 81
  • After modifying all char arrays to std::strings, everything worked amazingly! Thank you for bothering! – Ziphold Jul 18 '18 at 19:35