目錄的枚舉非遞歸實現

目錄的枚舉經常用到,但是大家大多數用遞歸就能解決問題,但是在某些環境,內存受到限制情況下,遞歸就回佔用大量內存,導致程序崩潰,那麼這個時候怎麼辦?

使用非遞歸!把遞歸轉爲非遞歸

  • 目錄的遞歸訪問轉爲非遞歸訪問.以windows 爲例:
  • 枚舉目錄需要一個路徑
  • 繼續訪問需要上次訪問目錄的句柄
    • 遇到目錄,將新目錄追加上;保存原來的句柄
    • 退回上一級,根據\,將目錄退一層;將原來句柄取回來
  • 思路就是這樣,代碼呈上:
// enum_dir.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <Windows.h>
#include <deque>
#include <string>
std::deque<HANDLE> h_stack;
void push_path(TCHAR* path, const TCHAR* sub_path)
{
    while (*path)
    {
        ++path;
    }
    *path = L'\\';
    ++path;

    while (*sub_path)
    {
        *path++ = *sub_path++;
    }
    *path = 0;
}
void pop_path(TCHAR* path)
{
    while (*path)
    {
        ++path;
    }
    path--;
    while (*path != _T('\\'))
    {
        --path;
    }
    *path = 0;
}

void test(wchar_t* path)
{
    WIN32_FIND_DATA d = {};
    HANDLE h;
    BOOL b = TRUE;
    std::wstring str = path;

    while (1)
    {
        //目錄枚舉開始
    start:
        str = path;
        str += L"\\*";
        h = FindFirstFile(str.data(), &d);
        if (h)
        {
            while (1)
            {
                if (!(wcscmp(d.cFileName, L".") == 0 || wcscmp(d.cFileName, L"..") == 0))
                {
                    if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                    {
                        //路徑追加,繼續枚舉
                        push_path(path, d.cFileName);
                        //保留句柄,恢復時候使用
                        h_stack.push_back(h);
                        //繼續枚舉新目錄
                        goto start;
                    }
                    else
                    {
                        //文件
                        wchar_t buf[512] = {};
                        wsprintf(buf, L"path:%s:%s\n", path, d.cFileName);
                        OutputDebugStringW(buf);
                    }
                }
                //讀取下一個文件
            read_content:
                memset(&d, 0, sizeof(d));
                b = FindNextFile(h, &d);
                if (!b)
                {
                    //這一遭結束,回到上一遭
                    FindClose(h);
                    if (h_stack.size())
                    {
                        h = *h_stack.rbegin();
                        h_stack.pop_back();
                        pop_path(path);
                        //環境已經恢復繼續枚舉
                        goto read_content;
                    }
                    //否則,game over
                    goto gameover;
                }
            }
        }
    }
gameover:
    return;
}

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t buf[260] = { 0 };
    wcscpy(buf, L"c:\\test");
    test(buf);
    return 0;
}

嵌入式中使用fatfs 的時候,也有這樣的情況,可以試一下解決空間佔用問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章