자료구조, 알고리즘

연결리스트 큐 이용 파일 탐색,,, No 재귀호출

디버그정 2009. 11. 12. 08:12

스택이나 큐를 사용하면 재귀함수를 non재귀함수로 만들 수 있다.
이전에는 스택을 이용하여 html 소스를 추출하는 것을 만들어 보았다.
이번에는 큐를 사용하여 파일을 찾는 함수를 작성해 보았다.
(이재규 c++ 알고리즘도 좀 참고했다.)
연결리스트 자체가 이미 큐로서 충분히 기능할 수 있으므로 별도의 큐 클래스를 만들지 않았다.
큐 클래스로 별도로 구성하면  아무래도 쓸데없는 부분까지 구성해야 하므로 더 번거로운 작업이 될 수 있다.
단순 연결리스트를 생성하고 큐의 put, get 등 기본적 개념을 이용하였다.


// 큐를 이용해 Non Recursive 함수로 구성해 봄.
// 큐의 경우 FIFO 구조이므로 상위디렉부터 검사하고 하위로 차근차근 검사해나가는 파일탐색에 적용할 수 있다.
// 트리의 level traverse와 유사한 구조이다.
DWORD __stdcall FindFile(LPCTSTR lpszMask, LPCTSTR lpszDir)
{
 struct Node{
  TCHAR szDir[2048];
  Node *pNext;
 };
 Node *pFront=NULL, *pRear=NULL, *pNew=NULL, *pTemp=NULL;
 TCHAR szFind[2048]={0}, szFilePath[2048]={0};
 HANDLE hFind;
 WIN32_FIND_DATA wfd={0};
 DWORD dwFileCount=0;


 // 첫번째 요소 put
 pFront=(Node*)malloc(sizeof(Node));
 if(!pFront){
  MessageBox(NULL, _T("Node 메모리 할당이 실패하였습니다."), _T("에러"), MB_ICONERROR|MB_TOPMOST);
  return 0;
 }
 lstrcpy(pFront->szDir, lpszDir);
 // 디렉토리 문자열 수정: 뒤에 \ 없으면 붙여준다.
 if((pFront->szDir)[lstrlen(pFront->szDir)-1]!='\\') lstrcat(pFront->szDir, _T("\\"));
 pFront->pNext=NULL;
 pRear=pFront;


 ////// 큐를 이용해 노재귀 형태로 구성 가능하다.
 ////// pFront가 NULL이면 큐가 빈 상태이므로 벗어난다.
 while(pFront){
  // 마스크 이용해 파일을 찾는다.
  lstrcpy(szFind, pFront->szDir); // 이미 디렉토리 뒤에 \가 붙여진 상태이다.
  lstrcat(szFind, lpszMask);
  if(INVALID_HANDLE_VALUE != (hFind=FindFirstFile(szFind, &wfd))){
   do{
    // 검색된 파일 처리... ex) 리스트뷰와 연계해서 각 행마다 입력 등등,,,
    lstrcpy(szFilePath, pFront->szDir);
    lstrcat(szFilePath, wfd.cFileName);
    MessageBox(0, szFilePath, _T("found"), 0);
    ++dwFileCount;

   }while(FindNextFile(hFind, &wfd));
   FindClose(hFind);
  }


  // 디렉토리를 구한 후 put한다.
  lstrcpy(szFind, pFront->szDir);
  lstrcat(szFind, _T("*.*"));
  if(INVALID_HANDLE_VALUE != (hFind=FindFirstFile(szFind, &wfd))){
   do{
    if(lstrcmpi(wfd.cFileName, _T(".")) && lstrcmpi(wfd.cFileName, _T("..")) && (wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)){
     // put한다.
     if(pNew=(Node*)malloc(sizeof(Node))){
      wsprintf(pNew->szDir, _T("%s%s\\"), pFront->szDir, wfd.cFileName); // \를 뒤에 붙여준다.
      pNew->pNext=NULL;
      pRear->pNext=pNew;
      pRear=pNew;
     } else {
      MessageBox(NULL, _T("Node 메모리 할당이 실패하였습니다."), _T("에러"), MB_ICONERROR|MB_TOPMOST);
     }
    }
   }while(FindNextFile(hFind, &wfd));
   FindClose(hFind);
  }


  // front 삭제
  pTemp=pFront;
  if(pFront->pNext){pFront=pFront->pNext;}
  else{pFront=NULL;} // 넥스트가 없는 경우 큐가 빈 상태이다. pFront=NULL로 이를 나타낸다.
  free(pTemp);
 }

 return dwFileCount;
}