核心函數 find
void find(char* lpPath)
{
char szFind[MAX_PATH];
WIN32_FIND_DATA FindFileData;
strcpy(szFind, lpPath);
strcat(szFind, "*.*");
HANDLE hFind = ::FindFirstFile(szFind, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE) return;
while (TRUE)
{
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// 跳過 "." 與 ".."
if (FindFileData.cFileName[0] != '.')
{
char szFile[MAX_PATH];
strcpy(szFile, lpPath);
strcat(szFile, "\\");
strcat(szFile, FindFileData.cFileName);
find(szFile); // 遞迴進入子目錄
}
}
else
{
// 輸出檔案名稱
cout << FindFileData.cFileName << endl;
}
if (!FindNextFile(hFind, &FindFileData)) break;
}
FindClose(hFind);
}
關鍵點說明
- 使用
FindFirstFile/FindNextFile/FindClose 三部曲。
FILE_ATTRIBUTE_DIRECTORY 判斷目錄。
- 檢查
cFileName[0] != '.' 排除當前目錄 (.) 與父目錄 (..)。
- 路徑拼接時補上反斜線
\\。
- 遞迴呼叫
find(szFile) 處理子目錄。
改進建議
- 改用
std::string 或 CString 避免緩衝區溢位。
- 加入錯誤處理與長路徑支援 (
\\?\ 前綴)。
- 若需收集結果,可傳入
std::vector<std::string>& 參數。
- 考慮使用
CFileFind (MFC) 或 std::filesystem (C++17) 簡化程式碼。
MFC 版本參考
void FindFiles(const CString& strPath, CStringArray& arrFiles)
{
CFileFind finder;
BOOL bWorking = finder.FindFile(strPath + _T("\\*.*"));
while (bWorking)
{
bWorking = finder.FindNextFile();
if (finder.IsDots()) continue;
if (finder.IsDirectory())
FindFiles(finder.GetFilePath(), arrFiles);
else
arrFiles.Add(finder.GetFilePath());
}
finder.Close();
}