|
-
Jan 5th, 2003, 08:14 PM
#1
Avoiding recursion at all costs?
For once a question from me 
I'm writing a file search algorithm that searches every physical fixed drive and every network drive including all subdirectories for a filename. Although there is a shell function that brings up the file search box of Explorer, there seems to be no function to do this programmatically, neither in the shell nor in the file I/O functions.
The problem I have is: the function that searches the directory tree could either be recursive (shiver) or use some kind of loop and an array to simulate the recursion.
The tree-nature of directories requires two loops: one that walks into the depth of the tree and another that walks the directory siblings. The sibling-walker is the inner loop. The problem is that I can't use continue or break (or something like that) from within the inner loop to act on the outer loop. As I don't want to have cryptic continue flags the only way that seems left to me is using goto (*shiver again*).
Here's my code (MFC, but a lot of API access).
CList is a templated linked list. CStringList is equivalent to a specialization of CList for CString.
CFileFind is a class that encapsulates the API WIN32_FIND_DATA, FindFirstFile and FindNextFile.
Code:
bool CJBStarterApp::SearchTree(const CString & strInitDir,
const CString & strFilename, CString & strOut)
{
// Uses a freaky goto to avoid recursiveness.
// Makes you wonder...
CStringList lsStack;
CList<CFileFind *, CFileFind *> lpffStack;
CFileFind *pCurrentFF = NULL;
CString strCurDir(strInitDir);
recur:
pCurrentFF = new CFileFind();
::SetCurrentDirectory(strCurDir);
if(pCurrentFF->FindFile(strFilename))
{
pCurrentFF->FindNextFile();
strOut = pCurrentFF->GetFilePath();
// Unroll stack and return
delete pCurrentFF;
while(!lpffStack.IsEmpty())
delete lpffStack.RemoveHead();
return true;
}
pCurrentFF->FindFile();
while(pCurrentFF->FindNextFile())
{
if(pCurrentFF->IsDirectory())
{
lpffStack.AddHead(pCurrentFF);
lsStack.AddHead(strCurDir);
strCurDir = pCurrentFF->GetFilePath();
goto recur;
cont:
delete pCurrentFF;
pCurrentFF = lpffStack.RemoveHead();
strCurDir = lsStack.RemoveHead();
::SetCurrentDirectory(strCurDir);
}
}
if(lpffStack.IsEmpty())
return false;
goto cont;
}
I believe it should work (haven't tried yet), but I'm not sure and that's a bad sign. If I'm not able to follow program flow right after I've written the app then this can't be good.
I welcome any ideas on restructuring this code to make it more readable. I welcome any reference to an API function that does this even more.
Thanks in advance.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|