首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Win32 非遞歸遍歷文件目錄:棧模擬遞歸與回調機制

     編輯:C++ 入門

Win32 非遞歸遍歷文件目錄:棧模擬遞歸與回調機制

遞歸遍歷目錄雖簡單但棧深度不可控,易棧溢出。本文給出基於 std::stack 的非遞歸實現,支持關鍵字搜索、批量重命名等場景。

核心算法流程

  1. 頂層目錄入棧。
  2. 循環:棧非空則取頂目錄出棧,遍歷該目錄下所有文件/子目錄(FindFirstFile/FindNextFile)。
  3. 遇到子目錄:若匹配關鍵字則回調通知,否則入棧待後續處理。
  4. 遇到文件:匹配關鍵字則回調通知。
  5. 棧元素存 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=完成。
  • 非遞歸本質:顯式棧存儲待處理目錄,邏輯與遞歸完全等價。

應用場景

文中實際用於「批量給指定目錄下所有文件添加/修改/刪除前綴」,搜索邏輯與業務邏輯解耦,通過回調實現,極具擴展性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved