2

Trying to get all sub directories, and eventually all files in sub directories, and I'm passing a std::vector as a reference to a function that actually gets all of the directories. I can cout the cFileName inside the function but once it returns the main the vector has weird characters.

Currently have my Character Set to use Unicode. When I was using multibyte it would actually print weird characters, now it prints nothing. The vector does have something in it (directories.size() returns a value > 0)

Can't really think of anything else. Hopefully this was a good question lol. Thanks

#include <iostream>
#include <vector>
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>

// Declare function prototypes
DWORD listDirectories(std::vector<TCHAR*>&);

// Global variable that holds the current working path of the program
TCHAR buffer[MAX_PATH];

void main()
{
    // Declare variables, dwCount for return value from listDirectories, directories stores all sub directories, cDirectory stores current directory
    DWORD dwCount;
    //std::vector<TCHAR*> directories;
    std::vector<TCHAR*> directories;
    TCHAR cDirectory[MAX_PATH];

    // Get current directory
    GetCurrentDirectory(MAX_PATH, buffer);

    // Set cDirectory (current directory) to buffer (ATM is current directory) + add \\ to the end and make it the working directory
    _tcscpy_s(cDirectory, buffer);
    _tcscat_s(cDirectory, L"\\*");

    // dwCount is count of how many directories found, to be used later
    dwCount = listDirectories(directories);

    // Range for loop to print each value in the std::vector<TCHAR*> directories
    for (auto tStr : directories) {
        // Doing wcout here prints weird characters.
        std::wcout << tStr << std::endl;
    }

    std::cin.get();
}   // end void main()

DWORD listDirectories(std::vector<TCHAR*> &directories)
{
    // Declare variables, count used for number of directories, hFind for FindFirstFile, data used to store file data
    DWORD count = 0;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    WIN32_FIND_DATA data;
    TCHAR currentDir[MAX_PATH];

    // Copy the current working directory into currentDir, will be used for subDir
    _tcscpy_s(currentDir, buffer);

    // Append "\\*" to buffer to make it a working directory
    _tcscat_s(buffer, L"\\*");

    // Find first file in the current working directory, storying data in data as a reference
    hFind = FindFirstFile(buffer, &data);

    // If hFind is not an invalid handle
    if (hFind != INVALID_HANDLE_VALUE) {
        // Go through each file in the directory
        do
        {
            // If the file attributes is a directory
            if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                // Create a sub directory
                TCHAR subDir[MAX_PATH];

                // Fill subDir with current directory + "\\" + dir name
                _tcscpy_s(subDir, currentDir);
                _tcscat_s(subDir, L"\\");
                _tcscat_s(subDir, data.cFileName);

                // Fill subDir with current directory + "\\" + dir name
                //sprintf_s(subDir, "%s%s%s", currentDir, "\\", data.cFileName);

                // Add directory to my directories (std::vector<TCHAR*>) if count > 1, because I don't want the "." and ".." directories
                if (count > 1){
                    directories.push_back(subDir);
                    // Doing wcout here prints the subDir just fine and works properly
                    std::wcout << subDir << std::endl;
                }

                // Add 1 to count, used as the return for how many directories found in the current directory
                count++;
            }
        } while (FindNextFile(hFind, &data) != 0);
    }

    // Return count of directories found. -2 to get rid of the "." and ".." directories
    return (count - 2);
}   // end DWORD listDirectories(std::vector<TCHAR*>&)
Praetorian
  • 106,671
  • 19
  • 240
  • 328
Siver
  • 67
  • 1
  • 11

1 Answers1

4

In your listDirectories() function

TCHAR subDir[MAX_PATH];
...
directories.push_back(subDir);

subDir is an array local to the do ... while loop within the function and its lifetime ends with every iteration of the loop.

Change std::vector<TCHAR*> directories; to std::vector<std::basic_string<TCHAR>> directories; and your code should work correctly. Now you'll make a copy of the directory name and add that to the vector.


Another alternative is to forget about all the TCHAR stuff and just use the wide character versions of everything when dealing with the Windows API.

std::vector<std::wstring> directories;
wchar_t cDirectory[MAX_PATH];
...
hFind = FindFirstFileW(buffer, &data);

and so forth

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • making it a std::basic_string worked flawlessly. I don't know much, if anything, about windows coding. This was just my first attempt to get into it. TCHAR was just chosen because I knew it was a typdef for char* that supported multibyte and unicode. I'm just gonna use wstring though since I know it's simpler and if it does work with the windows API. Thank you. – Siver May 12 '15 at 14:46