Visual c++ 递归函数不';t返回正确的值

Visual c++ 递归函数不';t返回正确的值,visual-c++,recursion,Visual C++,Recursion,我有一个递归函数。它对驱动器内的第二个参数中给定名称的文件夹或第一个参数中给定名称的文件夹进行递归搜索。第二个参数中给出的文件夹可以位于第一个参数中给出的驱动器或文件夹中的任何路径和任何嵌套级别上。 所以函数浏览第一个参数中指定的驱动器或文件夹的所有内容,以查找第二个参数中指定的文件夹。下面是函数本身: wstring FolderPathValidator::FindRequiredFolder(const wstring& p_InitialPath, wstring p_Requi

我有一个递归函数。它对驱动器内的第二个参数中给定名称的文件夹或第一个参数中给定名称的文件夹进行递归搜索。第二个参数中给出的文件夹可以位于第一个参数中给出的驱动器或文件夹中的任何路径和任何嵌套级别上。 所以函数浏览第一个参数中指定的驱动器或文件夹的所有内容,以查找第二个参数中指定的文件夹。下面是函数本身:

wstring FolderPathValidator::FindRequiredFolder(const wstring& p_InitialPath, wstring p_RequiredFolderName)
{
      wstring foundFolder = L"";
      wstring folderPath = p_InitialPath + L"\\*";
      WIN32_FIND_DATAW folderInfo;
      HANDLE search_handle = FindFirstFileW(folderPath.c_str(), &folderInfo);
      if (search_handle != INVALID_HANDLE_VALUE)
      {
           vector<wstring> folders;

           do
           {
                if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                     if ((!lstrcmpW(folderInfo.cFileName, L".")) || (!lstrcmpW(folderInfo.cFileName, L"..")))
                     continue;
                }

                folderPath = p_InitialPath + L"\\" + wstring(folderInfo.cFileName);

                if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                     if (folderInfo.cFileName == p_RequiredFolderName)
                     {
                          foundFolder = folderInfo.cFileName;
                          return foundFolder;
                     }
                     folders.push_back(folderPath);
                }
           } while (FindNextFileW(search_handle, &folderInfo));

           ::FindClose(search_handle);

           for (vector<wstring>::iterator iter = folders.begin(), end = folders.end(); iter != end; ++iter)
               FindRequiredFolder(*iter, p_RequiredFolderName);
      }

      return foundFolder;
}
但是,如果我将我的函数指向故意正确的方式(第二个参数中给出的文件夹存在的地方),它将返回一个空字符串。如何更正代码,使函数返回找到的文件夹

我添加了我一步一步地检入调试器,在那里我看到函数找到了所需的文件夹,但在其调用运算符中返回了一个空字符串。

尝试以下操作:

wstring FoundFolder = FindRequiredFolder(L"C:\\", L"TextFiles_to_Test");

您正在开始搜索“C:”驱动器的当前工作目录,而不是C:驱动器的根目录。

您的问题是,当您找到所需的文件夹名称时,返回的内容不正确-

