TraverseDirecory--关于递归函数的内存控制

soulmachine 2008-11-23 05:28:59
一直在想,为什么WIN32没有提供遍历目录之类的函数(不要说FindFirstFile,FindNextFile,它们显得还不够易用),于是我设计了一个TraverseDirectory,碰到了一个问题,先看看代码:
/**
* @brief 遍历一个目录下的所有文件,可递归子目录
* @author soulmachine@gmail.com
* @param[in] pszDirPath 目录的路径,末尾没有'\'
* @param[in] pszFilterPostfix 过滤后缀,如"\\*.*", "\\*.jpg"
* @param[in] bRecursive 是否递归子目录
* @param[in] pfnProcessFile 回调函数指针,用于处理单个文件
* @param[out] pParameter 传递给pfnProcessFile 的参数
* @return 返回文件总数,失败返回-1, 一般失败只发生在第一次 FindFirstFile。
* @note 本函数主要用FindFirstFile,FindNextFile实现。
* @remarks 本函数是用递归版本
*/
int TraverseDirectory(PCTSTR pszDirPath, PCTSTR pszFilterPostfix,
const BOOL bRecursive, int (*pfnProcessFile) \
(PCTSTR pszFilePath, PVOID pParameter), PVOID pParameter)
{
static int nFileCount = 0; //文件总数

WIN32_FIND_DATA findFileData; //保存当前找到的文件的属性
HANDLE hFind = INVALID_HANDLE_VALUE; //FindFirstFile返回的句柄
//当层函数的扫描路径,文件绝对路径或下层函数的目录路径
TCHAR szDirPath[MAX_PATH];

(void)_tcscpy(szDirPath,pszDirPath);
(void)_tcscat(szDirPath, pszFilterPostfix);

hFind = FindFirstFile(szDirPath, &findFileData);
if(INVALID_HANDLE_VALUE == hFind)
{
// FindFirstFile失败的原因:
// 文件夹是坏的
// 没有权限
nFileCount = -1;
ERROR_RETURN(FindFirstFile_Failed);
}

do
{
(void)_sntprintf(szDirPath, (size_t)MAX_PATH, TEXT("%s\\%s"), pszDirPath, findFileData.cFileName);
//如果不是目录
if((DWORD)0 == (findFileData.dwFileAttributes & (DWORD)FILE_ATTRIBUTE_DIRECTORY))
{
nFileCount++;
if(NULL != pfnProcessFile)
{
(void)pfnProcessFile(szDirPath, pParameter);
}
}
//如果是目录,但不是.和..,递归
else if(bRecursive && (findFileData.cFileName[0] != TEXT('.')))
{
(void)TraverseDirectory(szDirPath, pszFilterPostfix, bRecursive, pfnProcessFile, pParameter);
}
else
{
//是.和.. 则什么也不做
}
} while (FALSE != FindNextFile(hFind,&findFileData));

(void)FindClose(hFind);

FindFirstFile_Failed:

return nFileCount;
}


我要问的问题是,递归函数的参数,有的是一直不变的,有的是经常变的,比如这里的pszDirPath,每一层调用都不同,而pszFilterPostfix, bRecursive,pfnProcessFile在所有递归层次中都是相同的,但是它们依然占用了一个形参的位置,至少4个字节的空间,每次递归都要为这三个参数分配栈空间,如果递归层次深,这三个参数占用的内存其实是很可观的。
我想到的唯一节省内存的方式是将不经产变的参数合并到一个结构体中,比如,

typedef struct tagPARAMETER
{
PCTSTR pszFilterPostfix;
BOOL bRecursive;
int (*pfnProcessFile) (PCTSTR pszFilePath, PVOID pParameter);
};


这样,原本占三个位置的形参,只占一个了,是原来的1/3。
大家对于“不变”和“易变”的参数是怎么处理的?对于递归函数,有没有更好的办法来节省内存?
...全文
57 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
goldencode 2008-12-05
  • 打赏
  • 举报
回复
使用结构体并没有减少栈的使用啊?传的是结构体的指针? 其实那个所谓变的参数也可以传指针啊, 字符串本身是需要保存的,可以保存在任何地方,没有问题.
pushregistration 2008-11-23
  • 打赏
  • 举报
回复
ding
android2008 2008-11-23
  • 打赏
  • 举报
回复
ding
soulmachine 2008-11-23
  • 打赏
  • 举报
回复
我个人觉得将“不变”的参数个并的方案比较ugly,如果每一个递归函数都有一个自己的形参结构体,那么可能会出现代码中结构体满天飞的现象,这是我不愿看到的
soulmachine 2008-11-23
  • 打赏
  • 举报
回复
讨论的范围仅限于纯C(pure C),WIN32,不要搬出C++,.NET之类的方案。

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