2014-12-19 2 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

이 시도 : "C :"드라이브 -되지 않은 C의 루트 디렉토리 : 당신은에 대한 현재 작업 디렉토리 무엇이든에 검색 시작

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

드라이브를.

+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 

이것은 문제 일 수 있습니다.
또한 시간이 꽤 걸립니다. 나는 c:\tmp에서 방금 만든 foo1219을 찾았는데 시간이 좀 걸렸다. (휴지통, 문서, 프로그램 파일 등은 모두 값 비싸다.) 이에 대한 사용자 인터페이스가있는 경우 대화 상자를 사용하여 사용자가 폴더를 선택할 수 있습니다. 공통 대화 상자 파일 대화 상자는 매우 유용 할 수 있습니다.

+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 

빌드 :

0 :

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. 

당신이 필요합니다 알고 있지만하지 마십시오 당신이 실제로 트리에서의 위치에 관계없이 찾고있는 기본 이름 디렉토리를 일치하는 폴더를 찾아 정말 저를 괴롭혔습니다. 나는 그런 식의 강박 관념이있다.

관련 문제