if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
        if (folderInfo.cFileName == p_RequiredFolderName)
        {
            return folderPath;  // <-- return the found (fully qualified) path name
        }
        // else
        folders.push_back(folderPath);
}
if(folderInfo.dwFileAttributes&FILE\u ATTRIBUTE\u目录)
{
if(folderInfo.cFileName==p_RequiredFolderName)
{

return folderPath;//这将返回与
p_RequiredFolderName
匹配的第一个文件夹的完全限定路径。如果
p_RequiredFolderName
不存在,则返回空字符串:

wstring FindRequiredFolder(const wstring& p_InitialPath, const wstring& p_RequiredFolderName)
{
    wstring foundFolder;
    wstring searchSpec = p_InitialPath + L"\\*";
    WIN32_FIND_DATAW folderInfo;
    HANDLE search_handle = ::FindFirstFileW(searchSpec.c_str(), &folderInfo);
    if (search_handle != INVALID_HANDLE_VALUE){
        do{
            if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                if ((!lstrcmpW(folderInfo.cFileName, L".")) || (!lstrcmpW(folderInfo.cFileName, L"..")))
                    continue;

                wstring fullPath = p_InitialPath + L"\\" + folderInfo.cFileName;
                if (folderInfo.cFileName == p_RequiredFolderName){
                    foundFolder = fullPath;  // we're done.
                }
                else{
                    foundFolder = FindRequiredFolder(fullPath, p_RequiredFolderName);
                }
                if (foundFolder.length()){
                    break;
                }
            }
        } while (::FindNextFileW(search_handle, &folderInfo));

        ::FindClose(search_handle);
    }
    return foundFolder;
}

我在想我前面提到的关于返回第一个匹配文件夹的警告,所以我把它放在一起:

#define UNICODE
#define _UNICODE
#include <windows.h>
#include <vector>
#include <string>

// Find *all* folders in a directory tree with a given name.
// Params:
//    initialPath      location to start search
//    searchForName    name of folder to search for
//    locations        vector in which to put paths for any matches
//  Returns
//    vector containing all matches (if any).  Same as input parameter,
//    helps with performance on recursion (and also RVO).
std::vector<std::wstring> 
FindRequiredFolderLocations(const std::wstring& initialPath, 
                            const std::wstring& searchForName,
                            std::vector<std::wstring>& locations
                           )
{
    std::wstring searchSpec = initialPath + L"\\*";

    WIN32_FIND_DATA folderInfo;
    HANDLE search_handle = ::FindFirstFile(searchSpec.c_str(), &folderInfo);
    if (search_handle != INVALID_HANDLE_VALUE){
        do{
            if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                if ((!lstrcmp(folderInfo.cFileName, L".")) || (!lstrcmp(folderInfo.cFileName, L"..")))
                    continue;

                std::wstring fullPath = initialPath + L"\\" + folderInfo.cFileName;
                if (folderInfo.cFileName == searchForName){
                    locations.push_back(fullPath);
                }
                FindRequiredFolderLocations(fullPath, searchForName, locations);
            }
        } while (::FindNextFile(search_handle, &folderInfo));

        ::FindClose(search_handle);
    }
    return locations;
}

// Overload not requiring "locations" vector parameter (see above)
std::vector<std::wstring> 
FindRequiredFolderLocations(const std::wstring& initialPath, 
                            const std::wstring& folderName)
{
    std::vector<std::wstring> result;
    return FindRequiredFolderLocations(initialPath, folderName, result);
}

#ifdef TEST_FRFL
#include <iostream>
void FRFL_Test(const std::wstring& folderName)
{
    std::vector<std::wstring> locations;

    FindRequiredFolderLocations(L"C:",  folderName, locations);
    size_t count = locations.size();
    if (0 == count){
        std::wcout << L"Required folder not found.\n";
    }
    else if (1 == count){
        std::wcout << L"One location found: " << locations[0] << L"\n";
    }
    else{
        std::wcout << L"multiple locations found for required folder name:\n";
        for (auto loc : locations){
            std::wcout << L"\t" << loc.c_str() << L"\n";
        }
        std::wcout << L"Which one do you want?\n";
    }
}

int main()
{
    FRFL_Test(L"!!exists_1_Location");
    FRFL_Test(L"!!exists_several_Locations");
    FRFL_Test(L"!!exists_nowhere");

    return 0;
}

#endif
运行以下命令以创建测试目录:

C:\tmp>md-frfl
C:\tmp>md frfl\a
C:\tmp>md frfl\a\b
C:\tmp>md frfl\a\b\!!存在\u 1\u位置
C:\tmp>md frfl\a\!!存在多个位置
C:\tmp>md frfl\a\b\!!存在多个位置
C:\tmp>md frfl\!!存在多个位置
C:\tmp>md!!存在多个位置
输出:

C:\tmp>so findpathw
找到一个位置:C:\tmp\frfl\a\b\!!存在\u 1\u位置
找到所需文件夹名称的多个位置:
C:\tmp\!!存在多个位置
C:\tmp\frfl\!!存在多个位置
C:\tmp\frfl\a\!!存在多个位置
C:\tmp\frfl\a\b\!!存在多个位置
你想要哪一个?
找不到所需的文件夹。

我不知道你是否需要它,但无论它在目录树中的实际位置如何,找到任何与你要查找的目录基名称匹配的文件夹都会让我感到非常困扰。我有点痴迷于此。

