2014-12-19 81 views
0

我有一個遞歸函數。它執行文件夾的遞歸搜索,在驅動器或文件夾中的第二個參數中給出名稱,該名稱在第一個參數中給出。在第二個參數中給出的文件夾可以定位在第一個參數中給出的驅動器或文件夾內的任何路徑和任何嵌套級別。 因此,功能瀏覽第一個參數中指定的驅動器或文件夾的所有內容,以查找第二個參數中指定的文件夾。下面是函數本身:遞歸函數不返回正確的值

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"); 

但是,如果我直接把我的功能,明知正確的方式(其中第二個參數給出的文件夾是否存在)它返回一個空字符串。我應該如何更正代碼,以便函數返回找到的文件夾。

我補充一點,我一步一步地檢查調試器,在那裏我看到該函數找到需要的文件夾,但在其調用操作符中返回一個空字符串。

回答

2

試試這個:

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

你開始搜索在任何針對該當前工作目錄「C:」驅動器 - 而不是C的目錄:驅動器。

+0

不幸的是,它並沒有幫助。 – user3769902

0

你的問題是,你當你到所需的文件夾名稱沒有返回正確的事情 -

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); 
} 

你可能有這種方法的幾個問題,但(你可能已經考慮到了這些) : 首先,這將返回第一個匹配,無論它出現在樹中的哪個位置。考慮:

 
    c:\a\system 
    c:\windows\system 
    c:\tmp\system 

這可能是一個問題給你。
此外,它需要一段時間。我尋找foo1219,我剛剛在c:\tmp中創建了它,並花了一段時間(回收站,文檔,程序文件等等,都是昂貴的)。如果您有任何用戶界面,您可能需要使用對話框並讓用戶選擇一個文件夾。常用對話框「文件」對話框可能非常有用。

+0

我回答關於對話框,但在客戶的需求說明中說,用戶將從命令行輸入文件夾名稱。 – user3769902

+0

在關閉函數文件夾名稱或完全限定路徑名稱到文件夾的正文的大括號之前,必須返回哪些內容? – user3769902

+0

它沒有幫助。在返回路徑的情況下,該函數返回當前檢查的路徑。但這是錯誤的。如果該文件夾不存在,該函數必須返回所需的文件夾路徑或空字符串。 – user3769902

0

這將返回匹配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; 
} 
+0

@ user3769902:很樂意提供幫助。如果這個:http://stackoverflow.com/questions/27568785/recursive-function-doesnt-return-correct-value/27573447#27573447是你給我的答案,是否接受?這可能也是有用的:http://stackoverflow.com/questions/27568785/recursive-function-doesnt-return-correct-value/27584344#27584344。 – frasnian

0

我在想是警告我前面關於返回第一個匹配的文件夾提到,所以我把這個在一起:

#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>cl /nologo /EHsc /W4 /DTEST_FRFL so-findpathw.cpp 

運行以下命令來創建測試目錄:

C:\tmp>md frfl 
C:\tmp>md frfl\a 
C:\tmp>md frfl\a\b 
C:\tmp>md frfl\a\b\!!exists_1_Location 
C:\tmp>md frfl\a\!!exists_several_Locations 
C:\tmp>md frfl\a\b\!!exists_several_Locations 
C:\tmp>md frfl\!!exists_several_Locations 
C:\tmp>md !!exists_several_Locations 

輸出:

C:\tmp>so-findpathw 
One location found: C:\tmp\frfl\a\b\!!exists_1_Location 
multiple locations found for required folder name: 
     C:\tmp\!!exists_several_Locations 
     C:\tmp\frfl\!!exists_several_Locations 
     C:\tmp\frfl\a\!!exists_several_Locations 
     C:\tmp\frfl\a\b\!!exists_several_Locations 
Which one do you want? 
Required folder not found. 

不知道你需要這一點,但發現基本名稱你的地方實際上是位於樹尋找無論目錄匹配的任何文件夾只是真的困擾我。我有點迷戀。