遞歸遍歷目錄雖簡單但棧深度不可控,易棧溢出。本文給出基於 std::stack 的非遞歸實現,支持關鍵字搜索、批量重命名等場景。
FindFirstFile/FindNextFile)。WCHAR*,出棧時 free 釋放內存。typedef HRESULT (__stdcall *Callback)(HWND, BSTR, int); // 回調類型 std::stack<WCHAR*> dirStack; // 存目錄完整路徑指針
HRESULT SearchFiles(BSTR topDir, BSTR keyword, HWND hwnd, long cbAddr) {
Callback cb = (Callback)cbAddr;
if (!cb || !(GetFileAttributesW(topDir) & FILE_ATTRIBUTE_DIRECTORY))
return E_INVALIDARG;
// 頂層目錄本身匹配關鍵字
if (StrStrI(topDir, keyword)) {
cb(hwnd, topDir, 2); // 2=文件/匹配目錄
cb(hwnd, L"搜索完成", 0);
return S_OK;
}
WCHAR* first = (WCHAR*)calloc(MAX_PATH, sizeof(WCHAR));
lstrcpyW(first, topDir);
dirStack.push(first);
while (!dirStack.empty()) {
WCHAR* cur = dirStack.top(); dirStack.pop();
cb(hwnd, cur, 1); // 1=遍歷中目錄
WCHAR parent[MAX_PATH]; lstrcpyW(parent, cur);
if (cur[lstrlenW(cur)-1] != L'\\') lstrcatW(parent, L"\\");
lstrcatW(cur, L"*.*");
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(cur, &fd);
if (h != INVALID_HANDLE_VALUE) {
do {
if (wcscmp(fd.cFileName, L".")==0 || wcscmp(fd.cFileName, L"..")==0) continue;
WCHAR full[MAX_PATH];
lstrcpyW(full, parent);
lstrcatW(full, fd.cFileName);
if (StrStrI(fd.cFileName, keyword)) {
cb(hwnd, full, 2); // 匹配項
} else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
WCHAR* sub = (WCHAR*)calloc(MAX_PATH, sizeof(WCHAR));
lstrcpyW(sub, full);
dirStack.push(sub); // 子目錄入棧
}
} while (FindNextFile(h, &fd));
FindClose(h);
}
free(cur); // 釋放當前目錄路徑內存
}
cb(hwnd, L"搜索完成", 0);
return S_OK;
}
lstrcpyW/lstrcatW 配合 calloc 管理寬字符路徑內存。StrStrI 不區分大小寫搜索關鍵字。int type:1=遍歷目錄,2=匹配結果,0=完成。文中實際用於「批量給指定目錄下所有文件添加/修改/刪除前綴」,搜索邏輯與業務邏輯解耦,通過回調實現,極具擴展性。