不幸的是,这并没有帮助。我想到了这个对话框,但在客户的需求规范中说用户会从命令行输入文件夹名称。在关闭函数文件夹名称主体或文件夹完全限定路径名称的大括号之前,我必须返回什么?这没有帮助。如果返回路径,函数将返回当前选中的路径。但这是错误的。如果der不存在。如果执行此操作:int main(){std::wstring str=FindRequiredFolder(L“C:\\”,L“todolist”);wprintf(L“%s\n”,str.C\u str());返回0;}我得到以下信息:C:\tmp>so findpath C:\\bin\todolist请澄清您的期望。我需要以下信息。如果找到所需文件夹,函数必须返回此文件夹的完全限定路径。如果找不到所需文件夹,函数必须返回空字符串。@user3769902:乐意帮助。如果:这是您的答案打电话给我,它被接受了吗?这可能也很有用:。
wstring FindRequiredFolder(const wstring& p_InitialPath, const wstring& p_RequiredFolderName)
{
    wstring foundFolder;
    wstring searchSpec = p_InitialPath + L"\\*";
    WIN32_FIND_DATAW folderInfo;
    HANDLE search_handle = ::FindFirstFileW(searchSpec.c_str(), &folderInfo);
    if (search_handle != INVALID_HANDLE_VALUE){
        do{
            if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                if ((!lstrcmpW(folderInfo.cFileName, L".")) || (!lstrcmpW(folderInfo.cFileName, L"..")))
                    continue;

                wstring fullPath = p_InitialPath + L"\\" + folderInfo.cFileName;
                if (folderInfo.cFileName == p_RequiredFolderName){
                    foundFolder = fullPath;  // we're done.
                }
                else{
                    foundFolder = FindRequiredFolder(fullPath, p_RequiredFolderName);
                }
                if (foundFolder.length()){
                    break;
                }
            }
        } while (::FindNextFileW(search_handle, &folderInfo));

        ::FindClose(search_handle);
    }
    return foundFolder;
}
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <vector>
#include <string>

// Find *all* folders in a directory tree with a given name.
// Params:
//    initialPath      location to start search
//    searchForName    name of folder to search for
//    locations        vector in which to put paths for any matches
//  Returns
//    vector containing all matches (if any).  Same as input parameter,
//    helps with performance on recursion (and also RVO).
std::vector<std::wstring> 
FindRequiredFolderLocations(const std::wstring& initialPath, 
                            const std::wstring& searchForName,
                            std::vector<std::wstring>& locations
                           )
{
    std::wstring searchSpec = initialPath + L"\\*";

    WIN32_FIND_DATA folderInfo;
    HANDLE search_handle = ::FindFirstFile(searchSpec.c_str(), &folderInfo);
    if (search_handle != INVALID_HANDLE_VALUE){
        do{
            if (folderInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                if ((!lstrcmp(folderInfo.cFileName, L".")) || (!lstrcmp(folderInfo.cFileName, L"..")))
                    continue;

                std::wstring fullPath = initialPath + L"\\" + folderInfo.cFileName;
                if (folderInfo.cFileName == searchForName){
                    locations.push_back(fullPath);
                }
                FindRequiredFolderLocations(fullPath, searchForName, locations);
            }
        } while (::FindNextFile(search_handle, &folderInfo));

        ::FindClose(search_handle);
    }
    return locations;
}

// Overload not requiring "locations" vector parameter (see above)
std::vector<std::wstring> 
FindRequiredFolderLocations(const std::wstring& initialPath, 
                            const std::wstring& folderName)
{
    std::vector<std::wstring> result;
    return FindRequiredFolderLocations(initialPath, folderName, result);
}

#ifdef TEST_FRFL
#include <iostream>
void FRFL_Test(const std::wstring& folderName)
{
    std::vector<std::wstring> locations;

    FindRequiredFolderLocations(L"C:",  folderName, locations);
    size_t count = locations.size();
    if (0 == count){
        std::wcout << L"Required folder not found.\n";
    }
    else if (1 == count){
        std::wcout << L"One location found: " << locations[0] << L"\n";
    }
    else{
        std::wcout << L"multiple locations found for required folder name:\n";
        for (auto loc : locations){
            std::wcout << L"\t" << loc.c_str() << L"\n";
        }
        std::wcout << L"Which one do you want?\n";
    }
}

int main()
{
    FRFL_Test(L"!!exists_1_Location");
    FRFL_Test(L"!!exists_several_Locations");
    FRFL_Test(L"!!exists_nowhere");

    return 0;
}

#endif